From fdcee9313f2eb640cb9a919a96bef2fa2ba0bba9 Mon Sep 17 00:00:00 2001 From: Andrew Shu Date: Wed, 24 Aug 2022 22:44:07 -0700 Subject: [PATCH 1/3] feat(complete): Add completion for help subcommands Adds parser flags to toggle whether to run the expensive clone logic for completions case. Help completion will only suggest subcommands, not args. clap_complete generator sets the flag. --- clap_complete/src/generator/mod.rs | 1 + clap_complete/tests/snapshots/basic.bash | 30 ++++- clap_complete/tests/snapshots/basic.elvish | 6 + clap_complete/tests/snapshots/basic.fish | 4 +- clap_complete/tests/snapshots/basic.ps1 | 8 ++ clap_complete/tests/snapshots/basic.zsh | 36 +++++- .../tests/snapshots/feature_sample.bash | 30 ++++- .../tests/snapshots/feature_sample.elvish | 6 + .../tests/snapshots/feature_sample.fish | 2 + .../tests/snapshots/feature_sample.ps1 | 8 ++ .../tests/snapshots/feature_sample.zsh | 36 +++++- clap_complete/tests/snapshots/quoting.bash | 100 ++++++++++++++++- clap_complete/tests/snapshots/quoting.elvish | 21 ++++ clap_complete/tests/snapshots/quoting.fish | 7 ++ clap_complete/tests/snapshots/quoting.ps1 | 28 +++++ clap_complete/tests/snapshots/quoting.zsh | 86 +++++++++++++- .../tests/snapshots/special_commands.bash | 72 +++++++++++- .../tests/snapshots/special_commands.elvish | 15 +++ .../tests/snapshots/special_commands.fish | 5 + .../tests/snapshots/special_commands.ps1 | 20 ++++ .../tests/snapshots/special_commands.zsh | 66 ++++++++++- .../tests/snapshots/sub_subcommands.bash | 88 ++++++++++++++- .../tests/snapshots/sub_subcommands.elvish | 18 +++ .../tests/snapshots/sub_subcommands.fish | 6 + .../tests/snapshots/sub_subcommands.ps1 | 24 ++++ .../tests/snapshots/sub_subcommands.zsh | 105 +++++++++++++++++- .../tests/snapshots/basic.fig.js | 15 ++- .../tests/snapshots/feature_sample.fig.js | 15 ++- .../tests/snapshots/quoting.fig.js | 35 +++++- .../tests/snapshots/special_commands.fig.js | 26 ++++- .../tests/snapshots/sub_subcommands.fig.js | 40 +++++-- src/builder/app_settings.rs | 8 ++ src/builder/command.rs | 59 +++++++++- src/mkeymap.rs | 6 + 34 files changed, 978 insertions(+), 54 deletions(-) diff --git a/clap_complete/src/generator/mod.rs b/clap_complete/src/generator/mod.rs index dd9c0584f22..7cf9f83dc7d 100644 --- a/clap_complete/src/generator/mod.rs +++ b/clap_complete/src/generator/mod.rs @@ -234,6 +234,7 @@ where G: Generator, S: Into, { + cmd.prepare_build_for_completion(); cmd.build(); gen.generate(cmd, buf) diff --git a/clap_complete/tests/snapshots/basic.bash b/clap_complete/tests/snapshots/basic.bash index 4690e8b8085..39d6014f75f 100644 --- a/clap_complete/tests/snapshots/basic.bash +++ b/clap_complete/tests/snapshots/basic.bash @@ -39,7 +39,7 @@ _my-app() { return 0 ;; my__app__help) - opts="-c [SUBCOMMAND]..." + opts="-c test help" if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -52,6 +52,34 @@ _my-app() { COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 ;; + my__app__help__help) + opts="" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + my__app__help__test) + opts="" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; my__app__test) opts="-d -c -h --help" if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then diff --git a/clap_complete/tests/snapshots/basic.elvish b/clap_complete/tests/snapshots/basic.elvish index ca7c71fd263..abff7a00530 100644 --- a/clap_complete/tests/snapshots/basic.elvish +++ b/clap_complete/tests/snapshots/basic.elvish @@ -33,6 +33,12 @@ set edit:completion:arg-completer[my-app] = {|@words| } &'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'= { + } + &'my-app;help;help'= { } ] $completions[$command] diff --git a/clap_complete/tests/snapshots/basic.fish b/clap_complete/tests/snapshots/basic.fish index e836a340ef0..1ee4a9d4dc0 100644 --- a/clap_complete/tests/snapshots/basic.fish +++ b/clap_complete/tests/snapshots/basic.fish @@ -6,4 +6,6 @@ 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" -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" -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)' diff --git a/clap_complete/tests/snapshots/basic.ps1 b/clap_complete/tests/snapshots/basic.ps1 index 96af4b570ab..9ef673923c3 100644 --- a/clap_complete/tests/snapshots/basic.ps1 +++ b/clap_complete/tests/snapshots/basic.ps1 @@ -38,6 +38,14 @@ Register-ArgumentCompleter -Native -CommandName 'my-app' -ScriptBlock { } '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' { + break + } + 'my-app;help;help' { break } }) diff --git a/clap_complete/tests/snapshots/basic.zsh b/clap_complete/tests/snapshots/basic.zsh index c72bc6dc397..2050e865127 100644 --- a/clap_complete/tests/snapshots/basic.zsh +++ b/clap_complete/tests/snapshots/basic.zsh @@ -39,12 +39,31 @@ _arguments "${_arguments_options[@]}" / (help) _arguments "${_arguments_options[@]}" / '*-c[]' / -'*::subcommand -- The subcommand whose help message to display:' / +":: :_my-app__help_commands" / +"*::: :->help" / +&& ret=0 + + case $state in + (help) + words=($line[1] "${words[@]}") + (( CURRENT += 1 )) + curcontext="${curcontext%:*:*}:my-app-help-command-$line[1]:" + case $line[1] in + (test) +_arguments "${_arguments_options[@]}" / +&& ret=0 +;; +(help) +_arguments "${_arguments_options[@]}" / && ret=0 ;; esac ;; esac +;; + esac + ;; +esac } (( $+functions[_my-app_commands] )) || @@ -57,9 +76,22 @@ _my-app_commands() { } (( $+functions[_my-app__help_commands] )) || _my-app__help_commands() { - local commands; commands=() + local commands; commands=( +'test:Subcommand' / +'help:Print this message or the help of the given subcommand(s)' / + ) _describe -t commands 'my-app help commands' commands "$@" } +(( $+functions[_my-app__help__help_commands] )) || +_my-app__help__help_commands() { + local commands; commands=() + _describe -t commands 'my-app help help commands' commands "$@" +} +(( $+functions[_my-app__help__test_commands] )) || +_my-app__help__test_commands() { + local commands; commands=() + _describe -t commands 'my-app help test commands' commands "$@" +} (( $+functions[_my-app__test_commands] )) || _my-app__test_commands() { local commands; commands=() diff --git a/clap_complete/tests/snapshots/feature_sample.bash b/clap_complete/tests/snapshots/feature_sample.bash index 260103562e3..5bbb5762d06 100644 --- a/clap_complete/tests/snapshots/feature_sample.bash +++ b/clap_complete/tests/snapshots/feature_sample.bash @@ -39,7 +39,7 @@ _my-app() { return 0 ;; my__app__help) - opts="[SUBCOMMAND]..." + opts="test help" if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -52,6 +52,34 @@ _my-app() { COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 ;; + my__app__help__help) + opts="" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + my__app__help__test) + opts="" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; my__app__test) opts="-h -V --case --help --version" if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then diff --git a/clap_complete/tests/snapshots/feature_sample.elvish b/clap_complete/tests/snapshots/feature_sample.elvish index bc18cbdc69b..afb35cf0d05 100644 --- a/clap_complete/tests/snapshots/feature_sample.elvish +++ b/clap_complete/tests/snapshots/feature_sample.elvish @@ -37,6 +37,12 @@ set edit:completion:arg-completer[my-app] = {|@words| cand --version 'Print version information' } &'my-app;help'= { + cand test 'tests things' + cand help 'Print this message or the help of the given subcommand(s)' + } + &'my-app;help;test'= { + } + &'my-app;help;help'= { } ] $completions[$command] diff --git a/clap_complete/tests/snapshots/feature_sample.fish b/clap_complete/tests/snapshots/feature_sample.fish index aa9666dfeb6..b2126b2171a 100644 --- a/clap_complete/tests/snapshots/feature_sample.fish +++ b/clap_complete/tests/snapshots/feature_sample.fish @@ -6,3 +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" -l case -d 'the case to test' -r 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 test" -s V -l version -d 'Print version 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" -f -a "test" -d 'tests things' +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)' diff --git a/clap_complete/tests/snapshots/feature_sample.ps1 b/clap_complete/tests/snapshots/feature_sample.ps1 index bf1ec4d0f0e..679d431aa56 100644 --- a/clap_complete/tests/snapshots/feature_sample.ps1 +++ b/clap_complete/tests/snapshots/feature_sample.ps1 @@ -42,6 +42,14 @@ Register-ArgumentCompleter -Native -CommandName 'my-app' -ScriptBlock { break } 'my-app;help' { + [CompletionResult]::new('test', 'test', [CompletionResultType]::ParameterValue, 'tests things') + [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)') + break + } + 'my-app;help;test' { + break + } + 'my-app;help;help' { break } }) diff --git a/clap_complete/tests/snapshots/feature_sample.zsh b/clap_complete/tests/snapshots/feature_sample.zsh index f8a675117ac..8019ef3c881 100644 --- a/clap_complete/tests/snapshots/feature_sample.zsh +++ b/clap_complete/tests/snapshots/feature_sample.zsh @@ -45,12 +45,31 @@ _arguments "${_arguments_options[@]}" / ;; (help) _arguments "${_arguments_options[@]}" / -'*::subcommand -- The subcommand whose help message to display:' / +":: :_my-app__help_commands" / +"*::: :->help" / +&& ret=0 + + case $state in + (help) + words=($line[1] "${words[@]}") + (( CURRENT += 1 )) + curcontext="${curcontext%:*:*}:my-app-help-command-$line[1]:" + case $line[1] in + (test) +_arguments "${_arguments_options[@]}" / +&& ret=0 +;; +(help) +_arguments "${_arguments_options[@]}" / && ret=0 ;; esac ;; esac +;; + esac + ;; +esac } (( $+functions[_my-app_commands] )) || @@ -63,9 +82,22 @@ _my-app_commands() { } (( $+functions[_my-app__help_commands] )) || _my-app__help_commands() { - local commands; commands=() + local commands; commands=( +'test:tests things' / +'help:Print this message or the help of the given subcommand(s)' / + ) _describe -t commands 'my-app help commands' commands "$@" } +(( $+functions[_my-app__help__help_commands] )) || +_my-app__help__help_commands() { + local commands; commands=() + _describe -t commands 'my-app help help commands' commands "$@" +} +(( $+functions[_my-app__help__test_commands] )) || +_my-app__help__test_commands() { + local commands; commands=() + _describe -t commands 'my-app help test commands' commands "$@" +} (( $+functions[_my-app__test_commands] )) || _my-app__test_commands() { local commands; commands=() diff --git a/clap_complete/tests/snapshots/quoting.bash b/clap_complete/tests/snapshots/quoting.bash index 9ede25887c8..b831012b5d3 100644 --- a/clap_complete/tests/snapshots/quoting.bash +++ b/clap_complete/tests/snapshots/quoting.bash @@ -138,7 +138,7 @@ _my-app() { return 0 ;; my__app__help) - opts="[SUBCOMMAND]..." + opts="cmd-single-quotes cmd-double-quotes cmd-backticks cmd-backslash cmd-brackets cmd-expansions help" if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -151,6 +151,104 @@ _my-app() { COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 ;; + my__app__help__cmd__backslash) + opts="" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + my__app__help__cmd__backticks) + opts="" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + my__app__help__cmd__brackets) + opts="" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + my__app__help__cmd__double__quotes) + opts="" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + my__app__help__cmd__expansions) + opts="" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + my__app__help__cmd__single__quotes) + opts="" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + my__app__help__help) + opts="" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; esac } diff --git a/clap_complete/tests/snapshots/quoting.elvish b/clap_complete/tests/snapshots/quoting.elvish index 5c2c787be34..44b28cd8b50 100644 --- a/clap_complete/tests/snapshots/quoting.elvish +++ b/clap_complete/tests/snapshots/quoting.elvish @@ -61,6 +61,27 @@ set edit:completion:arg-completer[my-app] = {|@words| cand --help 'Print help information' } &'my-app;help'= { + cand cmd-single-quotes 'Can be ''always'', ''auto'', or ''never''' + cand cmd-double-quotes 'Can be "always", "auto", or "never"' + cand cmd-backticks 'For more information see `echo test`' + cand cmd-backslash 'Avoid ''/n''' + cand cmd-brackets 'List packages [filter]' + cand cmd-expansions 'Execute the shell command with $SHELL' + cand help 'Print this message or the help of the given subcommand(s)' + } + &'my-app;help;cmd-single-quotes'= { + } + &'my-app;help;cmd-double-quotes'= { + } + &'my-app;help;cmd-backticks'= { + } + &'my-app;help;cmd-backslash'= { + } + &'my-app;help;cmd-brackets'= { + } + &'my-app;help;cmd-expansions'= { + } + &'my-app;help;help'= { } ] $completions[$command] diff --git a/clap_complete/tests/snapshots/quoting.fish b/clap_complete/tests/snapshots/quoting.fish index c9e24fb7ae2..b13bf5c2ec3 100644 --- a/clap_complete/tests/snapshots/quoting.fish +++ b/clap_complete/tests/snapshots/quoting.fish @@ -19,3 +19,10 @@ complete -c my-app -n "__fish_seen_subcommand_from cmd-backticks" -s h -l help - complete -c my-app -n "__fish_seen_subcommand_from cmd-backslash" -s h -l help -d 'Print help information' complete -c my-app -n "__fish_seen_subcommand_from cmd-brackets" -s h -l help -d 'Print help information' complete -c my-app -n "__fish_seen_subcommand_from cmd-expansions" -s h -l help -d 'Print help information' +complete -c my-app -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from cmd-single-quotes; and not __fish_seen_subcommand_from cmd-double-quotes; and not __fish_seen_subcommand_from cmd-backticks; and not __fish_seen_subcommand_from cmd-backslash; and not __fish_seen_subcommand_from cmd-brackets; and not __fish_seen_subcommand_from cmd-expansions; and not __fish_seen_subcommand_from help" -f -a "cmd-single-quotes" -d 'Can be /'always/', /'auto/', or /'never/'' +complete -c my-app -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from cmd-single-quotes; and not __fish_seen_subcommand_from cmd-double-quotes; and not __fish_seen_subcommand_from cmd-backticks; and not __fish_seen_subcommand_from cmd-backslash; and not __fish_seen_subcommand_from cmd-brackets; and not __fish_seen_subcommand_from cmd-expansions; and not __fish_seen_subcommand_from help" -f -a "cmd-double-quotes" -d 'Can be "always", "auto", or "never"' +complete -c my-app -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from cmd-single-quotes; and not __fish_seen_subcommand_from cmd-double-quotes; and not __fish_seen_subcommand_from cmd-backticks; and not __fish_seen_subcommand_from cmd-backslash; and not __fish_seen_subcommand_from cmd-brackets; and not __fish_seen_subcommand_from cmd-expansions; and not __fish_seen_subcommand_from help" -f -a "cmd-backticks" -d 'For more information see `echo test`' +complete -c my-app -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from cmd-single-quotes; and not __fish_seen_subcommand_from cmd-double-quotes; and not __fish_seen_subcommand_from cmd-backticks; and not __fish_seen_subcommand_from cmd-backslash; and not __fish_seen_subcommand_from cmd-brackets; and not __fish_seen_subcommand_from cmd-expansions; and not __fish_seen_subcommand_from help" -f -a "cmd-backslash" -d 'Avoid /'//n/'' +complete -c my-app -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from cmd-single-quotes; and not __fish_seen_subcommand_from cmd-double-quotes; and not __fish_seen_subcommand_from cmd-backticks; and not __fish_seen_subcommand_from cmd-backslash; and not __fish_seen_subcommand_from cmd-brackets; and not __fish_seen_subcommand_from cmd-expansions; and not __fish_seen_subcommand_from help" -f -a "cmd-brackets" -d 'List packages [filter]' +complete -c my-app -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from cmd-single-quotes; and not __fish_seen_subcommand_from cmd-double-quotes; and not __fish_seen_subcommand_from cmd-backticks; and not __fish_seen_subcommand_from cmd-backslash; and not __fish_seen_subcommand_from cmd-brackets; and not __fish_seen_subcommand_from cmd-expansions; and not __fish_seen_subcommand_from help" -f -a "cmd-expansions" -d 'Execute the shell command with $SHELL' +complete -c my-app -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from cmd-single-quotes; and not __fish_seen_subcommand_from cmd-double-quotes; and not __fish_seen_subcommand_from cmd-backticks; and not __fish_seen_subcommand_from cmd-backslash; and not __fish_seen_subcommand_from cmd-brackets; and not __fish_seen_subcommand_from cmd-expansions; and not __fish_seen_subcommand_from help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)' diff --git a/clap_complete/tests/snapshots/quoting.ps1 b/clap_complete/tests/snapshots/quoting.ps1 index 78fa953f12f..9c75e98dd3a 100644 --- a/clap_complete/tests/snapshots/quoting.ps1 +++ b/clap_complete/tests/snapshots/quoting.ps1 @@ -71,6 +71,34 @@ Register-ArgumentCompleter -Native -CommandName 'my-app' -ScriptBlock { break } 'my-app;help' { + [CompletionResult]::new('cmd-single-quotes', 'cmd-single-quotes', [CompletionResultType]::ParameterValue, 'Can be ''always'', ''auto'', or ''never''') + [CompletionResult]::new('cmd-double-quotes', 'cmd-double-quotes', [CompletionResultType]::ParameterValue, 'Can be "always", "auto", or "never"') + [CompletionResult]::new('cmd-backticks', 'cmd-backticks', [CompletionResultType]::ParameterValue, 'For more information see `echo test`') + [CompletionResult]::new('cmd-backslash', 'cmd-backslash', [CompletionResultType]::ParameterValue, 'Avoid ''/n''') + [CompletionResult]::new('cmd-brackets', 'cmd-brackets', [CompletionResultType]::ParameterValue, 'List packages [filter]') + [CompletionResult]::new('cmd-expansions', 'cmd-expansions', [CompletionResultType]::ParameterValue, 'Execute the shell command with $SHELL') + [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)') + break + } + 'my-app;help;cmd-single-quotes' { + break + } + 'my-app;help;cmd-double-quotes' { + break + } + 'my-app;help;cmd-backticks' { + break + } + 'my-app;help;cmd-backslash' { + break + } + 'my-app;help;cmd-brackets' { + break + } + 'my-app;help;cmd-expansions' { + break + } + 'my-app;help;help' { break } }) diff --git a/clap_complete/tests/snapshots/quoting.zsh b/clap_complete/tests/snapshots/quoting.zsh index e1b09fc981e..9df120066ca 100644 --- a/clap_complete/tests/snapshots/quoting.zsh +++ b/clap_complete/tests/snapshots/quoting.zsh @@ -72,8 +72,47 @@ _arguments "${_arguments_options[@]}" / ;; (help) _arguments "${_arguments_options[@]}" / -'*::subcommand -- The subcommand whose help message to display:' / +":: :_my-app__help_commands" / +"*::: :->help" / && ret=0 + + case $state in + (help) + words=($line[1] "${words[@]}") + (( CURRENT += 1 )) + curcontext="${curcontext%:*:*}:my-app-help-command-$line[1]:" + case $line[1] in + (cmd-single-quotes) +_arguments "${_arguments_options[@]}" / +&& ret=0 +;; +(cmd-double-quotes) +_arguments "${_arguments_options[@]}" / +&& ret=0 +;; +(cmd-backticks) +_arguments "${_arguments_options[@]}" / +&& ret=0 +;; +(cmd-backslash) +_arguments "${_arguments_options[@]}" / +&& ret=0 +;; +(cmd-brackets) +_arguments "${_arguments_options[@]}" / +&& ret=0 +;; +(cmd-expansions) +_arguments "${_arguments_options[@]}" / +&& ret=0 +;; +(help) +_arguments "${_arguments_options[@]}" / +&& ret=0 +;; + esac + ;; +esac ;; esac ;; @@ -98,35 +137,78 @@ _my-app__cmd-backslash_commands() { local commands; commands=() _describe -t commands 'my-app cmd-backslash commands' commands "$@" } +(( $+functions[_my-app__help__cmd-backslash_commands] )) || +_my-app__help__cmd-backslash_commands() { + local commands; commands=() + _describe -t commands 'my-app help cmd-backslash commands' commands "$@" +} (( $+functions[_my-app__cmd-backticks_commands] )) || _my-app__cmd-backticks_commands() { local commands; commands=() _describe -t commands 'my-app cmd-backticks commands' commands "$@" } +(( $+functions[_my-app__help__cmd-backticks_commands] )) || +_my-app__help__cmd-backticks_commands() { + local commands; commands=() + _describe -t commands 'my-app help cmd-backticks commands' commands "$@" +} (( $+functions[_my-app__cmd-brackets_commands] )) || _my-app__cmd-brackets_commands() { local commands; commands=() _describe -t commands 'my-app cmd-brackets commands' commands "$@" } +(( $+functions[_my-app__help__cmd-brackets_commands] )) || +_my-app__help__cmd-brackets_commands() { + local commands; commands=() + _describe -t commands 'my-app help cmd-brackets commands' commands "$@" +} (( $+functions[_my-app__cmd-double-quotes_commands] )) || _my-app__cmd-double-quotes_commands() { local commands; commands=() _describe -t commands 'my-app cmd-double-quotes commands' commands "$@" } +(( $+functions[_my-app__help__cmd-double-quotes_commands] )) || +_my-app__help__cmd-double-quotes_commands() { + local commands; commands=() + _describe -t commands 'my-app help cmd-double-quotes commands' commands "$@" +} (( $+functions[_my-app__cmd-expansions_commands] )) || _my-app__cmd-expansions_commands() { local commands; commands=() _describe -t commands 'my-app cmd-expansions commands' commands "$@" } +(( $+functions[_my-app__help__cmd-expansions_commands] )) || +_my-app__help__cmd-expansions_commands() { + local commands; commands=() + _describe -t commands 'my-app help cmd-expansions commands' commands "$@" +} (( $+functions[_my-app__cmd-single-quotes_commands] )) || _my-app__cmd-single-quotes_commands() { local commands; commands=() _describe -t commands 'my-app cmd-single-quotes commands' commands "$@" } +(( $+functions[_my-app__help__cmd-single-quotes_commands] )) || +_my-app__help__cmd-single-quotes_commands() { + local commands; commands=() + _describe -t commands 'my-app help cmd-single-quotes commands' commands "$@" +} (( $+functions[_my-app__help_commands] )) || _my-app__help_commands() { - local commands; commands=() + local commands; commands=( +'cmd-single-quotes:Can be '/''always'/'', '/''auto'/'', or '/''never'/''' / +'cmd-double-quotes:Can be "always", "auto", or "never"' / +'cmd-backticks:For more information see `echo test`' / +'cmd-backslash:Avoid '/''//n'/''' / +'cmd-brackets:List packages /[filter/]' / +'cmd-expansions:Execute the shell command with $SHELL' / +'help:Print this message or the help of the given subcommand(s)' / + ) _describe -t commands 'my-app help commands' commands "$@" } +(( $+functions[_my-app__help__help_commands] )) || +_my-app__help__help_commands() { + local commands; commands=() + _describe -t commands 'my-app help help commands' commands "$@" +} _my-app "$@" diff --git a/clap_complete/tests/snapshots/special_commands.bash b/clap_complete/tests/snapshots/special_commands.bash index c1b9968748c..1fd80140a37 100644 --- a/clap_complete/tests/snapshots/special_commands.bash +++ b/clap_complete/tests/snapshots/special_commands.bash @@ -48,7 +48,7 @@ _my-app() { return 0 ;; my__app__help) - opts="[SUBCOMMAND]..." + opts="test some_cmd some-cmd-with-hyphens some-hidden-cmd help" if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -61,6 +61,76 @@ _my-app() { COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 ;; + my__app__help__help) + opts="" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + my__app__help__some__cmd__with__hyphens) + opts="" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + my__app__help__some__hidden__cmd) + opts="" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + my__app__help__some_cmd) + opts="" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + my__app__help__test) + opts="" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; my__app__some__cmd__with__hyphens) opts="-h -V --help --version" if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then diff --git a/clap_complete/tests/snapshots/special_commands.elvish b/clap_complete/tests/snapshots/special_commands.elvish index fec8ac8767c..e60f9591962 100644 --- a/clap_complete/tests/snapshots/special_commands.elvish +++ b/clap_complete/tests/snapshots/special_commands.elvish @@ -59,6 +59,21 @@ set edit:completion:arg-completer[my-app] = {|@words| cand --version 'Print version information' } &'my-app;help'= { + cand test 'tests things' + cand some_cmd 'tests other things' + cand some-cmd-with-hyphens 'some-cmd-with-hyphens' + cand some-hidden-cmd 'some-hidden-cmd' + cand help 'Print this message or the help of the given subcommand(s)' + } + &'my-app;help;test'= { + } + &'my-app;help;some_cmd'= { + } + &'my-app;help;some-cmd-with-hyphens'= { + } + &'my-app;help;some-hidden-cmd'= { + } + &'my-app;help;help'= { } ] $completions[$command] diff --git a/clap_complete/tests/snapshots/special_commands.fish b/clap_complete/tests/snapshots/special_commands.fish index d0359632cda..d1d58fe3134 100644 --- a/clap_complete/tests/snapshots/special_commands.fish +++ b/clap_complete/tests/snapshots/special_commands.fish @@ -16,3 +16,8 @@ complete -c my-app -n "__fish_seen_subcommand_from some-cmd-with-hyphens" -s h - complete -c my-app -n "__fish_seen_subcommand_from some-cmd-with-hyphens" -s V -l version -d 'Print version information' complete -c my-app -n "__fish_seen_subcommand_from some-hidden-cmd" -s h -l help -d 'Print help information' complete -c my-app -n "__fish_seen_subcommand_from some-hidden-cmd" -s V -l version -d 'Print version information' +complete -c my-app -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from test; and not __fish_seen_subcommand_from some_cmd; and not __fish_seen_subcommand_from some-cmd-with-hyphens; and not __fish_seen_subcommand_from some-hidden-cmd; and not __fish_seen_subcommand_from help" -f -a "test" -d 'tests things' +complete -c my-app -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from test; and not __fish_seen_subcommand_from some_cmd; and not __fish_seen_subcommand_from some-cmd-with-hyphens; and not __fish_seen_subcommand_from some-hidden-cmd; and not __fish_seen_subcommand_from help" -f -a "some_cmd" -d 'tests other things' +complete -c my-app -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from test; and not __fish_seen_subcommand_from some_cmd; and not __fish_seen_subcommand_from some-cmd-with-hyphens; and not __fish_seen_subcommand_from some-hidden-cmd; and not __fish_seen_subcommand_from help" -f -a "some-cmd-with-hyphens" +complete -c my-app -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from test; and not __fish_seen_subcommand_from some_cmd; and not __fish_seen_subcommand_from some-cmd-with-hyphens; and not __fish_seen_subcommand_from some-hidden-cmd; and not __fish_seen_subcommand_from help" -f -a "some-hidden-cmd" +complete -c my-app -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from test; and not __fish_seen_subcommand_from some_cmd; and not __fish_seen_subcommand_from some-cmd-with-hyphens; and not __fish_seen_subcommand_from some-hidden-cmd; and not __fish_seen_subcommand_from help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)' diff --git a/clap_complete/tests/snapshots/special_commands.ps1 b/clap_complete/tests/snapshots/special_commands.ps1 index 924328985e8..81c70160a39 100644 --- a/clap_complete/tests/snapshots/special_commands.ps1 +++ b/clap_complete/tests/snapshots/special_commands.ps1 @@ -67,6 +67,26 @@ Register-ArgumentCompleter -Native -CommandName 'my-app' -ScriptBlock { break } 'my-app;help' { + [CompletionResult]::new('test', 'test', [CompletionResultType]::ParameterValue, 'tests things') + [CompletionResult]::new('some_cmd', 'some_cmd', [CompletionResultType]::ParameterValue, 'tests other things') + [CompletionResult]::new('some-cmd-with-hyphens', 'some-cmd-with-hyphens', [CompletionResultType]::ParameterValue, 'some-cmd-with-hyphens') + [CompletionResult]::new('some-hidden-cmd', 'some-hidden-cmd', [CompletionResultType]::ParameterValue, 'some-hidden-cmd') + [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)') + break + } + 'my-app;help;test' { + break + } + 'my-app;help;some_cmd' { + break + } + 'my-app;help;some-cmd-with-hyphens' { + break + } + 'my-app;help;some-hidden-cmd' { + break + } + 'my-app;help;help' { break } }) diff --git a/clap_complete/tests/snapshots/special_commands.zsh b/clap_complete/tests/snapshots/special_commands.zsh index 7e57caf368a..405e503ba2b 100644 --- a/clap_complete/tests/snapshots/special_commands.zsh +++ b/clap_complete/tests/snapshots/special_commands.zsh @@ -71,12 +71,43 @@ _arguments "${_arguments_options[@]}" / ;; (help) _arguments "${_arguments_options[@]}" / -'*::subcommand -- The subcommand whose help message to display:' / +":: :_my-app__help_commands" / +"*::: :->help" / +&& ret=0 + + case $state in + (help) + words=($line[1] "${words[@]}") + (( CURRENT += 1 )) + curcontext="${curcontext%:*:*}:my-app-help-command-$line[1]:" + case $line[1] in + (test) +_arguments "${_arguments_options[@]}" / +&& ret=0 +;; +(some_cmd) +_arguments "${_arguments_options[@]}" / +&& ret=0 +;; +(some-cmd-with-hyphens) +_arguments "${_arguments_options[@]}" / +&& ret=0 +;; +(some-hidden-cmd) +_arguments "${_arguments_options[@]}" / +&& ret=0 +;; +(help) +_arguments "${_arguments_options[@]}" / && ret=0 ;; esac ;; esac +;; + esac + ;; +esac } (( $+functions[_my-app_commands] )) || @@ -92,24 +123,55 @@ _my-app_commands() { } (( $+functions[_my-app__help_commands] )) || _my-app__help_commands() { - local commands; commands=() + local commands; commands=( +'test:tests things' / +'some_cmd:tests other things' / +'some-cmd-with-hyphens:' / +'some-hidden-cmd:' / +'help:Print this message or the help of the given subcommand(s)' / + ) _describe -t commands 'my-app help commands' commands "$@" } +(( $+functions[_my-app__help__help_commands] )) || +_my-app__help__help_commands() { + local commands; commands=() + _describe -t commands 'my-app help help commands' commands "$@" +} +(( $+functions[_my-app__help__some-cmd-with-hyphens_commands] )) || +_my-app__help__some-cmd-with-hyphens_commands() { + local commands; commands=() + _describe -t commands 'my-app help some-cmd-with-hyphens commands' commands "$@" +} (( $+functions[_my-app__some-cmd-with-hyphens_commands] )) || _my-app__some-cmd-with-hyphens_commands() { local commands; commands=() _describe -t commands 'my-app some-cmd-with-hyphens commands' commands "$@" } +(( $+functions[_my-app__help__some-hidden-cmd_commands] )) || +_my-app__help__some-hidden-cmd_commands() { + local commands; commands=() + _describe -t commands 'my-app help some-hidden-cmd commands' commands "$@" +} (( $+functions[_my-app__some-hidden-cmd_commands] )) || _my-app__some-hidden-cmd_commands() { local commands; commands=() _describe -t commands 'my-app some-hidden-cmd commands' commands "$@" } +(( $+functions[_my-app__help__some_cmd_commands] )) || +_my-app__help__some_cmd_commands() { + local commands; commands=() + _describe -t commands 'my-app help some_cmd commands' commands "$@" +} (( $+functions[_my-app__some_cmd_commands] )) || _my-app__some_cmd_commands() { local commands; commands=() _describe -t commands 'my-app some_cmd commands' commands "$@" } +(( $+functions[_my-app__help__test_commands] )) || +_my-app__help__test_commands() { + local commands; commands=() + _describe -t commands 'my-app help test commands' commands "$@" +} (( $+functions[_my-app__test_commands] )) || _my-app__test_commands() { local commands; commands=() diff --git a/clap_complete/tests/snapshots/sub_subcommands.bash b/clap_complete/tests/snapshots/sub_subcommands.bash index 73b877c4f5e..1e05935e32c 100644 --- a/clap_complete/tests/snapshots/sub_subcommands.bash +++ b/clap_complete/tests/snapshots/sub_subcommands.bash @@ -45,7 +45,7 @@ _my-app() { return 0 ;; my__app__help) - opts="[SUBCOMMAND]..." + opts="test some_cmd help" if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -58,6 +58,62 @@ _my-app() { COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 ;; + my__app__help__help) + opts="" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + my__app__help__some_cmd) + opts="sub_cmd" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + my__app__help__some_cmd__sub_cmd) + opts="" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 4 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + my__app__help__test) + opts="" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; my__app__some_cmd) opts="-h -V --help --version sub_cmd help" if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then @@ -73,7 +129,7 @@ _my-app() { return 0 ;; my__app__some_cmd__help) - opts="[SUBCOMMAND]..." + opts="sub_cmd help" if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -86,6 +142,34 @@ _my-app() { COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 ;; + my__app__some_cmd__help__help) + opts="" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 4 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + my__app__some_cmd__help__sub_cmd) + opts="" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 4 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; my__app__some_cmd__sub_cmd) opts="-h -V --config --help --version" if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then diff --git a/clap_complete/tests/snapshots/sub_subcommands.elvish b/clap_complete/tests/snapshots/sub_subcommands.elvish index 58ba8e7c6db..bf5336ad527 100644 --- a/clap_complete/tests/snapshots/sub_subcommands.elvish +++ b/clap_complete/tests/snapshots/sub_subcommands.elvish @@ -53,8 +53,26 @@ set edit:completion:arg-completer[my-app] = {|@words| cand --version 'Print version information' } &'my-app;some_cmd;help'= { + cand sub_cmd 'sub-subcommand' + cand help 'Print this message or the help of the given subcommand(s)' + } + &'my-app;some_cmd;help;sub_cmd'= { + } + &'my-app;some_cmd;help;help'= { } &'my-app;help'= { + cand test 'tests things' + cand some_cmd 'top level subcommand' + cand help 'Print this message or the help of the given subcommand(s)' + } + &'my-app;help;test'= { + } + &'my-app;help;some_cmd'= { + cand sub_cmd 'sub-subcommand' + } + &'my-app;help;some_cmd;sub_cmd'= { + } + &'my-app;help;help'= { } ] $completions[$command] diff --git a/clap_complete/tests/snapshots/sub_subcommands.fish b/clap_complete/tests/snapshots/sub_subcommands.fish index 72805f911af..7996d5a028e 100644 --- a/clap_complete/tests/snapshots/sub_subcommands.fish +++ b/clap_complete/tests/snapshots/sub_subcommands.fish @@ -14,3 +14,9 @@ complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and not __fish_seen complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and __fish_seen_subcommand_from sub_cmd" -l config -d 'the other case to test' -r -f -a "{Lest quotes aren/'t escaped. }" complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and __fish_seen_subcommand_from sub_cmd" -s h -l help -d 'Print help information' complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and __fish_seen_subcommand_from sub_cmd" -s V -l version -d 'Print version information' +complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and __fish_seen_subcommand_from help; and not __fish_seen_subcommand_from sub_cmd; and not __fish_seen_subcommand_from help" -f -a "sub_cmd" -d 'sub-subcommand' +complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and __fish_seen_subcommand_from help; and not __fish_seen_subcommand_from sub_cmd; 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 not __fish_seen_subcommand_from test; and not __fish_seen_subcommand_from some_cmd; and not __fish_seen_subcommand_from help" -f -a "test" -d 'tests things' +complete -c my-app -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from test; and not __fish_seen_subcommand_from some_cmd; and not __fish_seen_subcommand_from help" -f -a "some_cmd" -d 'top level subcommand' +complete -c my-app -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from test; and not __fish_seen_subcommand_from some_cmd; 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 some_cmd; and not __fish_seen_subcommand_from sub_cmd" -f -a "sub_cmd" -d 'sub-subcommand' diff --git a/clap_complete/tests/snapshots/sub_subcommands.ps1 b/clap_complete/tests/snapshots/sub_subcommands.ps1 index fc0f051b7ff..37bde11d78b 100644 --- a/clap_complete/tests/snapshots/sub_subcommands.ps1 +++ b/clap_complete/tests/snapshots/sub_subcommands.ps1 @@ -60,9 +60,33 @@ Register-ArgumentCompleter -Native -CommandName 'my-app' -ScriptBlock { break } 'my-app;some_cmd;help' { + [CompletionResult]::new('sub_cmd', 'sub_cmd', [CompletionResultType]::ParameterValue, 'sub-subcommand') + [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)') + break + } + 'my-app;some_cmd;help;sub_cmd' { + break + } + 'my-app;some_cmd;help;help' { break } 'my-app;help' { + [CompletionResult]::new('test', 'test', [CompletionResultType]::ParameterValue, 'tests things') + [CompletionResult]::new('some_cmd', 'some_cmd', [CompletionResultType]::ParameterValue, 'top level subcommand') + [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)') + break + } + 'my-app;help;test' { + break + } + 'my-app;help;some_cmd' { + [CompletionResult]::new('sub_cmd', 'sub_cmd', [CompletionResultType]::ParameterValue, 'sub-subcommand') + break + } + 'my-app;help;some_cmd;sub_cmd' { + break + } + 'my-app;help;help' { break } }) diff --git a/clap_complete/tests/snapshots/sub_subcommands.zsh b/clap_complete/tests/snapshots/sub_subcommands.zsh index c26b9ff9ec3..918c76c14e0 100644 --- a/clap_complete/tests/snapshots/sub_subcommands.zsh +++ b/clap_complete/tests/snapshots/sub_subcommands.zsh @@ -70,21 +70,79 @@ _arguments "${_arguments_options[@]}" / ;; (help) _arguments "${_arguments_options[@]}" / -'*::subcommand -- The subcommand whose help message to display:' / +":: :_my-app__some_cmd__help_commands" / +"*::: :->help" / +&& ret=0 + + case $state in + (help) + words=($line[1] "${words[@]}") + (( CURRENT += 1 )) + curcontext="${curcontext%:*:*}:my-app-some_cmd-help-command-$line[1]:" + case $line[1] in + (sub_cmd) +_arguments "${_arguments_options[@]}" / +&& ret=0 +;; +(help) +_arguments "${_arguments_options[@]}" / && ret=0 ;; esac ;; esac +;; + esac + ;; +esac ;; (help) _arguments "${_arguments_options[@]}" / -'*::subcommand -- The subcommand whose help message to display:' / +":: :_my-app__help_commands" / +"*::: :->help" / +&& ret=0 + + case $state in + (help) + words=($line[1] "${words[@]}") + (( CURRENT += 1 )) + curcontext="${curcontext%:*:*}:my-app-help-command-$line[1]:" + case $line[1] in + (test) +_arguments "${_arguments_options[@]}" / +&& ret=0 +;; +(some_cmd) +_arguments "${_arguments_options[@]}" / +":: :_my-app__help__some_cmd_commands" / +"*::: :->some_cmd" / +&& ret=0 + + case $state in + (some_cmd) + words=($line[1] "${words[@]}") + (( CURRENT += 1 )) + curcontext="${curcontext%:*:*}:my-app-help-some_cmd-command-$line[1]:" + case $line[1] in + (sub_cmd) +_arguments "${_arguments_options[@]}" / && ret=0 ;; esac ;; esac +;; +(help) +_arguments "${_arguments_options[@]}" / +&& ret=0 +;; + esac + ;; +esac +;; + esac + ;; +esac } (( $+functions[_my-app_commands] )) || @@ -98,14 +156,38 @@ _my-app_commands() { } (( $+functions[_my-app__help_commands] )) || _my-app__help_commands() { - local commands; commands=() + local commands; commands=( +'test:tests things' / +'some_cmd:top level subcommand' / +'help:Print this message or the help of the given subcommand(s)' / + ) _describe -t commands 'my-app help commands' commands "$@" } +(( $+functions[_my-app__help__help_commands] )) || +_my-app__help__help_commands() { + local commands; commands=() + _describe -t commands 'my-app help help commands' commands "$@" +} (( $+functions[_my-app__some_cmd__help_commands] )) || _my-app__some_cmd__help_commands() { - local commands; commands=() + local commands; commands=( +'sub_cmd:sub-subcommand' / +'help:Print this message or the help of the given subcommand(s)' / + ) _describe -t commands 'my-app some_cmd help commands' commands "$@" } +(( $+functions[_my-app__some_cmd__help__help_commands] )) || +_my-app__some_cmd__help__help_commands() { + local commands; commands=() + _describe -t commands 'my-app some_cmd help help commands' commands "$@" +} +(( $+functions[_my-app__help__some_cmd_commands] )) || +_my-app__help__some_cmd_commands() { + local commands; commands=( +'sub_cmd:sub-subcommand' / + ) + _describe -t commands 'my-app help some_cmd commands' commands "$@" +} (( $+functions[_my-app__some_cmd_commands] )) || _my-app__some_cmd_commands() { local commands; commands=( @@ -114,11 +196,26 @@ _my-app__some_cmd_commands() { ) _describe -t commands 'my-app some_cmd commands' commands "$@" } +(( $+functions[_my-app__help__some_cmd__sub_cmd_commands] )) || +_my-app__help__some_cmd__sub_cmd_commands() { + local commands; commands=() + _describe -t commands 'my-app help some_cmd sub_cmd commands' commands "$@" +} +(( $+functions[_my-app__some_cmd__help__sub_cmd_commands] )) || +_my-app__some_cmd__help__sub_cmd_commands() { + local commands; commands=() + _describe -t commands 'my-app some_cmd help sub_cmd commands' commands "$@" +} (( $+functions[_my-app__some_cmd__sub_cmd_commands] )) || _my-app__some_cmd__sub_cmd_commands() { local commands; commands=() _describe -t commands 'my-app some_cmd sub_cmd commands' commands "$@" } +(( $+functions[_my-app__help__test_commands] )) || +_my-app__help__test_commands() { + local commands; commands=() + _describe -t commands 'my-app help test commands' commands "$@" +} (( $+functions[_my-app__test_commands] )) || _my-app__test_commands() { local commands; commands=() diff --git a/clap_complete_fig/tests/snapshots/basic.fig.js b/clap_complete_fig/tests/snapshots/basic.fig.js index ba7a90145fe..01439ff1f9c 100644 --- a/clap_complete_fig/tests/snapshots/basic.fig.js +++ b/clap_complete_fig/tests/snapshots/basic.fig.js @@ -22,16 +22,21 @@ const completion: Fig.Spec = { { name: "help", description: "Print this message or the help of the given subcommand(s)", + subcommands: [ + { + name: "test", + description: "Subcommand", + }, + { + name: "help", + description: "Print this message or the help of the given subcommand(s)", + }, + ], options: [ { name: "-c", }, ], - args: { - name: "subcommand", - isVariadic: true, - isOptional: true, - }, }, ], options: [ diff --git a/clap_complete_fig/tests/snapshots/feature_sample.fig.js b/clap_complete_fig/tests/snapshots/feature_sample.fig.js index f0799bc7c33..434bfe6badb 100644 --- a/clap_complete_fig/tests/snapshots/feature_sample.fig.js +++ b/clap_complete_fig/tests/snapshots/feature_sample.fig.js @@ -28,11 +28,16 @@ const completion: Fig.Spec = { { name: "help", description: "Print this message or the help of the given subcommand(s)", - args: { - name: "subcommand", - isVariadic: true, - isOptional: true, - }, + subcommands: [ + { + name: "test", + description: "tests things", + }, + { + name: "help", + description: "Print this message or the help of the given subcommand(s)", + }, + ], }, ], options: [ diff --git a/clap_complete_fig/tests/snapshots/quoting.fig.js b/clap_complete_fig/tests/snapshots/quoting.fig.js index 0dc80bcad6a..9142bd1af1a 100644 --- a/clap_complete_fig/tests/snapshots/quoting.fig.js +++ b/clap_complete_fig/tests/snapshots/quoting.fig.js @@ -65,11 +65,36 @@ const completion: Fig.Spec = { { name: "help", description: "Print this message or the help of the given subcommand(s)", - args: { - name: "subcommand", - isVariadic: true, - isOptional: true, - }, + subcommands: [ + { + name: "cmd-single-quotes", + description: "Can be 'always', 'auto', or 'never'", + }, + { + name: "cmd-double-quotes", + description: "Can be /"always/", /"auto/", or /"never/"", + }, + { + name: "cmd-backticks", + description: "For more information see `echo test`", + }, + { + name: "cmd-backslash", + description: "Avoid '//n'", + }, + { + name: "cmd-brackets", + description: "List packages [filter]", + }, + { + name: "cmd-expansions", + description: "Execute the shell command with $SHELL", + }, + { + name: "help", + description: "Print this message or the help of the given subcommand(s)", + }, + ], }, ], options: [ diff --git a/clap_complete_fig/tests/snapshots/special_commands.fig.js b/clap_complete_fig/tests/snapshots/special_commands.fig.js index ef1317c921e..bfdc87053e7 100644 --- a/clap_complete_fig/tests/snapshots/special_commands.fig.js +++ b/clap_complete_fig/tests/snapshots/special_commands.fig.js @@ -85,11 +85,27 @@ const completion: Fig.Spec = { { name: "help", description: "Print this message or the help of the given subcommand(s)", - args: { - name: "subcommand", - isVariadic: true, - isOptional: true, - }, + subcommands: [ + { + name: "test", + description: "tests things", + }, + { + name: "some_cmd", + description: "tests other things", + }, + { + name: ["some-cmd-with-hyphens", "hyphen"], + }, + { + name: "some-hidden-cmd", + hidden: true, + }, + { + name: "help", + description: "Print this message or the help of the given subcommand(s)", + }, + ], }, ], options: [ diff --git a/clap_complete_fig/tests/snapshots/sub_subcommands.fig.js b/clap_complete_fig/tests/snapshots/sub_subcommands.fig.js index 4e8293cc050..d5c95e6ad4f 100644 --- a/clap_complete_fig/tests/snapshots/sub_subcommands.fig.js +++ b/clap_complete_fig/tests/snapshots/sub_subcommands.fig.js @@ -58,11 +58,16 @@ const completion: Fig.Spec = { { name: "help", description: "Print this message or the help of the given subcommand(s)", - args: { - name: "subcommand", - isVariadic: true, - isOptional: true, - }, + subcommands: [ + { + name: "sub_cmd", + description: "sub-subcommand", + }, + { + name: "help", + description: "Print this message or the help of the given subcommand(s)", + }, + ], }, ], options: [ @@ -79,11 +84,26 @@ const completion: Fig.Spec = { { name: "help", description: "Print this message or the help of the given subcommand(s)", - args: { - name: "subcommand", - isVariadic: true, - isOptional: true, - }, + subcommands: [ + { + name: "test", + description: "tests things", + }, + { + name: "some_cmd", + description: "top level subcommand", + subcommands: [ + { + name: "sub_cmd", + description: "sub-subcommand", + }, + ], + }, + { + name: "help", + description: "Print this message or the help of the given subcommand(s)", + }, + ], }, ], options: [ diff --git a/src/builder/app_settings.rs b/src/builder/app_settings.rs index 5af79f46e8e..3de45c4df3f 100644 --- a/src/builder/app_settings.rs +++ b/src/builder/app_settings.rs @@ -50,9 +50,11 @@ pub(crate) enum AppSettings { DisableHelpSubcommand, DisableVersionFlag, PropagateVersion, + DisablePropagatedArgs, Hidden, HidePossibleValues, HelpExpected, + ExpandHelpSubcommandTrees, NoBinaryName, #[allow(dead_code)] ColorAuto, @@ -101,6 +103,8 @@ bitflags! { const INFER_LONG_ARGS = 1 << 43; const IGNORE_ERRORS = 1 << 44; const MULTICALL = 1 << 45; + const EXPAND_HELP_SUBCOMMAND_TREES = 1 << 46; + const DISABLE_PROPAGATED_ARGS = 1 << 47; const NO_OP = 0; } } @@ -140,10 +144,14 @@ impl_settings! { AppSettings, AppFlags, => Flags::DISABLE_VERSION_FLAG, PropagateVersion => Flags::PROPAGATE_VERSION, + DisablePropagatedArgs + => Flags::DISABLE_PROPAGATED_ARGS, HidePossibleValues => Flags::NO_POS_VALUES, HelpExpected => Flags::HELP_REQUIRED, + ExpandHelpSubcommandTrees + => Flags::EXPAND_HELP_SUBCOMMAND_TREES, Hidden => Flags::HIDDEN, Multicall diff --git a/src/builder/command.rs b/src/builder/command.rs index f2a8f328db4..be79f239e0e 100644 --- a/src/builder/command.rs +++ b/src/builder/command.rs @@ -3740,6 +3740,12 @@ impl Command { Ok(matcher.into_inner()) } + /// Prepare for completions by setting flags useful for that case. + /// Call this on the top-level [`Command`] before calling [`Command::build`]. + pub fn prepare_build_for_completion(&mut self) { + self.g_settings.set(AppSettings::ExpandHelpSubcommandTrees); + } + /// Prepare for introspecting on all included [`Command`]s /// /// Call this on the top-level [`Command`] when done building and before reading state for @@ -3782,7 +3788,9 @@ impl Command { self._propagate(); self._check_help_and_version(); - self._propagate_global_args(); + if !self.is_set(AppSettings::DisablePropagatedArgs) { + self._propagate_global_args(); + } let mut pos_counter = 1; let hide_pv = self.is_set(AppSettings::HidePossibleValues); @@ -4062,6 +4070,13 @@ impl Command { debug!("Command::_propagate_global_args:{}", self.name); for sc in &mut self.subcommands { + if sc.is_set(AppSettings::DisablePropagatedArgs) { + debug!( + "Command::_propagate skipping {}, has DisablePropagatedArgs", + sc.get_name() + ); + continue; + } for a in self.args.args().filter(|a| a.is_global_set()) { if sc.find(&a.id).is_some() { debug!( @@ -4140,15 +4155,40 @@ impl Command { if !self.is_set(AppSettings::DisableHelpSubcommand) { debug!("Command::_check_help_and_version: Building help subcommand"); - let mut help_subcmd = Command::new("help") - .about("Print this message or the help of the given subcommand(s)") - .arg( + let help_about = "Print this message or the help of the given subcommand(s)"; + + let mut help_subcmd = if self.is_set(AppSettings::ExpandHelpSubcommandTrees) { + // Slow code path to recursively clone all other subcommand subtrees under help + let help_subcmd = Command::new("help") + .about(help_about) + .global_setting(AppSettings::DisableHelpSubcommand) + .subcommands(self.get_subcommands().cloned().map(|mut sc| { + // Remove args so help completion will not suggest them, only subcommands + sc._clear_args_recursive(); + + sc.global_setting(AppSettings::DisablePropagatedArgs) + .global_setting(AppSettings::DisableHelpFlag) + .global_setting(AppSettings::DisableVersionFlag) + })); + + let mut help_help_subcmd = Command::new("help").about(help_about); + help_help_subcmd.version = None; + help_help_subcmd.long_version = None; + help_help_subcmd = help_help_subcmd + .setting(AppSettings::DisablePropagatedArgs) + .setting(AppSettings::DisableHelpFlag) + .setting(AppSettings::DisableVersionFlag); + + help_subcmd.subcommand(help_help_subcmd) + } else { + Command::new("help").about(help_about).arg( Arg::new("subcommand") .action(ArgAction::Append) .num_args(..) .value_name("SUBCOMMAND") .help("The subcommand whose help message to display"), - ); + ) + }; self._propagate_subcommand(&mut help_subcmd); // The parser acts like this is set, so let's set it so we don't falsely @@ -4164,6 +4204,15 @@ impl Command { } } + fn _clear_args_recursive(&mut self) { + self.args.clear(); + + if self.has_subcommands() { + self.get_subcommands_mut() + .for_each(Command::_clear_args_recursive); + } + } + pub(crate) fn _render_version(&self, use_long: bool) -> String { debug!("Command::_render_version"); diff --git a/src/mkeymap.rs b/src/mkeymap.rs index 3c660171331..e0bff186c88 100644 --- a/src/mkeymap.rs +++ b/src/mkeymap.rs @@ -150,6 +150,12 @@ impl MKeyMap { // since it's a cold function, using this wouldn't hurt much .map(|i| self.args.remove(i)) } + + /// Remove all args. + pub(crate) fn clear(&mut self) { + self.args.clear(); + self.keys.clear(); + } } impl Index<&'_ KeyType> for MKeyMap { From 729406661c2e4502de009c72a190f95d668f982e Mon Sep 17 00:00:00 2001 From: Andrew Shu Date: Thu, 25 Aug 2022 15:23:04 -0700 Subject: [PATCH 2/3] refactor(complete): Clean up help completion * Manual subtree copy to ensure correct behavior and settings * Always set ExpandHelpSubcommandTrees in Command::build * Remove redundant logic --- clap_complete/src/generator/mod.rs | 1 - clap_complete/src/generator/utils.rs | 6 +++ .../tests/snapshots/special_commands.fig.js | 3 +- src/builder/command.rs | 39 ++++++++----------- src/mkeymap.rs | 6 --- 5 files changed, 23 insertions(+), 32 deletions(-) diff --git a/clap_complete/src/generator/mod.rs b/clap_complete/src/generator/mod.rs index 7cf9f83dc7d..dd9c0584f22 100644 --- a/clap_complete/src/generator/mod.rs +++ b/clap_complete/src/generator/mod.rs @@ -234,7 +234,6 @@ where G: Generator, S: Into, { - cmd.prepare_build_for_completion(); cmd.build(); gen.generate(cmd, buf) diff --git a/clap_complete/src/generator/utils.rs b/clap_complete/src/generator/utils.rs index f5d530ccd0b..e956ee9a656 100644 --- a/clap_complete/src/generator/utils.rs +++ b/clap_complete/src/generator/utils.rs @@ -198,6 +198,12 @@ mod tests { ("help".to_string(), "my-cmd help".to_string()), ("config".to_string(), "my-cmd test config".to_string()), ("help".to_string(), "my-cmd test help".to_string()), + ("config".to_string(), "my-cmd test help config".to_string()), + ("help".to_string(), "my-cmd test help help".to_string()), + ("test".to_string(), "my-cmd help test".to_string()), + ("hello".to_string(), "my-cmd help hello".to_string()), + ("help".to_string(), "my-cmd help help".to_string()), + ("config".to_string(), "my-cmd help test config".to_string()), ] ); } diff --git a/clap_complete_fig/tests/snapshots/special_commands.fig.js b/clap_complete_fig/tests/snapshots/special_commands.fig.js index bfdc87053e7..76cd4c9e240 100644 --- a/clap_complete_fig/tests/snapshots/special_commands.fig.js +++ b/clap_complete_fig/tests/snapshots/special_commands.fig.js @@ -95,11 +95,10 @@ const completion: Fig.Spec = { description: "tests other things", }, { - name: ["some-cmd-with-hyphens", "hyphen"], + name: "some-cmd-with-hyphens", }, { name: "some-hidden-cmd", - hidden: true, }, { name: "help", diff --git a/src/builder/command.rs b/src/builder/command.rs index be79f239e0e..f31e013616b 100644 --- a/src/builder/command.rs +++ b/src/builder/command.rs @@ -3740,21 +3740,20 @@ impl Command { Ok(matcher.into_inner()) } - /// Prepare for completions by setting flags useful for that case. - /// Call this on the top-level [`Command`] before calling [`Command::build`]. - pub fn prepare_build_for_completion(&mut self) { - self.g_settings.set(AppSettings::ExpandHelpSubcommandTrees); - } - /// Prepare for introspecting on all included [`Command`]s /// /// Call this on the top-level [`Command`] when done building and before reading state for /// cases like completions, custom help output, etc. pub fn build(&mut self) { + self._prepare_build_for_completion(); self._build_recursive(); self._build_bin_names_internal(); } + fn _prepare_build_for_completion(&mut self) { + self.g_settings.set(AppSettings::ExpandHelpSubcommandTrees); + } + pub(crate) fn _build_recursive(&mut self) { self._build_self(); for subcmd in self.get_subcommands_mut() { @@ -3788,9 +3787,7 @@ impl Command { self._propagate(); self._check_help_and_version(); - if !self.is_set(AppSettings::DisablePropagatedArgs) { - self._propagate_global_args(); - } + self._propagate_global_args(); let mut pos_counter = 1; let hide_pv = self.is_set(AppSettings::HidePossibleValues); @@ -4162,14 +4159,7 @@ impl Command { let help_subcmd = Command::new("help") .about(help_about) .global_setting(AppSettings::DisableHelpSubcommand) - .subcommands(self.get_subcommands().cloned().map(|mut sc| { - // Remove args so help completion will not suggest them, only subcommands - sc._clear_args_recursive(); - - sc.global_setting(AppSettings::DisablePropagatedArgs) - .global_setting(AppSettings::DisableHelpFlag) - .global_setting(AppSettings::DisableVersionFlag) - })); + .subcommands(self.get_subcommands().map(Command::_copy_subtree_for_help)); let mut help_help_subcmd = Command::new("help").about(help_about); help_help_subcmd.version = None; @@ -4204,13 +4194,16 @@ impl Command { } } - fn _clear_args_recursive(&mut self) { - self.args.clear(); - - if self.has_subcommands() { - self.get_subcommands_mut() - .for_each(Command::_clear_args_recursive); + fn _copy_subtree_for_help(&self) -> Command { + let mut cmd = Command::new(self.get_name().to_string()) + .global_setting(AppSettings::DisablePropagatedArgs) + .global_setting(AppSettings::DisableHelpFlag) + .global_setting(AppSettings::DisableVersionFlag) + .subcommands(self.get_subcommands().map(Command::_copy_subtree_for_help)); + if self.get_about().is_some() { + cmd = cmd.about(self.get_about().unwrap().clone()); } + cmd } pub(crate) fn _render_version(&self, use_long: bool) -> String { diff --git a/src/mkeymap.rs b/src/mkeymap.rs index e0bff186c88..3c660171331 100644 --- a/src/mkeymap.rs +++ b/src/mkeymap.rs @@ -150,12 +150,6 @@ impl MKeyMap { // since it's a cold function, using this wouldn't hurt much .map(|i| self.args.remove(i)) } - - /// Remove all args. - pub(crate) fn clear(&mut self) { - self.args.clear(); - self.keys.clear(); - } } impl Index<&'_ KeyType> for MKeyMap { From 0d0be5160692209a0ccd01b31b0bdb5d48b0cd55 Mon Sep 17 00:00:00 2001 From: Andrew Shu Date: Fri, 26 Aug 2022 12:57:10 -0700 Subject: [PATCH 3/3] fix(complete): Fix help completion issues * Copy hide flag * Revert global args special handling. Another commit will address the issue of whether global args should be included in help subtrees. --- clap_complete/tests/snapshots/basic.bash | 4 ++-- clap_complete/tests/snapshots/basic.elvish | 2 ++ clap_complete/tests/snapshots/basic.fish | 2 ++ clap_complete/tests/snapshots/basic.ps1 | 2 ++ clap_complete/tests/snapshots/basic.zsh | 2 ++ clap_complete_fig/tests/snapshots/basic.fig.js | 10 ++++++++++ .../tests/snapshots/special_commands.fig.js | 1 + src/builder/app_settings.rs | 4 ---- src/builder/command.rs | 10 +--------- 9 files changed, 22 insertions(+), 15 deletions(-) diff --git a/clap_complete/tests/snapshots/basic.bash b/clap_complete/tests/snapshots/basic.bash index 39d6014f75f..f55933fd1e2 100644 --- a/clap_complete/tests/snapshots/basic.bash +++ b/clap_complete/tests/snapshots/basic.bash @@ -53,7 +53,7 @@ _my-app() { return 0 ;; my__app__help__help) - opts="" + opts="-c" if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -67,7 +67,7 @@ _my-app() { return 0 ;; my__app__help__test) - opts="" + opts="-c" if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 diff --git a/clap_complete/tests/snapshots/basic.elvish b/clap_complete/tests/snapshots/basic.elvish index abff7a00530..71494e466e4 100644 --- a/clap_complete/tests/snapshots/basic.elvish +++ b/clap_complete/tests/snapshots/basic.elvish @@ -37,8 +37,10 @@ set edit:completion:arg-completer[my-app] = {|@words| 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] diff --git a/clap_complete/tests/snapshots/basic.fish b/clap_complete/tests/snapshots/basic.fish index 1ee4a9d4dc0..54415fd69e9 100644 --- a/clap_complete/tests/snapshots/basic.fish +++ b/clap_complete/tests/snapshots/basic.fish @@ -9,3 +9,5 @@ complete -c my-app -n "__fish_seen_subcommand_from test" -s h -l help -d 'Print 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 diff --git a/clap_complete/tests/snapshots/basic.ps1 b/clap_complete/tests/snapshots/basic.ps1 index 9ef673923c3..242b7e2d7f4 100644 --- a/clap_complete/tests/snapshots/basic.ps1 +++ b/clap_complete/tests/snapshots/basic.ps1 @@ -43,9 +43,11 @@ Register-ArgumentCompleter -Native -CommandName 'my-app' -ScriptBlock { 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 } }) diff --git a/clap_complete/tests/snapshots/basic.zsh b/clap_complete/tests/snapshots/basic.zsh index 2050e865127..ad6c2aecab1 100644 --- a/clap_complete/tests/snapshots/basic.zsh +++ b/clap_complete/tests/snapshots/basic.zsh @@ -51,10 +51,12 @@ _arguments "${_arguments_options[@]}" / case $line[1] in (test) _arguments "${_arguments_options[@]}" / +'*-c[]' / && ret=0 ;; (help) _arguments "${_arguments_options[@]}" / +'*-c[]' / && ret=0 ;; esac diff --git a/clap_complete_fig/tests/snapshots/basic.fig.js b/clap_complete_fig/tests/snapshots/basic.fig.js index 01439ff1f9c..e488df4bd7c 100644 --- a/clap_complete_fig/tests/snapshots/basic.fig.js +++ b/clap_complete_fig/tests/snapshots/basic.fig.js @@ -26,10 +26,20 @@ 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: [ diff --git a/clap_complete_fig/tests/snapshots/special_commands.fig.js b/clap_complete_fig/tests/snapshots/special_commands.fig.js index 76cd4c9e240..6829eb5f643 100644 --- a/clap_complete_fig/tests/snapshots/special_commands.fig.js +++ b/clap_complete_fig/tests/snapshots/special_commands.fig.js @@ -99,6 +99,7 @@ const completion: Fig.Spec = { }, { name: "some-hidden-cmd", + hidden: true, }, { name: "help", diff --git a/src/builder/app_settings.rs b/src/builder/app_settings.rs index 3de45c4df3f..6b350796f03 100644 --- a/src/builder/app_settings.rs +++ b/src/builder/app_settings.rs @@ -50,7 +50,6 @@ pub(crate) enum AppSettings { DisableHelpSubcommand, DisableVersionFlag, PropagateVersion, - DisablePropagatedArgs, Hidden, HidePossibleValues, HelpExpected, @@ -104,7 +103,6 @@ bitflags! { const IGNORE_ERRORS = 1 << 44; const MULTICALL = 1 << 45; const EXPAND_HELP_SUBCOMMAND_TREES = 1 << 46; - const DISABLE_PROPAGATED_ARGS = 1 << 47; const NO_OP = 0; } } @@ -144,8 +142,6 @@ impl_settings! { AppSettings, AppFlags, => Flags::DISABLE_VERSION_FLAG, PropagateVersion => Flags::PROPAGATE_VERSION, - DisablePropagatedArgs - => Flags::DISABLE_PROPAGATED_ARGS, HidePossibleValues => Flags::NO_POS_VALUES, HelpExpected diff --git a/src/builder/command.rs b/src/builder/command.rs index f31e013616b..185750272af 100644 --- a/src/builder/command.rs +++ b/src/builder/command.rs @@ -4067,13 +4067,6 @@ impl Command { debug!("Command::_propagate_global_args:{}", self.name); for sc in &mut self.subcommands { - if sc.is_set(AppSettings::DisablePropagatedArgs) { - debug!( - "Command::_propagate skipping {}, has DisablePropagatedArgs", - sc.get_name() - ); - continue; - } for a in self.args.args().filter(|a| a.is_global_set()) { if sc.find(&a.id).is_some() { debug!( @@ -4165,7 +4158,6 @@ impl Command { help_help_subcmd.version = None; help_help_subcmd.long_version = None; help_help_subcmd = help_help_subcmd - .setting(AppSettings::DisablePropagatedArgs) .setting(AppSettings::DisableHelpFlag) .setting(AppSettings::DisableVersionFlag); @@ -4196,7 +4188,7 @@ impl Command { fn _copy_subtree_for_help(&self) -> Command { let mut cmd = Command::new(self.get_name().to_string()) - .global_setting(AppSettings::DisablePropagatedArgs) + .hide(self.is_hide_set()) .global_setting(AppSettings::DisableHelpFlag) .global_setting(AppSettings::DisableVersionFlag) .subcommands(self.get_subcommands().map(Command::_copy_subtree_for_help));