diff --git a/clap_builder/src/builder/command.rs b/clap_builder/src/builder/command.rs index 78f3e75abf2..f67eb9c623f 100644 --- a/clap_builder/src/builder/command.rs +++ b/clap_builder/src/builder/command.rs @@ -3553,6 +3553,15 @@ impl Command { self.long_flag_aliases.iter().map(|a| a.0.as_str()) } + /// Iterate through the *hidden* aliases for this subcommand. + #[inline] + pub fn get_aliases(&self) -> impl Iterator + '_ { + self.aliases + .iter() + .filter(|(_, vis)| !*vis) + .map(|a| a.0.as_str()) + } + #[inline] pub(crate) fn is_set(&self, s: AppSettings) -> bool { self.settings.is_set(s) || self.g_settings.is_set(s) diff --git a/clap_complete/src/dynamic/completer.rs b/clap_complete/src/dynamic/completer.rs index 640e2d57a81..6a650f746bc 100644 --- a/clap_complete/src/dynamic/completer.rs +++ b/clap_complete/src/dynamic/completer.rs @@ -386,11 +386,18 @@ fn subcommands(p: &clap::Command) -> Vec { debug!("subcommands: Has subcommands...{:?}", p.has_subcommands()); p.get_subcommands() .flat_map(|sc| { - sc.get_name_and_visible_aliases().into_iter().map(|s| { - CompletionCandidate::new(s.to_string()) - .help(sc.get_about().cloned()) - .visible(true) - }) + sc.get_name_and_visible_aliases() + .into_iter() + .map(|s| { + CompletionCandidate::new(s.to_string()) + .help(sc.get_about().cloned()) + .visible(!sc.is_hide_set()) + }) + .chain(sc.get_aliases().into_iter().map(|s| { + CompletionCandidate::new(s.to_string()) + .help(sc.get_about().cloned()) + .visible(false) + })) }) .collect() } diff --git a/clap_complete/tests/testsuite/dynamic.rs b/clap_complete/tests/testsuite/dynamic.rs index df8bac01d56..2863da32034 100644 --- a/clap_complete/tests/testsuite/dynamic.rs +++ b/clap_complete/tests/testsuite/dynamic.rs @@ -54,6 +54,44 @@ fn suggest_hidden_long_flags() { ) } +#[test] +fn suggest_hidden_subcommand_and_aliases() { + let mut cmd = Command::new("exhaustive") + .subcommand( + Command::new("test_visible") + .visible_alias("test_visible-alias_visible") + .alias("test_visible-alias_hidden"), + ) + .subcommand( + Command::new("test_hidden") + .visible_alias("test_hidden-alias_visible") + .alias("test_hidden-alias_hidden") + .hide(true), + ); + + assert_data_eq!( + complete!(cmd, "test"), + snapbox::str![ + "test_visible +test_visible-alias_visible" + ] + ); + + assert_data_eq!( + complete!(cmd, "test_h"), + snapbox::str![ + "test_hidden +test_hidden-alias_hidden +test_hidden-alias_visible" + ] + ); + + assert_data_eq!( + complete!(cmd, "test_hidden-alias_h"), + snapbox::str!["test_hidden-alias_hidden"] + ) +} + #[test] fn suggest_subcommand_aliases() { let mut cmd = Command::new("exhaustive") diff --git a/clap_complete/tests/testsuite/elvish.rs b/clap_complete/tests/testsuite/elvish.rs index 2aa95f7e1dd..41a5e109b93 100644 --- a/clap_complete/tests/testsuite/elvish.rs +++ b/clap_complete/tests/testsuite/elvish.rs @@ -196,8 +196,8 @@ fn complete_dynamic() { let expected = snapbox::str![ r#"% exhaustive --generate COMPLETING argument ---generate --help -V action complete hint pacman value ---global --version -h alias help last quote "# +--generate --help -V action help last quote +--global --version -h alias hint pacman value"# ]; let actual = runtime.complete(input, &term).unwrap(); assert_data_eq!(actual, expected); @@ -213,4 +213,4 @@ fn complete_dynamic() { ]; let actual = runtime.complete(input, &term).unwrap(); assert_data_eq!(actual, expected); -} \ No newline at end of file +} diff --git a/clap_complete/tests/testsuite/fish.rs b/clap_complete/tests/testsuite/fish.rs index c6c11a4e639..b35458fd21e 100644 --- a/clap_complete/tests/testsuite/fish.rs +++ b/clap_complete/tests/testsuite/fish.rs @@ -185,11 +185,11 @@ fn complete_dynamic() { let input = "exhaustive \t\t"; let expected = snapbox::str![[r#" % exhaustive action -action last -V (Print version) -alias pacman --generate (generate) -complete (Register shell completions for this program) quote --global (everywhere) -help (Print this message or the help of the given subcommand(s)) value --help (Print help) -hint -h (Print help) --version (Print version) +action pacman --generate (generate) +alias quote --global (everywhere) +help (Print this message or the help of the given subcommand(s)) value --help (Print help) +hint -h (Print help) --version (Print version) +last -V (Print version) "#]]; let actual = runtime.complete(input, &term).unwrap(); assert_data_eq!(actual, expected); diff --git a/clap_complete/tests/testsuite/zsh.rs b/clap_complete/tests/testsuite/zsh.rs index e483e7fd7eb..ea8a1436aea 100644 --- a/clap_complete/tests/testsuite/zsh.rs +++ b/clap_complete/tests/testsuite/zsh.rs @@ -163,7 +163,6 @@ pacman action alias value quote hint last -- assert_data_eq!(actual, expected); } - #[cfg(all(unix, feature = "unstable-dynamic"))] #[test] fn register_dynamic() { @@ -184,8 +183,8 @@ fn complete_dynamic() { let input = "exhaustive \t\t"; let expected = snapbox::str![ r#"% exhaustive ---generate --help -V action complete hint pacman value ---global --version -h alias help last quote "# +--generate --help -V action help last quote +--global --version -h alias hint pacman value "# ]; let actual = runtime.complete(input, &term).unwrap(); assert_data_eq!(actual, expected); @@ -200,4 +199,4 @@ fn complete_dynamic() { ]; let actual = runtime.complete(input, &term).unwrap(); assert_data_eq!(actual, expected); -} \ No newline at end of file +}