Merge pull request #5256 from Serock3/master

fix(clap_complete): Use bin name instead of package name for bash completions in subcommands
This commit is contained in:
Ed Page 2024-01-19 10:45:28 -06:00 committed by GitHub
commit e1c3575044
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 393 additions and 5 deletions

View file

@ -18,6 +18,8 @@ impl Generator for Bash {
.get_bin_name()
.expect("crate::generate should have set the bin_name");
let fn_name = bin_name.replace('-', "__");
w!(
buf,
format!(
@ -65,10 +67,10 @@ else
fi
",
name = bin_name,
cmd = bin_name.replace('-', "__"),
cmd = fn_name,
name_opts = all_options_for_path(cmd, bin_name),
name_opts_details = option_details_for_path(cmd, bin_name),
subcmds = all_subcommands(cmd),
subcmds = all_subcommands(cmd, &fn_name),
subcmd_details = subcommand_details(cmd)
)
.as_bytes()
@ -76,7 +78,7 @@ fi
}
}
fn all_subcommands(cmd: &Command) -> String {
fn all_subcommands(cmd: &Command, parent_fn_name: &str) -> String {
debug!("all_subcommands");
fn add_command(
@ -106,9 +108,8 @@ fn all_subcommands(cmd: &Command) -> String {
}
}
let mut subcmds = vec![];
let fn_name = cmd.get_name().replace('-', "__");
for subcmd in cmd.get_subcommands() {
add_command(&fn_name, subcmd, &mut subcmds);
add_command(parent_fn_name, subcmd, &mut subcmds);
}
subcmds.sort();

View file

@ -0,0 +1,110 @@
_bin-name() {
local i cur prev opts cmd
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
cmd=""
opts=""
for i in ${COMP_WORDS[@]}
do
case "${cmd},${i}" in
",$1")
cmd="bin__name"
;;
bin__name,help)
cmd="bin__name__help"
;;
bin__name,test)
cmd="bin__name__test"
;;
bin__name__help,help)
cmd="bin__name__help__help"
;;
bin__name__help,test)
cmd="bin__name__help__test"
;;
*)
;;
esac
done
case "${cmd}" in
bin__name)
opts="-c -v -h --help test help"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
fi
case "${prev}" in
*)
COMPREPLY=()
;;
esac
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
bin__name__help)
opts="test help"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
fi
case "${prev}" in
*)
COMPREPLY=()
;;
esac
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
bin__name__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
;;
bin__name__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
;;
bin__name__test)
opts="-d -c -h --help"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
fi
case "${prev}" in
*)
COMPREPLY=()
;;
esac
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
esac
}
if [[ "${BASH_VERSINFO[0]}" -eq 4 && "${BASH_VERSINFO[1]}" -ge 4 || "${BASH_VERSINFO[0]}" -gt 4 ]]; then
complete -F _bin-name -o nosort -o bashdefault -o default bin-name
else
complete -F _bin-name -o bashdefault -o default bin-name
fi

View file

@ -0,0 +1,44 @@
use builtin;
use str;
set edit:completion:arg-completer[bin-name] = {|@words|
fn spaces {|n|
builtin:repeat $n ' ' | str:join ''
}
fn cand {|text desc|
edit:complex-candidate $text &display=$text' '(spaces (- 14 (wcswidth $text)))$desc
}
var command = 'bin-name'
for word $words[1..-1] {
if (str:has-prefix $word '-') {
break
}
set command = $command';'$word
}
var completions = [
&'bin-name'= {
cand -c 'c'
cand -v 'v'
cand -h 'Print help'
cand --help 'Print help'
cand test 'Subcommand'
cand help 'Print this message or the help of the given subcommand(s)'
}
&'bin-name;test'= {
cand -d 'd'
cand -c 'c'
cand -h 'Print help'
cand --help 'Print help'
}
&'bin-name;help'= {
cand test 'Subcommand'
cand help 'Print this message or the help of the given subcommand(s)'
}
&'bin-name;help;test'= {
}
&'bin-name;help;help'= {
}
]
$completions[$command]
}

View file

@ -0,0 +1,10 @@
complete -c bin-name -n "__fish_use_subcommand" -s c
complete -c bin-name -n "__fish_use_subcommand" -s v
complete -c bin-name -n "__fish_use_subcommand" -s h -l help -d 'Print help'
complete -c bin-name -n "__fish_use_subcommand" -f -a "test" -d 'Subcommand'
complete -c bin-name -n "__fish_use_subcommand" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
complete -c bin-name -n "__fish_seen_subcommand_from test" -s d
complete -c bin-name -n "__fish_seen_subcommand_from test" -s c
complete -c bin-name -n "__fish_seen_subcommand_from test" -s h -l help -d 'Print help'
complete -c bin-name -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 bin-name -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)'

View file

@ -0,0 +1,54 @@
using namespace System.Management.Automation
using namespace System.Management.Automation.Language
Register-ArgumentCompleter -Native -CommandName 'bin-name' -ScriptBlock {
param($wordToComplete, $commandAst, $cursorPosition)
$commandElements = $commandAst.CommandElements
$command = @(
'bin-name'
for ($i = 1; $i -lt $commandElements.Count; $i++) {
$element = $commandElements[$i]
if ($element -isnot [StringConstantExpressionAst] -or
$element.StringConstantType -ne [StringConstantType]::BareWord -or
$element.Value.StartsWith('-') -or
$element.Value -eq $wordToComplete) {
break
}
$element.Value
}) -join ';'
$completions = @(switch ($command) {
'bin-name' {
[CompletionResult]::new('-c', 'c', [CompletionResultType]::ParameterName, 'c')
[CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'v')
[CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
[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
}
'bin-name;test' {
[CompletionResult]::new('-d', 'd', [CompletionResultType]::ParameterName, 'd')
[CompletionResult]::new('-c', 'c', [CompletionResultType]::ParameterName, 'c')
[CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
break
}
'bin-name;help' {
[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
}
'bin-name;help;test' {
break
}
'bin-name;help;help' {
break
}
})
$completions.Where{ $_.CompletionText -like "$wordToComplete*" } |
Sort-Object -Property ListItemText
}

View file

@ -0,0 +1,104 @@
#compdef bin-name
autoload -U is-at-least
_bin-name() {
typeset -A opt_args
typeset -a _arguments_options
local ret=1
if is-at-least 5.2; then
_arguments_options=(-s -S -C)
else
_arguments_options=(-s -C)
fi
local context curcontext="$curcontext" state line
_arguments "${_arguments_options[@]}" \
'-c[]' \
'(-c)-v[]' \
'-h[Print help]' \
'--help[Print help]' \
":: :_bin-name_commands" \
"*::: :->my-app" \
&& ret=0
case $state in
(my-app)
words=($line[1] "${words[@]}")
(( CURRENT += 1 ))
curcontext="${curcontext%:*:*}:bin-name-command-$line[1]:"
case $line[1] in
(test)
_arguments "${_arguments_options[@]}" \
'*-d[]' \
'-c[]' \
'-h[Print help]' \
'--help[Print help]' \
&& ret=0
;;
(help)
_arguments "${_arguments_options[@]}" \
":: :_bin-name__help_commands" \
"*::: :->help" \
&& ret=0
case $state in
(help)
words=($line[1] "${words[@]}")
(( CURRENT += 1 ))
curcontext="${curcontext%:*:*}:bin-name-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[_bin-name_commands] )) ||
_bin-name_commands() {
local commands; commands=(
'test:Subcommand' \
'help:Print this message or the help of the given subcommand(s)' \
)
_describe -t commands 'bin-name commands' commands "$@"
}
(( $+functions[_bin-name__help_commands] )) ||
_bin-name__help_commands() {
local commands; commands=(
'test:Subcommand' \
'help:Print this message or the help of the given subcommand(s)' \
)
_describe -t commands 'bin-name help commands' commands "$@"
}
(( $+functions[_bin-name__help__help_commands] )) ||
_bin-name__help__help_commands() {
local commands; commands=()
_describe -t commands 'bin-name help help commands' commands "$@"
}
(( $+functions[_bin-name__help__test_commands] )) ||
_bin-name__help__test_commands() {
local commands; commands=()
_describe -t commands 'bin-name help test commands' commands "$@"
}
(( $+functions[_bin-name__test_commands] )) ||
_bin-name__test_commands() {
local commands; commands=()
_describe -t commands 'bin-name test commands' commands "$@"
}
if [ "$funcstack[1]" = "_bin-name" ]; then
_bin-name "$@"
else
compdef _bin-name bin-name
fi

View file

@ -72,6 +72,19 @@ fn sub_subcommands() {
);
}
#[test]
fn custom_bin_name() {
let name = "my-app";
let bin_name = "bin-name";
let cmd = common::basic_command(name);
common::assert_matches_path(
"tests/snapshots/custom_bin_name.bash",
clap_complete::shells::Bash,
cmd,
bin_name,
);
}
#[test]
fn value_hint() {
let name = "my-app";

View file

@ -72,6 +72,19 @@ fn sub_subcommands() {
);
}
#[test]
fn custom_bin_name() {
let name = "my-app";
let bin_name = "bin-name";
let cmd = common::basic_command(name);
common::assert_matches_path(
"tests/snapshots/custom_bin_name.elvish",
clap_complete::shells::Elvish,
cmd,
bin_name,
);
}
#[test]
fn value_hint() {
let name = "my-app";

View file

@ -72,6 +72,19 @@ fn sub_subcommands() {
);
}
#[test]
fn custom_bin_name() {
let name = "my-app";
let bin_name = "bin-name";
let cmd = common::basic_command(name);
common::assert_matches_path(
"tests/snapshots/custom_bin_name.fish",
clap_complete::shells::Fish,
cmd,
bin_name,
);
}
#[test]
fn value_hint() {
let name = "my-app";

View file

@ -72,6 +72,19 @@ fn sub_subcommands() {
);
}
#[test]
fn custom_bin_name() {
let name = "my-app";
let bin_name = "bin-name";
let cmd = common::basic_command(name);
common::assert_matches_path(
"tests/snapshots/custom_bin_name.ps1",
clap_complete::shells::PowerShell,
cmd,
bin_name,
);
}
#[test]
fn value_hint() {
let name = "my-app";

View file

@ -72,6 +72,19 @@ fn sub_subcommands() {
);
}
#[test]
fn custom_bin_name() {
let name = "my-app";
let bin_name = "bin-name";
let cmd = common::basic_command(name);
common::assert_matches_path(
"tests/snapshots/custom_bin_name.zsh",
clap_complete::shells::Zsh,
cmd,
bin_name,
);
}
#[test]
fn value_hint() {
let name = "my-app";