From 59270b1c811b923db6536bfe845d80847a430038 Mon Sep 17 00:00:00 2001 From: Martin von Zweigbergk Date: Tue, 27 Sep 2022 09:13:00 -0700 Subject: [PATCH 01/10] fix(complete): Make example commands match binary The example binaries were renamed in 89c2b3bb0d88, but the commands in them were not, making the generated completion scripts not work (because we use the command name as binary name in the examples). --- clap_complete/examples/completion-derive.rs | 2 +- clap_complete/examples/completion.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clap_complete/examples/completion-derive.rs b/clap_complete/examples/completion-derive.rs index bbaaf25fa46..3665be3a00b 100644 --- a/clap_complete/examples/completion-derive.rs +++ b/clap_complete/examples/completion-derive.rs @@ -19,7 +19,7 @@ use std::io; use std::path::PathBuf; #[derive(Parser, Debug, PartialEq)] -#[command(name = "value_hints_derive")] +#[command(name = "completion-derive")] struct Opt { /// If provided, outputs the completion file for given shell #[arg(long = "generate", value_enum)] diff --git a/clap_complete/examples/completion.rs b/clap_complete/examples/completion.rs index cf3d315a9f1..fac64aa2b69 100644 --- a/clap_complete/examples/completion.rs +++ b/clap_complete/examples/completion.rs @@ -17,7 +17,7 @@ use clap_complete::{generate, Generator, Shell}; use std::io; fn build_cli() -> Command { - Command::new("value_hints") + Command::new("completion") .arg( Arg::new("generator") .long("generate") From 8b33da3138f24c6dd9f103a61746869686f72f28 Mon Sep 17 00:00:00 2001 From: Martin von Zweigbergk Date: Tue, 27 Sep 2022 21:25:14 -0700 Subject: [PATCH 02/10] fix(complete): Make the two examples consistent The derive-based example has a `///` comment on one argument, which ends up as a description for the argument in the generated completion scripts. Let's switch to `//` so the two scripts produce the same output (except for the binary name), so they're easy to compare. --- clap_complete/examples/completion-derive.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clap_complete/examples/completion-derive.rs b/clap_complete/examples/completion-derive.rs index 3665be3a00b..ff5e8b85da3 100644 --- a/clap_complete/examples/completion-derive.rs +++ b/clap_complete/examples/completion-derive.rs @@ -21,7 +21,7 @@ use std::path::PathBuf; #[derive(Parser, Debug, PartialEq)] #[command(name = "completion-derive")] struct Opt { - /// If provided, outputs the completion file for given shell + // If provided, outputs the completion file for given shell #[arg(long = "generate", value_enum)] generator: Option, // Showcasing all possible ValueHints: From 6bc8d2632c6e9e7aef2d815a82497e6970aad209 Mon Sep 17 00:00:00 2001 From: Martin von Zweigbergk Date: Tue, 27 Sep 2022 21:06:41 -0700 Subject: [PATCH 03/10] refactor(complete): Add a subcommand to examples It's useful when testing to have a subcommand in the examples. --- clap_complete/examples/completion-derive.rs | 13 ++++++++++++- clap_complete/examples/completion.rs | 15 +++++++++------ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/clap_complete/examples/completion-derive.rs b/clap_complete/examples/completion-derive.rs index ff5e8b85da3..72f8fd89f93 100644 --- a/clap_complete/examples/completion-derive.rs +++ b/clap_complete/examples/completion-derive.rs @@ -12,7 +12,7 @@ //! . ./value_hints_derive.fish //! ./target/debug/examples/value_hints_derive -- //! ``` -use clap::{Command, CommandFactory, Parser, ValueHint}; +use clap::{Args, Command, CommandFactory, Parser, Subcommand, ValueHint}; use clap_complete::{generate, Generator, Shell}; use std::ffi::OsString; use std::io; @@ -24,6 +24,17 @@ struct Opt { // If provided, outputs the completion file for given shell #[arg(long = "generate", value_enum)] generator: Option, + #[clap(subcommand)] + command: Option, +} + +#[derive(Subcommand, Debug, PartialEq)] +enum Commands { + ValueHint(ValueHintOpt), +} + +#[derive(Args, Debug, PartialEq)] +struct ValueHintOpt { // Showcasing all possible ValueHints: #[arg(long, value_hint = ValueHint::Unknown)] unknown: Option, diff --git a/clap_complete/examples/completion.rs b/clap_complete/examples/completion.rs index fac64aa2b69..cf2299c4e80 100644 --- a/clap_complete/examples/completion.rs +++ b/clap_complete/examples/completion.rs @@ -17,12 +17,7 @@ use clap_complete::{generate, Generator, Shell}; use std::io; fn build_cli() -> Command { - Command::new("completion") - .arg( - Arg::new("generator") - .long("generate") - .value_parser(value_parser!(Shell)), - ) + let value_hint_command = Command::new("value-hint") .arg( Arg::new("unknown") .long("unknown") @@ -87,7 +82,15 @@ fn build_cli() -> Command { Arg::new("email") .long("email") .value_hint(ValueHint::EmailAddress), + ); + + Command::new("completion") + .arg( + Arg::new("generator") + .long("generate") + .value_parser(value_parser!(Shell)), ) + .subcommand(value_hint_command) } fn print_completions(gen: G, cmd: &mut Command) { From 5020d739d51dc7e541d521fa41c5fdd67c7f9043 Mon Sep 17 00:00:00 2001 From: Martin von Zweigbergk Date: Tue, 27 Sep 2022 21:29:06 -0700 Subject: [PATCH 04/10] refactor(complete): Add an alias for the subcommand I want to add support for completion of arguments for aliased subcommands so it's nice to have an example to test on. --- clap_complete/examples/completion-derive.rs | 1 + clap_complete/examples/completion.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/clap_complete/examples/completion-derive.rs b/clap_complete/examples/completion-derive.rs index 72f8fd89f93..baf142fb24a 100644 --- a/clap_complete/examples/completion-derive.rs +++ b/clap_complete/examples/completion-derive.rs @@ -30,6 +30,7 @@ struct Opt { #[derive(Subcommand, Debug, PartialEq)] enum Commands { + #[clap(visible_alias = "hint")] ValueHint(ValueHintOpt), } diff --git a/clap_complete/examples/completion.rs b/clap_complete/examples/completion.rs index cf2299c4e80..0455d4f9c1f 100644 --- a/clap_complete/examples/completion.rs +++ b/clap_complete/examples/completion.rs @@ -18,6 +18,7 @@ use std::io; fn build_cli() -> Command { let value_hint_command = Command::new("value-hint") + .visible_alias("hint") .arg( Arg::new("unknown") .long("unknown") From 8d0ef124e0b956c08aacb198d42e7ca2b0765413 Mon Sep 17 00:00:00 2001 From: Martin von Zweigbergk Date: Mon, 26 Sep 2022 21:18:24 -0700 Subject: [PATCH 05/10] test(complete): Include a visible command alias Only zsh includes completion for visible aliases of subcommands. Let's show that in tests. --- clap_complete/tests/common.rs | 1 + clap_complete/tests/snapshots/sub_subcommands.zsh | 1 + 2 files changed, 2 insertions(+) diff --git a/clap_complete/tests/common.rs b/clap_complete/tests/common.rs index 1e029923f60..ab52fe93a71 100644 --- a/clap_complete/tests/common.rs +++ b/clap_complete/tests/common.rs @@ -151,6 +151,7 @@ pub fn sub_subcommands_command(name: &'static str) -> clap::Command { feature_sample_command(name).subcommand( clap::Command::new("some_cmd") .about("top level subcommand") + .visible_alias("some_cmd_alias") .subcommand( clap::Command::new("sub_cmd").about("sub-subcommand").arg( clap::Arg::new("config") diff --git a/clap_complete/tests/snapshots/sub_subcommands.zsh b/clap_complete/tests/snapshots/sub_subcommands.zsh index 922613ba209..7d853d5d4e8 100644 --- a/clap_complete/tests/snapshots/sub_subcommands.zsh +++ b/clap_complete/tests/snapshots/sub_subcommands.zsh @@ -151,6 +151,7 @@ _my-app_commands() { local commands; commands=( 'test:tests things' \ 'some_cmd:top level subcommand' \ +'some_cmd_alias:top level subcommand' \ 'help:Print this message or the help of the given subcommand(s)' \ ) _describe -t commands 'my-app commands' commands "$@" From 9c59c69bb01b622f0147ca38f258204d10deead3 Mon Sep 17 00:00:00 2001 From: Martin von Zweigbergk Date: Mon, 26 Sep 2022 21:33:53 -0700 Subject: [PATCH 06/10] refactor(complete): Remove unnecessary early return There seems to be little reason to return early with an empty list when there are no subcommands, instead of going through the loop 0 times and then returning the empty list. --- clap_complete/src/generator/utils.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/clap_complete/src/generator/utils.rs b/clap_complete/src/generator/utils.rs index 0a2c5620c2b..ca76d189baa 100644 --- a/clap_complete/src/generator/utils.rs +++ b/clap_complete/src/generator/utils.rs @@ -39,10 +39,6 @@ pub fn subcommands(p: &Command) -> Vec<(String, String)> { let mut subcmds = vec![]; - if !p.has_subcommands() { - return subcmds; - } - for sc in p.get_subcommands() { let sc_bin_name = sc.get_bin_name().unwrap(); From 35b5f9b2765f78a95edc98849a6475779da230af Mon Sep 17 00:00:00 2001 From: Martin von Zweigbergk Date: Tue, 27 Sep 2022 09:54:57 -0700 Subject: [PATCH 07/10] refactor(complete): Remove an always-true check The `text` variable here is clearly never empty, so don't check if it is. --- clap_complete/src/shells/zsh.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/clap_complete/src/shells/zsh.rs b/clap_complete/src/shells/zsh.rs index d4fc63ba711..9730229a7fc 100644 --- a/clap_complete/src/shells/zsh.rs +++ b/clap_complete/src/shells/zsh.rs @@ -156,9 +156,7 @@ fn subcommands_of(p: &Command) -> String { help = escape_help(&subcommand.get_about().unwrap_or_default().to_string()) ); - if !text.is_empty() { - ret.push(text); - } + ret.push(text); } // The subcommands From ea264fde169b91c0f0cf0728efc5e6c287b54501 Mon Sep 17 00:00:00 2001 From: Martin von Zweigbergk Date: Wed, 28 Sep 2022 07:33:31 -0700 Subject: [PATCH 08/10] fix(complete): Fix `git diff git ` for Bash Early in the Bash-completion script, we build up a string that identifies the command or subcommand. When we see the top-level command's name (e.g. `git`) we set the command so far to that value. We do that regardless of where in the argument list it appears. For example, if the argument list is `git diff git`, we set the current command to `git` when run into it the second time. We therefore suggest arguments to the top-level command afterwards, which is not correct. This patch fixes that by also considering the string that identifies the command so far, so we only set the overall command to `git` if the command so far is the empty string. This is actually just a step on the way to getting completion to work for aliases of subcommands. Closes #4273 --- clap_complete/src/shells/bash.rs | 6 +++--- clap_complete/tests/snapshots/aliases.bash | 4 ++-- clap_complete/tests/snapshots/basic.bash | 8 ++++---- .../tests/snapshots/feature_sample.bash | 8 ++++---- clap_complete/tests/snapshots/quoting.bash | 18 +++++++++--------- .../tests/snapshots/special_commands.bash | 14 +++++++------- .../tests/snapshots/sub_subcommands.bash | 12 ++++++------ clap_complete/tests/snapshots/value_hint.bash | 4 ++-- 8 files changed, 37 insertions(+), 37 deletions(-) diff --git a/clap_complete/src/shells/bash.rs b/clap_complete/src/shells/bash.rs index e1429c77ba9..76e37b75cd1 100644 --- a/clap_complete/src/shells/bash.rs +++ b/clap_complete/src/shells/bash.rs @@ -31,8 +31,8 @@ impl Generator for Bash { for i in ${{COMP_WORDS[@]}} do - case \"${{i}}\" in - \"$1\") + case \"${{cmd}},${{i}}\" in + \",$1\") cmd=\"{cmd}\" ;;{subcmds} *) @@ -86,7 +86,7 @@ fn all_subcommands(cmd: &Command) -> String { subcmds.extend(scs.iter().map(|sc| { format!( - "{name}) + "*,{name}) cmd+=\"__{fn_name}\" ;;", name = sc, diff --git a/clap_complete/tests/snapshots/aliases.bash b/clap_complete/tests/snapshots/aliases.bash index a9949102be5..0ca8e493f5d 100644 --- a/clap_complete/tests/snapshots/aliases.bash +++ b/clap_complete/tests/snapshots/aliases.bash @@ -8,8 +8,8 @@ _my-app() { for i in ${COMP_WORDS[@]} do - case "${i}" in - "$1") + case "${cmd},${i}" in + ",$1") cmd="my__app" ;; *) diff --git a/clap_complete/tests/snapshots/basic.bash b/clap_complete/tests/snapshots/basic.bash index 08b27e0bbde..1f7c154a25d 100644 --- a/clap_complete/tests/snapshots/basic.bash +++ b/clap_complete/tests/snapshots/basic.bash @@ -8,14 +8,14 @@ _my-app() { for i in ${COMP_WORDS[@]} do - case "${i}" in - "$1") + case "${cmd},${i}" in + ",$1") cmd="my__app" ;; - help) + *,help) cmd+="__help" ;; - test) + *,test) cmd+="__test" ;; *) diff --git a/clap_complete/tests/snapshots/feature_sample.bash b/clap_complete/tests/snapshots/feature_sample.bash index 2d1ec386ce4..7854f3d7abb 100644 --- a/clap_complete/tests/snapshots/feature_sample.bash +++ b/clap_complete/tests/snapshots/feature_sample.bash @@ -8,14 +8,14 @@ _my-app() { for i in ${COMP_WORDS[@]} do - case "${i}" in - "$1") + case "${cmd},${i}" in + ",$1") cmd="my__app" ;; - help) + *,help) cmd+="__help" ;; - test) + *,test) cmd+="__test" ;; *) diff --git a/clap_complete/tests/snapshots/quoting.bash b/clap_complete/tests/snapshots/quoting.bash index b831012b5d3..2ac46bcd740 100644 --- a/clap_complete/tests/snapshots/quoting.bash +++ b/clap_complete/tests/snapshots/quoting.bash @@ -8,29 +8,29 @@ _my-app() { for i in ${COMP_WORDS[@]} do - case "${i}" in - "$1") + case "${cmd},${i}" in + ",$1") cmd="my__app" ;; - cmd-backslash) + *,cmd-backslash) cmd+="__cmd__backslash" ;; - cmd-backticks) + *,cmd-backticks) cmd+="__cmd__backticks" ;; - cmd-brackets) + *,cmd-brackets) cmd+="__cmd__brackets" ;; - cmd-double-quotes) + *,cmd-double-quotes) cmd+="__cmd__double__quotes" ;; - cmd-expansions) + *,cmd-expansions) cmd+="__cmd__expansions" ;; - cmd-single-quotes) + *,cmd-single-quotes) cmd+="__cmd__single__quotes" ;; - help) + *,help) cmd+="__help" ;; *) diff --git a/clap_complete/tests/snapshots/special_commands.bash b/clap_complete/tests/snapshots/special_commands.bash index 11f8c186c36..900a02bc036 100644 --- a/clap_complete/tests/snapshots/special_commands.bash +++ b/clap_complete/tests/snapshots/special_commands.bash @@ -8,23 +8,23 @@ _my-app() { for i in ${COMP_WORDS[@]} do - case "${i}" in - "$1") + case "${cmd},${i}" in + ",$1") cmd="my__app" ;; - help) + *,help) cmd+="__help" ;; - some-cmd-with-hyphens) + *,some-cmd-with-hyphens) cmd+="__some__cmd__with__hyphens" ;; - some-hidden-cmd) + *,some-hidden-cmd) cmd+="__some__hidden__cmd" ;; - some_cmd) + *,some_cmd) cmd+="__some_cmd" ;; - test) + *,test) cmd+="__test" ;; *) diff --git a/clap_complete/tests/snapshots/sub_subcommands.bash b/clap_complete/tests/snapshots/sub_subcommands.bash index 69793078c62..41ee58c57d5 100644 --- a/clap_complete/tests/snapshots/sub_subcommands.bash +++ b/clap_complete/tests/snapshots/sub_subcommands.bash @@ -8,20 +8,20 @@ _my-app() { for i in ${COMP_WORDS[@]} do - case "${i}" in - "$1") + case "${cmd},${i}" in + ",$1") cmd="my__app" ;; - help) + *,help) cmd+="__help" ;; - some_cmd) + *,some_cmd) cmd+="__some_cmd" ;; - sub_cmd) + *,sub_cmd) cmd+="__sub_cmd" ;; - test) + *,test) cmd+="__test" ;; *) diff --git a/clap_complete/tests/snapshots/value_hint.bash b/clap_complete/tests/snapshots/value_hint.bash index 2d3d88bae86..11fb39624fc 100644 --- a/clap_complete/tests/snapshots/value_hint.bash +++ b/clap_complete/tests/snapshots/value_hint.bash @@ -8,8 +8,8 @@ _my-app() { for i in ${COMP_WORDS[@]} do - case "${i}" in - "$1") + case "${cmd},${i}" in + ",$1") cmd="my__app" ;; *) From 9ee45f7f3dc659b3c7b283d2e863c3ca280db70d Mon Sep 17 00:00:00 2001 From: Martin von Zweigbergk Date: Wed, 28 Sep 2022 14:33:59 -0700 Subject: [PATCH 09/10] fix(complete): Fix `git diff log ` for Bash This continues the work started with the fix for #4273. There was another bug caused by using the subcommand names without considering their position in the argument list. If the user enters `git diff log `, we build up a string that identifies the subcommand. We ended up making the string `git__diff__log` in this case because we appended `__log` without considering the current state. Since `git__diff__log` does not correspond to an actual command, we wouldn't provide any suggestions. This commit restructures the code so we walk subcommands and subsubcommands in `bash.rs`. While walking those, we build up a list containing triples of the parent `$cmd` name (e.g. `git__diff`), the current command's name (e.g. `log`), and the `$cmd` for the current command. We then build the shell script's case arms based on that information. We could instead have fixed #4280 by using the second element in the pair returned from `utils::all_subcommands()` (a stringified list of the subcommand path) instead of the first one. However, that would not have helped us solve #4265. Closes #4280 --- clap_complete/src/shells/bash.rs | 53 +++++++++++++------ clap_complete/tests/snapshots/basic.bash | 14 +++-- .../tests/snapshots/feature_sample.bash | 14 +++-- clap_complete/tests/snapshots/quoting.bash | 49 ++++++++++++----- .../tests/snapshots/special_commands.bash | 35 ++++++++---- .../tests/snapshots/sub_subcommands.bash | 37 ++++++++++--- 6 files changed, 145 insertions(+), 57 deletions(-) diff --git a/clap_complete/src/shells/bash.rs b/clap_complete/src/shells/bash.rs index 76e37b75cd1..6ea962c5e49 100644 --- a/clap_complete/src/shells/bash.rs +++ b/clap_complete/src/shells/bash.rs @@ -75,26 +75,45 @@ complete -F _{name} -o bashdefault -o default {name} fn all_subcommands(cmd: &Command) -> String { debug!("all_subcommands"); - let mut subcmds = vec![String::new()]; - let mut scs = utils::all_subcommands(cmd) - .iter() - .map(|x| x.0.clone()) - .collect::>(); - - scs.sort(); - scs.dedup(); + fn add_command( + parent_fn_name: &str, + cmd: &Command, + subcmds: &mut Vec<(String, String, String)>, + ) { + let fn_name = format!( + "{parent_fn_name}__{cmd_name}", + parent_fn_name = parent_fn_name, + cmd_name = cmd.get_name().to_string().replace('-', "__") + ); + subcmds.push(( + parent_fn_name.to_string(), + cmd.get_name().to_string(), + fn_name.clone(), + )); + for subcmd in cmd.get_subcommands() { + add_command(&fn_name, subcmd, subcmds); + } + } + let mut subcmds = vec![]; + let fn_name = cmd.get_name().replace('-', "__"); + for subcmd in cmd.get_subcommands() { + add_command(&fn_name, subcmd, &mut subcmds); + } + subcmds.sort(); - subcmds.extend(scs.iter().map(|sc| { - format!( - "*,{name}) - cmd+=\"__{fn_name}\" + let mut cases = vec![String::new()]; + for (parent_fn_name, name, fn_name) in subcmds { + cases.push(format!( + "{parent_fn_name},{name}) + cmd=\"{fn_name}\" ;;", - name = sc, - fn_name = sc.replace('-', "__") - ) - })); + parent_fn_name = parent_fn_name, + name = name, + fn_name = fn_name, + )); + } - subcmds.join("\n ") + cases.join("\n ") } fn subcommand_details(cmd: &Command) -> String { diff --git a/clap_complete/tests/snapshots/basic.bash b/clap_complete/tests/snapshots/basic.bash index 1f7c154a25d..70946e79ca7 100644 --- a/clap_complete/tests/snapshots/basic.bash +++ b/clap_complete/tests/snapshots/basic.bash @@ -12,11 +12,17 @@ _my-app() { ",$1") cmd="my__app" ;; - *,help) - cmd+="__help" + my__app,help) + cmd="my__app__help" ;; - *,test) - cmd+="__test" + my__app,test) + cmd="my__app__test" + ;; + my__app__help,help) + cmd="my__app__help__help" + ;; + my__app__help,test) + cmd="my__app__help__test" ;; *) ;; diff --git a/clap_complete/tests/snapshots/feature_sample.bash b/clap_complete/tests/snapshots/feature_sample.bash index 7854f3d7abb..8ea49145b5a 100644 --- a/clap_complete/tests/snapshots/feature_sample.bash +++ b/clap_complete/tests/snapshots/feature_sample.bash @@ -12,11 +12,17 @@ _my-app() { ",$1") cmd="my__app" ;; - *,help) - cmd+="__help" + my__app,help) + cmd="my__app__help" ;; - *,test) - cmd+="__test" + my__app,test) + cmd="my__app__test" + ;; + my__app__help,help) + cmd="my__app__help__help" + ;; + my__app__help,test) + cmd="my__app__help__test" ;; *) ;; diff --git a/clap_complete/tests/snapshots/quoting.bash b/clap_complete/tests/snapshots/quoting.bash index 2ac46bcd740..e387c0bc52a 100644 --- a/clap_complete/tests/snapshots/quoting.bash +++ b/clap_complete/tests/snapshots/quoting.bash @@ -12,26 +12,47 @@ _my-app() { ",$1") cmd="my__app" ;; - *,cmd-backslash) - cmd+="__cmd__backslash" + my__app,cmd-backslash) + cmd="my__app__cmd__backslash" ;; - *,cmd-backticks) - cmd+="__cmd__backticks" + my__app,cmd-backticks) + cmd="my__app__cmd__backticks" ;; - *,cmd-brackets) - cmd+="__cmd__brackets" + my__app,cmd-brackets) + cmd="my__app__cmd__brackets" ;; - *,cmd-double-quotes) - cmd+="__cmd__double__quotes" + my__app,cmd-double-quotes) + cmd="my__app__cmd__double__quotes" ;; - *,cmd-expansions) - cmd+="__cmd__expansions" + my__app,cmd-expansions) + cmd="my__app__cmd__expansions" ;; - *,cmd-single-quotes) - cmd+="__cmd__single__quotes" + my__app,cmd-single-quotes) + cmd="my__app__cmd__single__quotes" ;; - *,help) - cmd+="__help" + my__app,help) + cmd="my__app__help" + ;; + my__app__help,cmd-backslash) + cmd="my__app__help__cmd__backslash" + ;; + my__app__help,cmd-backticks) + cmd="my__app__help__cmd__backticks" + ;; + my__app__help,cmd-brackets) + cmd="my__app__help__cmd__brackets" + ;; + my__app__help,cmd-double-quotes) + cmd="my__app__help__cmd__double__quotes" + ;; + my__app__help,cmd-expansions) + cmd="my__app__help__cmd__expansions" + ;; + my__app__help,cmd-single-quotes) + cmd="my__app__help__cmd__single__quotes" + ;; + my__app__help,help) + cmd="my__app__help__help" ;; *) ;; diff --git a/clap_complete/tests/snapshots/special_commands.bash b/clap_complete/tests/snapshots/special_commands.bash index 900a02bc036..31b5354aa7b 100644 --- a/clap_complete/tests/snapshots/special_commands.bash +++ b/clap_complete/tests/snapshots/special_commands.bash @@ -12,20 +12,35 @@ _my-app() { ",$1") cmd="my__app" ;; - *,help) - cmd+="__help" + my__app,help) + cmd="my__app__help" ;; - *,some-cmd-with-hyphens) - cmd+="__some__cmd__with__hyphens" + my__app,some-cmd-with-hyphens) + cmd="my__app__some__cmd__with__hyphens" ;; - *,some-hidden-cmd) - cmd+="__some__hidden__cmd" + my__app,some-hidden-cmd) + cmd="my__app__some__hidden__cmd" ;; - *,some_cmd) - cmd+="__some_cmd" + my__app,some_cmd) + cmd="my__app__some_cmd" ;; - *,test) - cmd+="__test" + my__app,test) + cmd="my__app__test" + ;; + my__app__help,help) + cmd="my__app__help__help" + ;; + my__app__help,some-cmd-with-hyphens) + cmd="my__app__help__some__cmd__with__hyphens" + ;; + my__app__help,some-hidden-cmd) + cmd="my__app__help__some__hidden__cmd" + ;; + my__app__help,some_cmd) + cmd="my__app__help__some_cmd" + ;; + my__app__help,test) + cmd="my__app__help__test" ;; *) ;; diff --git a/clap_complete/tests/snapshots/sub_subcommands.bash b/clap_complete/tests/snapshots/sub_subcommands.bash index 41ee58c57d5..fe9c8459704 100644 --- a/clap_complete/tests/snapshots/sub_subcommands.bash +++ b/clap_complete/tests/snapshots/sub_subcommands.bash @@ -12,17 +12,38 @@ _my-app() { ",$1") cmd="my__app" ;; - *,help) - cmd+="__help" + my__app,help) + cmd="my__app__help" ;; - *,some_cmd) - cmd+="__some_cmd" + my__app,some_cmd) + cmd="my__app__some_cmd" ;; - *,sub_cmd) - cmd+="__sub_cmd" + my__app,test) + cmd="my__app__test" ;; - *,test) - cmd+="__test" + my__app__help,help) + cmd="my__app__help__help" + ;; + my__app__help,some_cmd) + cmd="my__app__help__some_cmd" + ;; + my__app__help,test) + cmd="my__app__help__test" + ;; + my__app__help__some_cmd,sub_cmd) + cmd="my__app__help__some_cmd__sub_cmd" + ;; + my__app__some_cmd,help) + cmd="my__app__some_cmd__help" + ;; + my__app__some_cmd,sub_cmd) + cmd="my__app__some_cmd__sub_cmd" + ;; + my__app__some_cmd__help,help) + cmd="my__app__some_cmd__help__help" + ;; + my__app__some_cmd__help,sub_cmd) + cmd="my__app__some_cmd__help__sub_cmd" ;; *) ;; From 33fa7c4c19302829b5af3392194d5e7d77044f4c Mon Sep 17 00:00:00 2001 From: Martin von Zweigbergk Date: Wed, 28 Sep 2022 21:10:45 -0700 Subject: [PATCH 10/10] fix(complete): Fix command alias and Bash With the previous fixes for #4273 and #4280 in place, it's now easy to add support for subcommand aliases, which this commit does. This addresses #4265 for Bash. --- clap_complete/src/shells/bash.rs | 7 +++++++ clap_complete/tests/snapshots/sub_subcommands.bash | 3 +++ 2 files changed, 10 insertions(+) diff --git a/clap_complete/src/shells/bash.rs b/clap_complete/src/shells/bash.rs index 6ea962c5e49..e110537e5f6 100644 --- a/clap_complete/src/shells/bash.rs +++ b/clap_complete/src/shells/bash.rs @@ -90,6 +90,13 @@ fn all_subcommands(cmd: &Command) -> String { cmd.get_name().to_string(), fn_name.clone(), )); + for alias in cmd.get_visible_aliases() { + subcmds.push(( + parent_fn_name.to_string(), + alias.to_string(), + fn_name.clone(), + )); + } for subcmd in cmd.get_subcommands() { add_command(&fn_name, subcmd, subcmds); } diff --git a/clap_complete/tests/snapshots/sub_subcommands.bash b/clap_complete/tests/snapshots/sub_subcommands.bash index fe9c8459704..4c2573a77ab 100644 --- a/clap_complete/tests/snapshots/sub_subcommands.bash +++ b/clap_complete/tests/snapshots/sub_subcommands.bash @@ -18,6 +18,9 @@ _my-app() { my__app,some_cmd) cmd="my__app__some_cmd" ;; + my__app,some_cmd_alias) + cmd="my__app__some_cmd" + ;; my__app,test) cmd="my__app__test" ;;