diff --git a/clap_complete/src/generator/utils.rs b/clap_complete/src/generator/utils.rs index f5d530cc..e956ee9a 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/tests/snapshots/basic.bash b/clap_complete/tests/snapshots/basic.bash index 4690e8b8..f55933fd 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="-c" + 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="-c" + 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 ca7c71fd..71494e46 100644 --- a/clap_complete/tests/snapshots/basic.elvish +++ b/clap_complete/tests/snapshots/basic.elvish @@ -33,6 +33,14 @@ 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'= { + 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 e836a340..54415fd6 100644 --- a/clap_complete/tests/snapshots/basic.fish +++ b/clap_complete/tests/snapshots/basic.fish @@ -6,4 +6,8 @@ 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)' +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 96af4b57..242b7e2d 100644 --- a/clap_complete/tests/snapshots/basic.ps1 +++ b/clap_complete/tests/snapshots/basic.ps1 @@ -37,6 +37,16 @@ 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 } diff --git a/clap_complete/tests/snapshots/basic.zsh b/clap_complete/tests/snapshots/basic.zsh index c72bc6dc..ad6c2aec 100644 --- a/clap_complete/tests/snapshots/basic.zsh +++ b/clap_complete/tests/snapshots/basic.zsh @@ -39,8 +39,29 @@ _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[@]}" / +'*-c[]' / +&& ret=0 +;; +(help) +_arguments "${_arguments_options[@]}" / +'*-c[]' / +&& ret=0 +;; + esac + ;; +esac ;; esac ;; @@ -57,9 +78,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 26010356..5bbb5762 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 bc18cbdc..afb35cf0 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 aa9666df..b2126b21 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 bf1ec4d0..679d431a 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 f8a67511..8019ef3c 100644 --- a/clap_complete/tests/snapshots/feature_sample.zsh +++ b/clap_complete/tests/snapshots/feature_sample.zsh @@ -45,8 +45,27 @@ _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 ;; @@ -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 9ede2588..b831012b 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 5c2c787b..44b28cd8 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 c9e24fb7..b13bf5c2 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 78fa953f..9c75e98d 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 e1b09fc9..9df12006 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 c1b99687..1fd80140 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 fec8ac87..e60f9591 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 d0359632..d1d58fe3 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 92432898..81c70160 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 7e57caf3..405e503b 100644 --- a/clap_complete/tests/snapshots/special_commands.zsh +++ b/clap_complete/tests/snapshots/special_commands.zsh @@ -71,8 +71,39 @@ _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 ;; @@ -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 73b877c4..1e05935e 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 58ba8e7c..bf5336ad 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 72805f91..7996d5a0 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 fc0f051b..37bde11d 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 c26b9ff9..918c76c1 100644 --- a/clap_complete/tests/snapshots/sub_subcommands.zsh +++ b/clap_complete/tests/snapshots/sub_subcommands.zsh @@ -70,7 +70,62 @@ _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[@]}" / +":: :_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 @@ -79,12 +134,15 @@ esac ;; (help) _arguments "${_arguments_options[@]}" / -'*::subcommand -- The subcommand whose help message to display:' / && 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 ba7a9014..e488df4b 100644 --- a/clap_complete_fig/tests/snapshots/basic.fig.js +++ b/clap_complete_fig/tests/snapshots/basic.fig.js @@ -22,16 +22,31 @@ const completion: Fig.Spec = { { name: "help", description: "Print this message or the help of the given subcommand(s)", + subcommands: [ + { + 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", }, ], - 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 f0799bc7..434bfe6b 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 0dc80bca..9142bd1a 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 ef1317c9..6829eb5f 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", + }, + { + 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 4e8293cc..d5c95e6a 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 5af79f46..6b350796 100644 --- a/src/builder/app_settings.rs +++ b/src/builder/app_settings.rs @@ -53,6 +53,7 @@ pub(crate) enum AppSettings { Hidden, HidePossibleValues, HelpExpected, + ExpandHelpSubcommandTrees, NoBinaryName, #[allow(dead_code)] ColorAuto, @@ -101,6 +102,7 @@ bitflags! { const INFER_LONG_ARGS = 1 << 43; const IGNORE_ERRORS = 1 << 44; const MULTICALL = 1 << 45; + const EXPAND_HELP_SUBCOMMAND_TREES = 1 << 46; const NO_OP = 0; } } @@ -144,6 +146,8 @@ impl_settings! { AppSettings, AppFlags, => 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 18cdfe1f..d4f6212f 100644 --- a/src/builder/command.rs +++ b/src/builder/command.rs @@ -3749,10 +3749,15 @@ impl Command { /// 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() { @@ -4144,15 +4149,32 @@ 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().map(Command::_copy_subtree_for_help)); + + 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::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 @@ -4168,6 +4190,18 @@ impl Command { } } + fn _copy_subtree_for_help(&self) -> Command { + let mut cmd = Command::new(self.get_name().to_string()) + .hide(self.is_hide_set()) + .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 { debug!("Command::_render_version");