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

View file

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