Skip to content

Commit b9c0aee

Browse files
committed
Feat: Add external subcommands test to suite
1 parent 1036060 commit b9c0aee

File tree

11 files changed

+405
-0
lines changed

11 files changed

+405
-0
lines changed
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
_my-app() {
2+
local i cur prev opts cmd
3+
COMPREPLY=()
4+
if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then
5+
cur="$2"
6+
else
7+
cur="${COMP_WORDS[COMP_CWORD]}"
8+
fi
9+
prev="$3"
10+
cmd=""
11+
opts=""
12+
13+
for i in "${COMP_WORDS[@]:0:COMP_CWORD}"
14+
do
15+
case "${cmd},${i}" in
16+
",$1")
17+
cmd="my__app"
18+
;;
19+
my__app,external)
20+
cmd="my__app__external"
21+
;;
22+
my__app,help)
23+
cmd="my__app__help"
24+
;;
25+
my__app__help,external)
26+
cmd="my__app__help__external"
27+
;;
28+
my__app__help,help)
29+
cmd="my__app__help__help"
30+
;;
31+
*)
32+
;;
33+
esac
34+
done
35+
36+
case "${cmd}" in
37+
my__app)
38+
opts="-h --help external help"
39+
if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
40+
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
41+
return 0
42+
fi
43+
case "${prev}" in
44+
*)
45+
COMPREPLY=()
46+
;;
47+
esac
48+
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
49+
return 0
50+
;;
51+
my__app__external)
52+
opts="-h --help"
53+
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
54+
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
55+
return 0
56+
fi
57+
case "${prev}" in
58+
*)
59+
COMPREPLY=()
60+
;;
61+
esac
62+
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
63+
return 0
64+
;;
65+
my__app__help)
66+
opts="external help"
67+
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
68+
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
69+
return 0
70+
fi
71+
case "${prev}" in
72+
*)
73+
COMPREPLY=()
74+
;;
75+
esac
76+
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
77+
return 0
78+
;;
79+
my__app__help__external)
80+
opts=""
81+
if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
82+
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
83+
return 0
84+
fi
85+
case "${prev}" in
86+
*)
87+
COMPREPLY=()
88+
;;
89+
esac
90+
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
91+
return 0
92+
;;
93+
my__app__help__help)
94+
opts=""
95+
if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
96+
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
97+
return 0
98+
fi
99+
case "${prev}" in
100+
*)
101+
COMPREPLY=()
102+
;;
103+
esac
104+
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
105+
return 0
106+
;;
107+
esac
108+
}
109+
110+
if [[ "${BASH_VERSINFO[0]}" -eq 4 && "${BASH_VERSINFO[1]}" -ge 4 || "${BASH_VERSINFO[0]}" -gt 4 ]]; then
111+
complete -F _my-app -o nosort -o bashdefault -o default my-app
112+
else
113+
complete -F _my-app -o bashdefault -o default my-app
114+
fi
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
2+
use builtin;
3+
use str;
4+
5+
set edit:completion:arg-completer[my-app] = {|@words|
6+
fn spaces {|n|
7+
builtin:repeat $n ' ' | str:join ''
8+
}
9+
fn cand {|text desc|
10+
edit:complex-candidate $text &display=$text' '(spaces (- 14 (wcswidth $text)))$desc
11+
}
12+
var command = 'my-app'
13+
for word $words[1..-1] {
14+
if (str:has-prefix $word '-') {
15+
break
16+
}
17+
set command = $command';'$word
18+
}
19+
var completions = [
20+
&'my-app'= {
21+
cand -h 'Print help'
22+
cand --help 'Print help'
23+
cand external 'An external subcommand'
24+
cand help 'Print this message or the help of the given subcommand(s)'
25+
}
26+
&'my-app;external'= {
27+
cand -h 'Print help'
28+
cand --help 'Print help'
29+
}
30+
&'my-app;help'= {
31+
cand external 'An external subcommand'
32+
cand help 'Print this message or the help of the given subcommand(s)'
33+
}
34+
&'my-app;help;external'= {
35+
}
36+
&'my-app;help;help'= {
37+
}
38+
]
39+
$completions[$command]
40+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Print an optspec for argparse to handle cmd's options that are independent of any subcommand.
2+
function __fish_my_app_global_optspecs
3+
string join \n h/help
4+
end
5+
6+
function __fish_my_app_needs_command
7+
# Figure out if the current invocation already has a command.
8+
set -l cmd (commandline -opc)
9+
set -e cmd[1]
10+
argparse -s (__fish_my_app_global_optspecs) -- $cmd 2>/dev/null
11+
or return
12+
if set -q argv[1]
13+
# Also print the command, so this can be used to figure out what it is.
14+
echo $argv[1]
15+
return 1
16+
end
17+
return 0
18+
end
19+
20+
function __fish_my_app_using_subcommand
21+
set -l cmd (__fish_my_app_needs_command)
22+
test -z "$cmd"
23+
and return 1
24+
contains -- $cmd[1] $argv
25+
end
26+
27+
complete -c my-app -n "__fish_my_app_needs_command" -s h -l help -d 'Print help'
28+
complete -c my-app -n "__fish_my_app_needs_command" -f -a "external" -d 'An external subcommand'
29+
complete -c my-app -n "__fish_my_app_needs_command" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
30+
complete -c my-app -n "__fish_my_app_using_subcommand external" -s h -l help -d 'Print help'
31+
complete -c my-app -n "__fish_my_app_using_subcommand help; and not __fish_seen_subcommand_from external help" -f -a "external" -d 'An external subcommand'
32+
complete -c my-app -n "__fish_my_app_using_subcommand help; and not __fish_seen_subcommand_from external help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
2+
using namespace System.Management.Automation
3+
using namespace System.Management.Automation.Language
4+
5+
Register-ArgumentCompleter -Native -CommandName 'my-app' -ScriptBlock {
6+
param($wordToComplete, $commandAst, $cursorPosition)
7+
8+
$commandElements = $commandAst.CommandElements
9+
$command = @(
10+
'my-app'
11+
for ($i = 1; $i -lt $commandElements.Count; $i++) {
12+
$element = $commandElements[$i]
13+
if ($element -isnot [StringConstantExpressionAst] -or
14+
$element.StringConstantType -ne [StringConstantType]::BareWord -or
15+
$element.Value.StartsWith('-') -or
16+
$element.Value -eq $wordToComplete) {
17+
break
18+
}
19+
$element.Value
20+
}) -join ';'
21+
22+
$completions = @(switch ($command) {
23+
'my-app' {
24+
[CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
25+
[CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
26+
[CompletionResult]::new('external', 'external', [CompletionResultType]::ParameterValue, 'An external subcommand')
27+
[CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)')
28+
break
29+
}
30+
'my-app;external' {
31+
[CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
32+
[CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
33+
break
34+
}
35+
'my-app;help' {
36+
[CompletionResult]::new('external', 'external', [CompletionResultType]::ParameterValue, 'An external subcommand')
37+
[CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)')
38+
break
39+
}
40+
'my-app;help;external' {
41+
break
42+
}
43+
'my-app;help;help' {
44+
break
45+
}
46+
})
47+
48+
$completions.Where{ $_.CompletionText -like "$wordToComplete*" } |
49+
Sort-Object -Property ListItemText
50+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#compdef my-app
2+
3+
autoload -U is-at-least
4+
5+
_my-app() {
6+
typeset -A opt_args
7+
typeset -a _arguments_options
8+
local ret=1
9+
10+
if is-at-least 5.2; then
11+
_arguments_options=(-s -S -C)
12+
else
13+
_arguments_options=(-s -C)
14+
fi
15+
16+
local context curcontext="$curcontext" state line
17+
_arguments "${_arguments_options[@]}" : \
18+
'-h[Print help]' \
19+
'--help[Print help]' \
20+
":: :_my-app_commands" \
21+
"*::: :->my-app" \
22+
&& ret=0
23+
case $state in
24+
(my-app)
25+
words=($line[1] "${words[@]}")
26+
(( CURRENT += 1 ))
27+
curcontext="${curcontext%:*:*}:my-app-command-$line[1]:"
28+
case $line[1] in
29+
(external)
30+
_arguments "${_arguments_options[@]}" : \
31+
'-h[Print help]' \
32+
'--help[Print help]' \
33+
&& ret=0
34+
;;
35+
(help)
36+
_arguments "${_arguments_options[@]}" : \
37+
":: :_my-app__help_commands" \
38+
"*::: :->help" \
39+
&& ret=0
40+
41+
case $state in
42+
(help)
43+
words=($line[1] "${words[@]}")
44+
(( CURRENT += 1 ))
45+
curcontext="${curcontext%:*:*}:my-app-help-command-$line[1]:"
46+
case $line[1] in
47+
(external)
48+
_arguments "${_arguments_options[@]}" : \
49+
&& ret=0
50+
;;
51+
(help)
52+
_arguments "${_arguments_options[@]}" : \
53+
&& ret=0
54+
;;
55+
esac
56+
;;
57+
esac
58+
;;
59+
esac
60+
;;
61+
esac
62+
}
63+
64+
(( $+functions[_my-app_commands] )) ||
65+
_my-app_commands() {
66+
local commands; commands=(
67+
'external:An external subcommand' \
68+
'help:Print this message or the help of the given subcommand(s)' \
69+
)
70+
_describe -t commands 'my-app commands' commands "$@"
71+
}
72+
(( $+functions[_my-app__external_commands] )) ||
73+
_my-app__external_commands() {
74+
local commands; commands=()
75+
_describe -t commands 'my-app external commands' commands "$@"
76+
}
77+
(( $+functions[_my-app__help_commands] )) ||
78+
_my-app__help_commands() {
79+
local commands; commands=(
80+
'external:An external subcommand' \
81+
'help:Print this message or the help of the given subcommand(s)' \
82+
)
83+
_describe -t commands 'my-app help commands' commands "$@"
84+
}
85+
(( $+functions[_my-app__help__external_commands] )) ||
86+
_my-app__help__external_commands() {
87+
local commands; commands=()
88+
_describe -t commands 'my-app help external commands' commands "$@"
89+
}
90+
(( $+functions[_my-app__help__help_commands] )) ||
91+
_my-app__help__help_commands() {
92+
local commands; commands=()
93+
_describe -t commands 'my-app help help commands' commands "$@"
94+
}
95+
96+
if [ "$funcstack[1]" = "_my-app" ]; then
97+
_my-app "$@"
98+
else
99+
compdef _my-app my-app
100+
fi

clap_complete/tests/testsuite/bash.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,18 @@ fn sub_subcommands() {
8282
);
8383
}
8484

85+
#[test]
86+
fn external_subcommands() {
87+
let name = "my-app";
88+
let cmd = common::external_subcommand(name);
89+
common::assert_matches(
90+
snapbox::file!["../snapshots/external_subcommands.bash"],
91+
clap_complete::shells::Bash,
92+
cmd,
93+
name,
94+
);
95+
}
96+
8597
#[test]
8698
fn custom_bin_name() {
8799
let name = "my-app";

clap_complete/tests/testsuite/common.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,15 @@ pub(crate) fn special_commands_command(name: &'static str) -> clap::Command {
7575
.subcommand(clap::Command::new("some-hidden-cmd").hide(true))
7676
}
7777

78+
pub(crate) fn external_subcommand(name: &'static str) -> clap::Command {
79+
clap::Command::new(name)
80+
.subcommand(
81+
clap::Command::new("external")
82+
.allow_external_subcommands(true)
83+
.about("An external subcommand")
84+
)
85+
}
86+
7887
pub(crate) fn quoting_command(name: &'static str) -> clap::Command {
7988
clap::Command::new(name)
8089
.version("3.0")

clap_complete/tests/testsuite/elvish.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,18 @@ fn sub_subcommands() {
8181
);
8282
}
8383

84+
#[test]
85+
fn external_subcommands() {
86+
let name = "my-app";
87+
let cmd = common::external_subcommand(name);
88+
common::assert_matches(
89+
snapbox::file!["../snapshots/external_subcommands.elvish"],
90+
clap_complete::shells::Elvish,
91+
cmd,
92+
name,
93+
);
94+
}
95+
8496
#[test]
8597
fn custom_bin_name() {
8698
let name = "my-app";

0 commit comments

Comments
 (0)