When creating shell completion functionality in bash, it seems like the -C option would be powerful and common. It's defined like this:
-C command
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?