Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bash Autocompletion - How to pass this array to compgen without significant whitespace being collapsed?

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]}"))
like image 303
helpermethod Avatar asked May 18 '12 12:05

helpermethod


2 Answers

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.

like image 128
geirha Avatar answered Oct 20 '22 18:10

geirha


Perhaps this might do:

COMPREPLY=($(compgen -W "$(printf "%q " "${basenames[*]}")" -- "${COMP_WORDS[COMP_CWORD]}"))
like image 24
glenn jackman Avatar answered Oct 20 '22 20:10

glenn jackman