Estimated reading time: 3 minutes

Beyond simple tab completion

Matt Taylor wrote on the EADS Linux list:

wildmenu is to vim as $x is to bash. Define $x :)

The wildmenu option in vim shows possible command line completions above the command line, highlighting the currently selected completion option. A follow up email later and Matt says:

Basically, I want bash to show me the completions and Tab to slide through them in the same way vim does it.

The feature is surprisingly easy to achieve with bash, and is actually a feature of readline making it available to all software that uses completion functionality from readline.

The option we want is called menu-complete, but it not bound to a key by default. You can enable menu-complete in all readline-using applications by editing your ~/.inputrc (or whatever $INPUTRC points to if it is set) or just for bash if you do not wish to change the behaviour of other applications.

To change the behaviour by editing the readline configuration file we would do this:

"\C-a": menu-complete
# Alternative version, enables menu-complete only for bash
$if Bash
    "\C-a": menu-complete
$endif

The above tells readline we wish to bind menu-complete to Control-a, I find that key combination quite comfortable as Control-a is easy to reach the my keyboard layout and is of little use in any of the apps I use on a regular basis(I’d feel differently if Home was inaccessible). You must either re-read the configuration file or restart the bash session to enable this binding.

To enable the key binding in bash only we could also just edit the appropriate bash startup file:

bind '"\C-a": menu-complete'

You must source the startup file or restart bash to enable this binding, alternatively you can just test the command in your current bash setting until you’re happy with the key combination.

In a follow up email on the list Matt asks if it is possible to make the completion context aware, in much the same the bash-completion package does but without having to write new completion scripts. There are some other quite useful completion modes available in bash, I’ll describe a few below.

M-! tells bash to complete command names; be they actual on-disk commands, functions or aliases. M-/ completes only filenames, this can be very useful when bash-completion is refusing to tab complete a filename for you. C-$ implements variable name completion, this is most useful when you’re looking to unset or re-set a variable. Variable name completion isn’t actually necessary if you have bash-completion installed as it is smart enough to handle this for you in most cases.

And finally, there is a one more incredibly useful completion mode in bash and that is M-{, it adds all possible completions to the command line using the brace expansion syntax. For example, if I type ls ~/Git/Local/<M-{> it completes to /home/jay/Git/Local/{Makefile,countless,dot-configs,haskvim,jrutils}. Using readline motion commands, especially word motions such as M-f and M-b to jump forward and backward one word, I can easily apply a command to a certain set of files in a directory. Just don’t try it on /usr/bin unless you want to see how bash handles massive command lines!!


Authenticate this page by pasting this signature into Keybase.

Have a suggestion or see a typo? Edit this page