In bash
, it's easy enough to set up customized completion of command arguments using the complete
built-in. For example, for a hypothetical command with a synopsis of
foo --a | --b | --c
you could do
complete -W '--a --b --c' foo
You can also customize the completion you get when you press Tab at an empty prompt using complete -E
, for example complete -E -W 'foo bar'
. Then, pressing tab at the empty prompt would suggest only foo
and bar
.
How do I customize command completion at a non-empty prompt? For example, if I write f
, how do I customize the completion to make it complete to foo
?
(The actual case I'd like is loc
TAB → localc
. And my brother, who prompted me to ask this, wants it with mplayer
.)
Best Answer
Completion of the command (along with other things) is handled via bash readline completion. This operates at a slightly lower level than the usual "programmable completion" (which is invoked only when the command is identified, and the two special cases you identified above).
Update: the new release of bash-5.0 (Jan 2019) adds
complete -I
for exactly this problem.The relevant readline commands are:
In a similar way to the more common
complete -F
, some of this can be handed over to a function by usingbind -x
.This enables your own per-command or prefix string hooks in
~/.complete.d/
. E.g. if you create an executable~/.complete.d/loc
with:This will do (roughly) what you expect.
The function above goes to some lengths to emulate the normal bash command completion behaviour, though it is imperfect (particularly the dubious
sort | fmt | column
carry-on to display a list of matches).However, a non-trivial issue with this it can only use a function to replace the binding to the main
complete
function (invoked with TAB by default).This approach would work well with a different key-binding used for just custom command completion, but it simply does not implement the full completion logic after that (e.g. later words in the command line). Doing so would require parsing the command line, dealing with cursor position, and other tricky things that probably should not be considered in a shell script...