Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(complete)!: Shuffle API up for stabilization #5681

Merged
merged 5 commits into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions clap_complete/examples/dynamic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ fn command() -> clap::Command {
.value_parser(["json", "yaml", "toml"]),
)
.args_conflicts_with_subcommands(true);
clap_complete::dynamic::CompleteCommand::augment_subcommands(cmd)
clap_complete::CompleteCommand::augment_subcommands(cmd)
}

fn main() {
clap_complete::dynamic::CompleteEnv::with_factory(command).complete();
clap_complete::CompleteEnv::with_factory(command).complete();

let cmd = command();
let matches = cmd.get_matches();
if let Ok(completions) = clap_complete::dynamic::CompleteCommand::from_arg_matches(&matches) {
if let Ok(completions) = clap_complete::CompleteCommand::from_arg_matches(&matches) {
completions.complete(&mut command());
} else {
println!("{matches:#?}");
Expand Down
6 changes: 3 additions & 3 deletions clap_complete/examples/exhaustive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use clap_complete::{generate, Generator, Shell};

fn main() {
#[cfg(feature = "unstable-dynamic")]
clap_complete::dynamic::CompleteEnv::with_factory(cli).complete();
clap_complete::CompleteEnv::with_factory(cli).complete();

let matches = cli().get_matches();
if let Some(generator) = matches.get_one::<Shell>("generate") {
Expand All @@ -16,7 +16,7 @@ fn main() {
}

#[cfg(feature = "unstable-command")]
if let Ok(completions) = clap_complete::dynamic::CompleteCommand::from_arg_matches(&matches) {
if let Ok(completions) = clap_complete::CompleteCommand::from_arg_matches(&matches) {
completions.complete(&mut cli());
return;
};
Expand Down Expand Up @@ -199,6 +199,6 @@ fn cli() -> clap::Command {
]),
]);
#[cfg(feature = "unstable-command")]
let cli = clap_complete::dynamic::CompleteCommand::augment_subcommands(cli);
let cli = clap_complete::CompleteCommand::augment_subcommands(cli);
cli
}
56 changes: 56 additions & 0 deletions clap_complete/src/aot/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//! Prebuilt completions
//!
//! ## Quick Start
//!
//! - For generating at compile-time, see [`generate_to`]
//! - For generating at runtime, see [`generate`]
//!
//! [`Shell`] is a convenience `enum` for an argument value type that implements `Generator`
//! for each natively-supported shell type.
//!
//! To customize completions, see
//! - [`ValueHint`]
//! - [`ValueEnum`][clap::ValueEnum]
//!
//! ## Example
//!
//! ```rust,no_run
//! use clap::{Command, Arg, ValueHint, value_parser, ArgAction};
//! use clap_complete::{generate, Generator, Shell};
//! use std::io;
//!
//! fn build_cli() -> Command {
//! Command::new("example")
//! .arg(Arg::new("file")
//! .help("some input file")
//! .value_hint(ValueHint::AnyPath),
//! )
//! .arg(
//! Arg::new("generator")
//! .long("generate")
//! .action(ArgAction::Set)
//! .value_parser(value_parser!(Shell)),
//! )
//! }
//!
//! fn print_completions<G: Generator>(gen: G, cmd: &mut Command) {
//! generate(gen, cmd, cmd.get_name().to_string(), &mut io::stdout());
//! }
//!
//! fn main() {
//! let matches = build_cli().get_matches();
//!
//! if let Some(generator) = matches.get_one::<Shell>("generator").copied() {
//! let mut cmd = build_cli();
//! eprintln!("Generating completion file for {generator}...");
//! print_completions(generator, &mut cmd);
//! }
//! }
//! ```

mod generator;
mod shells;

pub use clap::ValueHint;
pub use generator::*;
pub use shells::*;
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@ impl Generator for Bash {

let fn_name = bin_name.replace('-', "__");

w!(
write!(
buf,
format!(
"_{name}() {{
"_{name}() {{
local i cur prev opts cmd
COMPREPLY=()
cur=\"${{COMP_WORDS[COMP_CWORD]}}\"
Expand Down Expand Up @@ -66,15 +65,13 @@ else
complete -F _{name} -o bashdefault -o default {name}
fi
",
name = bin_name,
cmd = fn_name,
name_opts = all_options_for_path(cmd, bin_name),
name_opts_details = option_details_for_path(cmd, bin_name),
subcmds = all_subcommands(cmd, &fn_name),
subcmd_details = subcommand_details(cmd)
)
.as_bytes()
);
name = bin_name,
cmd = fn_name,
name_opts = all_options_for_path(cmd, bin_name),
name_opts_details = option_details_for_path(cmd, bin_name),
subcmds = all_subcommands(cmd, &fn_name),
subcmd_details = subcommand_details(cmd)
).expect("failed to write completion file");
}
}

Expand Down Expand Up @@ -274,22 +271,23 @@ fn all_options_for_path(cmd: &Command, path: &str) -> String {

let mut opts = String::new();
for short in utils::shorts_and_visible_aliases(p) {
write!(&mut opts, "-{short} ").unwrap();
write!(&mut opts, "-{short} ").expect("writing to String is infallible");
}
for long in utils::longs_and_visible_aliases(p) {
write!(&mut opts, "--{long} ").unwrap();
write!(&mut opts, "--{long} ").expect("writing to String is infallible");
}
for pos in p.get_positionals() {
if let Some(vals) = utils::possible_values(pos) {
for value in vals {
write!(&mut opts, "{} ", value.get_name()).unwrap();
write!(&mut opts, "{} ", value.get_name())
.expect("writing to String is infallible");
}
} else {
write!(&mut opts, "{pos} ").unwrap();
write!(&mut opts, "{pos} ").expect("writing to String is infallible");
}
}
for (sc, _) in utils::subcommands(p) {
write!(&mut opts, "{sc} ").unwrap();
write!(&mut opts, "{sc} ").expect("writing to String is infallible");
}
opts.pop();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ impl Generator for Elvish {

let subcommands_cases = generate_inner(cmd, "");

let result = format!(
write!(
buf,
r#"
use builtin;
use str;
Expand All @@ -46,9 +47,8 @@ set edit:completion:arg-completer[{bin_name}] = {{|@words|
$completions[$command]
}}
"#,
);

w!(buf, result.as_bytes());
)
.expect("failed to write completion file");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ impl Generator for Fish {
needs_fn_name,
using_fn_name,
);
w!(buf, buffer.as_bytes());
write!(buf, "{buffer}").expect("failed to write completion file");
}
}

Expand Down Expand Up @@ -240,7 +240,9 @@ fn gen_subcommand_helpers(
}
}
let optspecs_fn_name = format!("__fish_{bin_name}_global_optspecs");
let template = format!("\
write!(
buf,
"\
# Print an optspec for argparse to handle cmd's options that are independent of any subcommand.\n\
function {optspecs_fn_name}\n\
\tstring join \\n{optspecs}\n\
Expand All @@ -264,8 +266,7 @@ fn gen_subcommand_helpers(
\tand return 1\n\
\tcontains -- $cmd[1] $argv\n\
end\n\n\
");
w!(buf, template.as_bytes());
").expect("failed to write completion file");
}

fn value_completion(option: &Arg) -> String {
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ impl Generator for PowerShell {

let subcommands_cases = generate_inner(cmd, "");

let result = format!(
write!(
buf,
r#"
using namespace System.Management.Automation
using namespace System.Management.Automation.Language
Expand Down Expand Up @@ -51,9 +52,8 @@ Register-ArgumentCompleter -Native -CommandName '{bin_name}' -ScriptBlock {{
Sort-Object -Property ListItemText
}}
"#
);

w!(buf, result.as_bytes());
)
.expect("failed to write completion file");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@ impl Generator for Zsh {
.get_bin_name()
.expect("crate::generate should have set the bin_name");

w!(
write!(
buf,
format!(
"#compdef {name}
"#compdef {name}

autoload -U is-at-least

Expand All @@ -49,13 +48,12 @@ else
compdef _{name} {name}
fi
",
name = bin_name,
initial_args = get_args_of(cmd, None),
subcommands = get_subcommands_of(cmd),
subcommand_details = subcommand_details(cmd)
)
.as_bytes()
);
name = bin_name,
initial_args = get_args_of(cmd, None),
subcommands = get_subcommands_of(cmd),
subcommand_details = subcommand_details(cmd)
)
.expect("failed to write completion file");
}
}

Expand Down Expand Up @@ -673,7 +671,7 @@ fn write_positionals_of(p: &Command) -> String {

#[cfg(test)]
mod tests {
use crate::shells::zsh::{escape_help, escape_value};
use super::{escape_help, escape_value};

#[test]
fn test_escape_value() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ pub use shells::*;

/// A completion subcommand to add to your CLI
///
/// To customize completions, see
/// - [`ValueHint`][crate::ValueHint]
/// - [`ValueEnum`][clap::ValueEnum]
/// - [`ArgValueCompleter`][crate::ArgValueCompleter]
///
/// **Warning:** `stdout` should not be written to before [`CompleteCommand::complete`] has had a
/// chance to run.
///
Expand All @@ -55,7 +60,7 @@ pub use shells::*;
/// ```no_run
/// // src/main.rs
/// use clap::{CommandFactory, FromArgMatches, Parser, Subcommand};
/// use clap_complete::dynamic::CompleteCommand;
/// use clap_complete::CompleteCommand;
///
/// #[derive(Parser, Debug)]
/// #[clap(name = "dynamic", about = "A dynamic command line tool")]
Expand Down Expand Up @@ -113,6 +118,11 @@ impl CompleteCommand {

/// A completion subcommand to add to your CLI
///
/// To customize completions, see
/// - [`ValueHint`][crate::ValueHint]
/// - [`ValueEnum`][clap::ValueEnum]
/// - [`ArgValueCompleter`][crate::ArgValueCompleter]
///
/// **Warning:** `stdout` should not be written to before [`CompleteArgs::complete`] has had a
/// chance to run.
///
Expand All @@ -122,7 +132,7 @@ impl CompleteCommand {
/// ```no_run
/// // src/main.rs
/// use clap::{CommandFactory, FromArgMatches, Parser, Subcommand};
/// use clap_complete::dynamic::CompleteArgs;
/// use clap_complete::CompleteArgs;
///
/// #[derive(Parser, Debug)]
/// #[clap(name = "dynamic", about = "A dynamic command line tool")]
Expand Down
17 changes: 2 additions & 15 deletions clap_complete/src/dynamic/mod.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,12 @@
//! Complete commands within shells
//! `clap`-native completion system
//!
//! To customize completions, see
//! - [`ValueHint`][crate::ValueHint]
//! - [`ValueEnum`][clap::ValueEnum]
//! - [`ArgValueCompleter`]
//! See [`complete()`]

mod candidate;
mod complete;
mod custom;

#[cfg(feature = "unstable-command")]
pub mod command;
pub mod env;

pub use candidate::CompletionCandidate;
pub use complete::complete;
pub use custom::ArgValueCompleter;
pub use custom::CustomCompleter;

#[cfg(feature = "unstable-command")]
pub use command::CompleteArgs;
#[cfg(feature = "unstable-command")]
pub use command::CompleteCommand;
pub use env::CompleteEnv;
Loading
Loading