Open mjpieters opened 1 year ago
bin_name
would not work for this
What we should do is add an assert that name
does not have a space.
bin_name
would not work for this
- Its for usage and includes all parents
- It can be affected by what the current process is called
Then why is the second half of the generated output using get_bin_name()
, via utils::subcommands()
? Because those are valid:
$ tail -n75 /tmp/sample_output/mcre_clap_generate.bash
case "${cmd}" in
mcre_clap_generate)
opts="-h --help completions 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
;;
mcre_clap_generate__completions)
opts="-h --help <OUTPUT_DIRECTORY>"
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
;;
mcre_clap_generate__help)
opts="completions 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
;;
mcre_clap_generate__help__completions)
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
;;
mcre_clap_generate__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
}
I've understood the structure of the bash completion function to be roughly this:
for i in ${COMP_WORDS[@]}
do
case "${cmd},${i}" in
# expand cmd to cmd__possible_part2_word
esac
done
case "${cmd}" in
# provide completion words for each group and subcommand
esac
The first part is generated by shells::bash::Bash::all_subcommands()
, the second part mostly by shells::bash::Bash::subcommand_details()
(the first option uses cmd.get_bin_name()
). The latter uses crate::generator::utils::all_subcommands()
, a method that produces a vector of vec![sc.get_name().to_string(), sc.get_bin_name().unwrap().to_string()]
two-value vectors, and the details are generated using only the second element from those (so sc.get_bin_name().unwrap().to_string()
).
Hence my assumption that the first part should also use those exact same strings.
I triggered something very similar by having a crate named foo_bar
(because foo
was taken), with the binary in src/bin/foo/main.rs
and thus named simply foo
. I called clap_complete::generate("bash", &mut command, "foo", &mut std::io::stdout());
and the completion looked like
for i in ${COMP_WORDS[@]}
do
case "${cmd},${i}" in
",$1")
cmd="foo"
;;
foo__bar,quux)
cmd="foo__bar__quux"
;;
Once I added #[command(name = "foo")]
into my derived clap::Parser
struct, the completion script switched from foo__bar
to foo
.
Please complete the following tasks
Rust Version
rustc 1.67.0 (fc594f156 2023-01-24)
Clap Version
4.2.1
Minimal reproducible code
Cargo.toml
main.rs
:Steps to reproduce the bug with the above code
Actual Behaviour
The generated bash and zsh completions files are not valid, because either generator uses
cmd.get_name()
instead ofcmd.get_bin_name()
as the parent command.You can see this most easily when trying to execute the generated bash output:
The Zsh generated output is similarly broken; using the
shellcheck
linter:Expected Behaviour
The parent name for a completion subcommand should be
cmd.get_bin_name()
(in the MRCE:mrce_clap_generate
), and notcmd.get_name()
(MCRE for clap generate output
in the MRCE).If I manually replace
MCRE for clap generate output
withmcre_clap_generate
in the generated output, the completions work as expected.Additional Context
No response
Debug Output