

Discover more from hrbrmstr's Daily Drop
Today's WPE finishes out this shell-centric week with a safari into the land of shell completions.
If you’re thinking, "But, I already know how to hit the <TAB>
key!", then this post is absolutely for you, since we're not only covering some more advanced shell completion techniques (yes, there is life beyond just <TAB>
), plus see how to craft our completions for scripts we craft or for third-party commands that leave us high and dry at the bar, forcing us to pick up their tabs.
We're mainly going to focus on bash
and zsh
in examples, but I'll include some resources for you cool kids who aren't stuck in the past like I am. I suspect users of more modern shells probably also dug deep into how their completions work.
Completion 101
Shell completions are a feature of command line shells that makes completing partially typed command or arguments quick and easy. Essentially, they enable you to type a few characters of a command or filename, then press the <TAB>
key to have the shell automagically complete the rest of the command or filename.
The concept of shell completions has been around since the early days of UNIX, although the exact implementation has evolved over time. Originally, shell completions were implemented using a simple list of commands and filenames, but modern shells use more sophisticated algorithms to generate completions based on context and previous commands.
There are many different types of shell completions, including command, filename, variable, parameter, and option completions. Different shells may implement completions in slightly different ways, although most shells follow a similar basic syntax and idiom, since it is somewhat daft to throw away decades of functionality just to stand out in the crowd.
In bash
, you can complete a command by typing the first few letters and then pressing the <TAB>
. In ksh
, you can also use <TAB>
to complete commands and arguments, but you can also use <ESC>
(or ctrl-[
) to access a menu of possible completions. If you bash
users are feeling cheated after seeing the fancy zsh
completion menu, you can add:
set show-all-if-ambiguous on
set show-all-if-unmodified on
set menu-complete-display-prefix on
"\t": menu-complete
"\e[Z": menu-complete-backward
to your ~/.inputrc
(create it if it does not exist) to get similar functionality.
Since this is a newsletter and not a book
, I'm going to askzsh
folks to hit up this guide, and bash
folks to hit up this other guide to get the low-down on completions. I promise you they are worth the time to pore over because you will be at least 2x more productive on the command line after doing so.Don't fret, though, this Drop is far from over, and you don't need to read ^^ before heading to the next section.
Completion 201
So, how do bash
and zsh
know how to do perform these magical completion operations?
When you hit <TAB>
while typing commands, the shell will inspect the input to find a relevant "completion specification" (compspec
). If one is found, the compspec
will generate a list of possible suggestions to complete the current word. A custom compsec
can be generated for any command using shell-specific completion commands and special environment variables.
Since you likely use completions now, you likely also realize they come for the ride when you brew install
, apt install
, or use some other package manager / run whatever the GH repo says to run to install them with an app. So, while completions aren't "magic", I do consider writing code a bit like crafting a spell, and there are various grimoire directories where they exist.
For bash
, the completion files are stored in the system-wide /etc/bash_completion.d/
directory or in your personal ~/.bash_completion.d/
(though, you aren't limited to just these locations). For zsh
, completion functions are typically stored in the fpath
array, which is an array of folders containing functions and scripts that can be auto-loaded when invoked. By default, the fpath
array includes the directories /usr/local/share/zsh/site-functions
and /usr/share/zsh/site-functions
, which are system-wide directories for storing zsh completion functions.
But, we're getting ahead of ourselves. You can quickly define a new completion for a given command right now without worrying about those files and fpath
s.
While both compdef
command in zsh
and complete
command in bash are used for defining shell completions, there are some key differences between the two.
In bash
, the aptly named complete
used to define completions for commands. In zsh
, compdef
defines completions for both commands and shell functions. zsh
also has a more robust completion system than bash
. (Gauntlet: thrown down.)
zsh
also provides a richer set of <TAB>
-completion options. Specifically, zsh
provides a set of built-in functions that can be used to generate custom completion lists based on context, such as _files
for completing file names and _arguments
for defining complex command-line arguments.
Here's an example of how to define a completion using the complete command in bash
which will suggest three options on <TAB>
:
complete -W "option1 option2 option3" my-awesome-option-picker-utility
while this zsh
definition will suggest filenames with a .csv
extension. The _files
function is used to generate the list of possible completions based on the current context.
compdef '_files -f "*.csv"' my-awesome-csv-utility
Master's Thesis (a.k.a. Your Assignment)
Shell completions are a fundamental component of getting things done faster and more accurately for those of us who live on the command line. Getting more familiar with how they work will level up your CLI experience. To that end, your marching orders are:
Tweak your completion setup. I linked to numerous guides and manuals that will help you make the most out of your existing completions.
Go examine all the completions at your disposal! You'll learn more about your system and be able to riff from the work of others.
Pick a utility you use that does not have completions and make some! Also, make sure to put those in a PR for the utility creator.
You've written scripts. Some of them likely take parameters. Most of them likely have no completions. Add some! For those readers who work with data, perhaps start by limiting the directory display to only the file types your scripts support.
Go one step further and use some third-party utilities — such as cod — to make completion development and usage even better!
Resources For Alternate Shells
FIN
Remember, it's the weekend! So keep an eye out for the Bonus Drop! ☮
#bash #zsh #shellcompletion
#completion
#shell
#complete
#compdef #cod
First and only pun. 🤙 Pinky swear.
I realize that the length of some Drops might cause you to disagree with me on that point.