Skip to content

Commit

Permalink
fix(help): Do not propagate global args to help
Browse files Browse the repository at this point in the history
This prevents global args from showing in help completions,
since help completions should only suggest subcommands.
Adds tests to ensure the args still show in the generated
help messages of subcommands.
  • Loading branch information
talklittle committed Aug 27, 2022
1 parent 1f3df00 commit eec047a
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 30 deletions.
6 changes: 3 additions & 3 deletions clap_complete/tests/snapshots/basic.bash
Expand Up @@ -39,7 +39,7 @@ _my-app() {
return 0
;;
my__app__help)
opts="-c test help"
opts="test help"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
Expand All @@ -53,7 +53,7 @@ _my-app() {
return 0
;;
my__app__help__help)
opts="-c"
opts=""
if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
Expand All @@ -67,7 +67,7 @@ _my-app() {
return 0
;;
my__app__help__test)
opts="-c"
opts=""
if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
Expand Down
3 changes: 0 additions & 3 deletions clap_complete/tests/snapshots/basic.elvish
Expand Up @@ -32,15 +32,12 @@ set edit:completion:arg-completer[my-app] = {|@words|
cand --help 'Print help information'
}
&'my-app;help'= {
cand -c 'c'
cand test 'Subcommand'
cand help 'Print this message or the help of the given subcommand(s)'
}
&'my-app;help;test'= {
cand -c 'c'
}
&'my-app;help;help'= {
cand -c 'c'
}
]
$completions[$command]
Expand Down
3 changes: 0 additions & 3 deletions clap_complete/tests/snapshots/basic.fish
Expand Up @@ -6,8 +6,5 @@ complete -c my-app -n "__fish_use_subcommand" -f -a "help" -d 'Print this messag
complete -c my-app -n "__fish_seen_subcommand_from test" -s d
complete -c my-app -n "__fish_seen_subcommand_from test" -s c
complete -c my-app -n "__fish_seen_subcommand_from test" -s h -l help -d 'Print help information'
complete -c my-app -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from test; and not __fish_seen_subcommand_from help" -s c
complete -c my-app -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from test; and not __fish_seen_subcommand_from help" -f -a "test" -d 'Subcommand'
complete -c my-app -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from test; and not __fish_seen_subcommand_from help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
complete -c my-app -n "__fish_seen_subcommand_from help; and __fish_seen_subcommand_from test" -s c
complete -c my-app -n "__fish_seen_subcommand_from help; and __fish_seen_subcommand_from help" -s c
3 changes: 0 additions & 3 deletions clap_complete/tests/snapshots/basic.ps1
Expand Up @@ -37,17 +37,14 @@ Register-ArgumentCompleter -Native -CommandName 'my-app' -ScriptBlock {
break
}
'my-app;help' {
[CompletionResult]::new('-c', 'c', [CompletionResultType]::ParameterName, 'c')
[CompletionResult]::new('test', 'test', [CompletionResultType]::ParameterValue, 'Subcommand')
[CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)')
break
}
'my-app;help;test' {
[CompletionResult]::new('-c', 'c', [CompletionResultType]::ParameterName, 'c')
break
}
'my-app;help;help' {
[CompletionResult]::new('-c', 'c', [CompletionResultType]::ParameterName, 'c')
break
}
})
Expand Down
3 changes: 0 additions & 3 deletions clap_complete/tests/snapshots/basic.zsh
Expand Up @@ -38,7 +38,6 @@ _arguments "${_arguments_options[@]}" /
;;
(help)
_arguments "${_arguments_options[@]}" /
'*-c[]' /
":: :_my-app__help_commands" /
"*::: :->help" /
&& ret=0
Expand All @@ -51,12 +50,10 @@ _arguments "${_arguments_options[@]}" /
case $line[1] in
(test)
_arguments "${_arguments_options[@]}" /
'*-c[]' /
&& ret=0
;;
(help)
_arguments "${_arguments_options[@]}" /
'*-c[]' /
&& ret=0
;;
esac
Expand Down
15 changes: 0 additions & 15 deletions clap_complete_fig/tests/snapshots/basic.fig.js
Expand Up @@ -26,25 +26,10 @@ const completion: Fig.Spec = {
{
name: "test",
description: "Subcommand",
options: [
{
name: "-c",
},
],
},
{
name: "help",
description: "Print this message or the help of the given subcommand(s)",
options: [
{
name: "-c",
},
],
},
],
options: [
{
name: "-c",
},
],
},
Expand Down
10 changes: 10 additions & 0 deletions src/builder/command.rs
Expand Up @@ -4070,7 +4070,17 @@ impl Command {
pub(crate) fn _propagate_global_args(&mut self) {
debug!("Command::_propagate_global_args:{}", self.name);

let autogenerated_help_subcommand = !self.is_disable_help_subcommand_set();

for sc in &mut self.subcommands {
if sc.get_name() == "help" && autogenerated_help_subcommand {
// Avoid propagating args to the autogenerated help subtrees used in completion.
// This prevents args from showing up during help completions like
// `myapp help subcmd <TAB>`, which should only suggest subcommands and not args,
// while still allowing args to show up properly on the generated help message.
continue;
}

for a in self.args.args().filter(|a| a.is_global_set()) {
if sc.find(&a.id).is_some() {
debug!(
Expand Down
105 changes: 105 additions & 0 deletions tests/builder/help.rs
Expand Up @@ -2097,6 +2097,111 @@ Arguments:
);
}

#[test]
fn global_args_should_show_on_toplevel_help_message() {
static HELP: &str = "myapp\x20
Usage:
myapp [OPTIONS] [SUBCOMMAND]
Subcommands:
subcmd\x20\x20\x20\x20
help Print this message or the help of the given subcommand(s)
Options:
-g, --some-global <someglobal>\x20\x20\x20\x20
-h, --help Print help information
";

let cmd = Command::new("myapp")
.arg(
Arg::new("someglobal")
.short('g')
.long("some-global")
.global(true),
)
.subcommand(Command::new("subcmd").subcommand(Command::new("multi").version("1.0")));

utils::assert_output(cmd, "myapp help", HELP, false);
}

#[test]
fn global_args_should_not_show_on_help_message_for_help_help() {
static HELP_HELP: &str = "myapp-help\x20
Print this message or the help of the given subcommand(s)
Usage:
myapp help [SUBCOMMAND]...
Arguments:
[SUBCOMMAND]... The subcommand whose help message to display
";

let cmd = Command::new("myapp")
.arg(
Arg::new("someglobal")
.short('g')
.long("some-global")
.global(true),
)
.subcommand(Command::new("subcmd").subcommand(Command::new("multi").version("1.0")));

utils::assert_output(cmd, "myapp help help", HELP_HELP, false);
}

#[test]
fn global_args_should_show_on_help_message_for_subcommand() {
static HELP_SUBCMD: &str = "myapp-subcmd\x20
Usage:
myapp subcmd [OPTIONS] [SUBCOMMAND]
Subcommands:
multi\x20\x20\x20\x20
help Print this message or the help of the given subcommand(s)
Options:
-g, --some-global <someglobal>\x20\x20\x20\x20
-h, --help Print help information
";

let cmd = Command::new("myapp")
.arg(
Arg::new("someglobal")
.short('g')
.long("some-global")
.global(true),
)
.subcommand(Command::new("subcmd").subcommand(Command::new("multi").version("1.0")));

utils::assert_output(cmd, "myapp help subcmd", HELP_SUBCMD, false);
}

#[test]
fn global_args_should_show_on_help_message_for_nested_subcommand() {
static HELP_SUB_SUBCMD: &str = "myapp-subcmd-multi 1.0
Usage:
myapp subcmd multi [OPTIONS]
Options:
-g, --some-global <someglobal>\x20\x20\x20\x20
-h, --help Print help information
-V, --version Print version information
";

let cmd = Command::new("myapp")
.arg(
Arg::new("someglobal")
.short('g')
.long("some-global")
.global(true),
)
.subcommand(Command::new("subcmd").subcommand(Command::new("multi").version("1.0")));

utils::assert_output(cmd, "myapp help subcmd multi", HELP_SUB_SUBCMD, false);
}

#[test]
fn option_usage_order() {
static OPTION_USAGE_ORDER: &str = "order
Expand Down

0 comments on commit eec047a

Please sign in to comment.