Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(clap_complete): Use bin name instead of package name for bash completions in subcommands #5256

Merged
merged 2 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions clap_complete/src/shells/bash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!(
Expand Down Expand Up @@ -65,18 +67,18 @@ 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()
);
}
}

fn all_subcommands(cmd: &Command) -> String {
fn all_subcommands(cmd: &Command, parent_fn_name: &str) -> String {
debug!("all_subcommands");

fn add_command(
Expand Down Expand Up @@ -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();

Expand Down
110 changes: 110 additions & 0 deletions clap_complete/tests/snapshots/custom_bin_name.bash
Original file line number Diff line number Diff line change
@@ -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
44 changes: 44 additions & 0 deletions clap_complete/tests/snapshots/custom_bin_name.elvish
Original file line number Diff line number Diff line change
@@ -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]
}
10 changes: 10 additions & 0 deletions clap_complete/tests/snapshots/custom_bin_name.fish
Original file line number Diff line number Diff line change
@@ -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)'
54 changes: 54 additions & 0 deletions clap_complete/tests/snapshots/custom_bin_name.ps1
Original file line number Diff line number Diff line change
@@ -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
}
104 changes: 104 additions & 0 deletions clap_complete/tests/snapshots/custom_bin_name.zsh
Original file line number Diff line number Diff line change
@@ -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
13 changes: 13 additions & 0 deletions clap_complete/tests/testsuite/bash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
Loading
Loading