When creating shell completion functionality in bash, it seems like the
-C option would be powerful and common. It's defined like this:
command is executed in a subshell environment, and its output is used as the possible completions.
That seems really straightforward. But, weirdly, it's not. If I do:
$ complete -C "echo one two three" test.sh
and then type
test.sh and hit [tab] one time, I get that line filled out with
$ test.sh one two three test.sh test.sh
back. What?! For comparison,
$ complete -W "one two three" test.sh
does exactly what I'd expect: it offers one, three, or two as possible completions (in sort order, of course).
I can't find any good documentation anywhere, so I'm experimenting.... maybe a semicolon helps?
complete -C "echo one two three;" test.sh ... Ah, okay, this helps some, because it removes that weird
test.sh from the end. But it still fills out the full string
one two three. This is odd, because that description above definitely says "possible completions", plural.
... so, hmmm, ah, newlines? Let's try
complete -C "echo -e 'one\ntwo\nthree';" test.sh.
Okay, so, this is promising. If I type
test.sh [tab], I get back
one three two. But then, things go wrong. I add an
o to resolve the ambiguity, so,
test.sh o[tab], and that returns
o one three two
Which is puzzling. In fact, any string I type gets added to the list; if I do
test.sh wtf[tab], I get
one three two wtf echoed back. I guess possibly I need to do something sophisticated with
compgen, but, again, I stress, this works as expected with
-W. And, in fact
$ complete -W '$(echo one two three)' test.sh
works just fine (note single quotes to prevent premature expansion/execution, in case you do something more sophisticated than
echo which could produce variable results).
What am I missing here?