fix(completions): improve correctness of completions when whitespace is involved

compgen takes exactly one "word" argument; if multiple are passed, it
will ignore all but the first. If `$cur` is not quoted and contains
whitespace, it will be expanded into multiple words, so the completions
will be based only on the first word of `$cur`, which is clearly not
correct.

To fix this, quote `$cur` to prevent word splitting, where necessary
(Bash does not perform word splitting inside the extended test command
`[[`, so quotes aren't necessary there).
This commit is contained in:
Josh Holland 2019-03-31 17:16:04 +01:00 committed by Pavan Kumar Sunkara
parent 0b58088781
commit 5948754d2f
2 changed files with 25 additions and 25 deletions

View file

@ -43,7 +43,7 @@ impl Generator for Bash {
{cmd})
opts=\"{name_opts}\"
if [[ ${{cur}} == -* || ${{COMP_CWORD}} -eq 1 ]] ; then
COMPREPLY=( $(compgen -W \"${{opts}}\" -- ${{cur}}) )
COMPREPLY=( $(compgen -W \"${{opts}}\" -- \"${{cur}}\") )
return 0
fi
case \"${{prev}}\" in
@ -52,7 +52,7 @@ impl Generator for Bash {
COMPREPLY=()
;;
esac
COMPREPLY=( $(compgen -W \"${{opts}}\" -- ${{cur}}) )
COMPREPLY=( $(compgen -W \"${{opts}}\" -- \"${{cur}}\") )
return 0
;;
{subcmd_details}
@ -117,7 +117,7 @@ fn subcommand_details(app: &App) -> String {
{subcmd})
opts=\"{sc_opts}\"
if [[ ${{cur}} == -* || ${{COMP_CWORD}} -eq {level} ]] ; then
COMPREPLY=( $(compgen -W \"${{opts}}\" -- ${{cur}}) )
COMPREPLY=( $(compgen -W \"${{opts}}\" -- \"${{cur}}\") )
return 0
fi
case \"${{prev}}\" in
@ -126,7 +126,7 @@ fn subcommand_details(app: &App) -> String {
COMPREPLY=()
;;
esac
COMPREPLY=( $(compgen -W \"${{opts}}\" -- ${{cur}}) )
COMPREPLY=( $(compgen -W \"${{opts}}\" -- \"${{cur}}\") )
return 0
;;",
subcmd_dets,
@ -181,9 +181,9 @@ fn vals_for(o: &Arg) -> String {
debug!("vals_for: o={}", o.get_name());
if let Some(ref vals) = o.get_possible_values() {
format!("$(compgen -W \"{}\" -- ${{cur}})", vals.join(" "))
format!("$(compgen -W \"{}\" -- \"${{cur}}\")", vals.join(" "))
} else {
String::from("$(compgen -f ${cur})")
String::from("$(compgen -f \"${cur}\")")
}
}

View file

@ -47,7 +47,7 @@ static BASH: &str = r#"_myapp() {
myapp)
opts=" -h -V --help --version <file> test help"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
fi
case "${prev}" in
@ -56,14 +56,14 @@ static BASH: &str = r#"_myapp() {
COMPREPLY=()
;;
esac
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
myapp__help)
opts=" -h -V --help --version "
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
fi
case "${prev}" in
@ -72,26 +72,26 @@ static BASH: &str = r#"_myapp() {
COMPREPLY=()
;;
esac
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
myapp__test)
opts=" -h -V --case --help --version "
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
fi
case "${prev}" in
--case)
COMPREPLY=($(compgen -f ${cur}))
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
*)
COMPREPLY=()
;;
esac
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
esac
@ -574,7 +574,7 @@ static BASH_SPECIAL_CMDS: &str = r#"_my_app() {
my_app)
opts=" -h -V --help --version <file> test some_cmd some-cmd-with-hypens help"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
fi
case "${prev}" in
@ -583,14 +583,14 @@ static BASH_SPECIAL_CMDS: &str = r#"_my_app() {
COMPREPLY=()
;;
esac
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
my_app__help)
opts=" -h -V --help --version "
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
fi
case "${prev}" in
@ -599,13 +599,13 @@ static BASH_SPECIAL_CMDS: &str = r#"_my_app() {
COMPREPLY=()
;;
esac
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
my_app__some__cmd__with__hypens)
opts=" -h -V --help --version "
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
fi
case "${prev}" in
@ -614,45 +614,45 @@ static BASH_SPECIAL_CMDS: &str = r#"_my_app() {
COMPREPLY=()
;;
esac
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
my_app__some_cmd)
opts=" -h -V --config --help --version "
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
fi
case "${prev}" in
--config)
COMPREPLY=($(compgen -f ${cur}))
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
*)
COMPREPLY=()
;;
esac
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
my_app__test)
opts=" -h -V --case --help --version "
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
fi
case "${prev}" in
--case)
COMPREPLY=($(compgen -f ${cur}))
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
*)
COMPREPLY=()
;;
esac
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
esac