Issue
The following bash completion passes an array of possible words (i.e. completions) to compgen.
basenames=("foo" "fu bar" "baz");
COMPREPLY=($(compgen -W "${basenames[*]}" -- "${COMP_WORDS[COMP_CWORD]}"))
The problem is that the whitespace in the array elements is not preserved, that is "foo bar" is treated as to elements thanks to word splitting. Is there some way to preserve the whitespace, so that 3 elements are shown, and not 4?
EDIT
basenames
contains filenames, that is nearly every character (apart from / and \0) is allowed.
EDIT 2
The -W flag expects a single word, that is something like foo bar foobar
. Passing multiple elements to it (this is what ${basenames[@]}
would do) won't work.
EDIT 3
Changed examplary basenames array (so the foo
and the foo
from foo bar
won't get collapsed).
Using a newline to separate the words works:
local IFS=$'\n'
COMPREPLY=($(compgen -W "$(printf "%s\n" "${basenames[@]}")" -- ${COMP_WORDS[COMP_CWORD]}"))
Using \0
doesn't:
local IFS=$'\0'
COMPREPLY=($(compgen -W "$(printf "%s\0" "${basenames[@]}")" -- ${COMP_WORDS[COMP_CWORD]}"))
Solution
Why bother with compgen
? Just add them to COMPREPLY manually. The following will complete the matching filenames from /some/path
, handling filenames safely.
some_completion_function() {
local files=("/some/path/$2"*)
[[ -e ${files[0]} ]] && COMPREPLY=( "${files[@]##*/}" )
}
It's not possible to have compgen
handle filenames safely.
Answered By - geirha Answer Checked By - Candace Johnson (WPSolving Volunteer)