One of the much-less-well-known-than-should-be features of the GNU Bourne-Again Shell (bash) is its programmable completion functions. The default tab-completion can be extended to cover any number of external commands. For example:
[jk@pokey nfsim]$ make <TAB><TAB> TAGS distclean import savelinks all docs importclean simulator check gcov install snapshot clean gcov-clean restorelinks tags [jk@pokey nfsim]$ make
Here, the completion code has found that we're using make, and parsed the Makefile (in the current directory) to find available targets, displaying the available options.
For a more impressive example:
[jk@pokey ~]$ scp b1:kernel/<TAB><TAB> kernel/linus/ kernel/patches/ kernel/modules/ kernel/powerpc-merge/ [jk@pokey ~]$ scp b1:kernel/
The completion code has ssh-ed into the remote machine to find the possible file-based completions for the scp command.
Neat, huh?
getting it working
The advanced completions aren't (usually) enabled by default, but it's
easy to do so. The Debian and Ubuntu distributions ship bash with a
default set of completions in /etc/bash_completion
, which
you can just source into the current shell:
[jk@pokey ~]$ . /etc/bash_completion
Now go crazy with the tab key.
To save having to source the completion file in every new shell, I
have the following fragment in my .bashrc
:
if [ -f /etc/bash_completion ]; then . /etc/bash_completion fi
adding completions
Being programmable, the programmable completions can be quite easily extended for other commands.
For example, I have a k42make
command, which will copy
a k42 tree to a predefined remote machine, then
ssh to that machine and run make. Because the arguments provided to
k42make
are passed directly to the remote make, it would be
great to provide the same completions as the make command (possible
because the
Makefile is available locally). We can define the k42make
command to use
the existing _make
function to generate expansions:
[jk@pokey ~]$ complete -F _make -o filenames k42make
As another example: I have a command called kdo
, which
runs a command, waits for it to complete and displays a KDE dialog when
it's done (see michael's
blog for the reasoning behind this). We can complete on available commands,
just the same as with strace
, exec
or
time
, using the _command
function:
[jk@pokey ~]$ complete -F _command -o filenames kdo
The last part of the previous section was an oversimplification - this
is what I really have in my .bashrc
:
if [ -f /etc/bash_completion ]; then . /etc/bash_completion # local completions complete -F _command -o filenames kdo complete -F _make -o filenames k42make fi
package maintainers
The /etc/bash_completion
script is extensible - after
defining its own completions, it includes any files in the
/etc/bash_completion.d/
directory. So, any installed package
can (and should!) drop a file in there, defining possible expansions for
command-line utilities.