Discover more from hrbrmstr's Daily Drop
Drop #217 (2023-03-10): Weekend Project Edition
You Complete Me
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.1
We're mainly going to focus on
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.
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.
bash, you can complete a command by typing the first few letters and then pressing the
ksh, you can also use
<TAB> to complete commands and arguments, but you can also use
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
~/.inputrc (create it if it does not exist) to get similar functionality.
Since this is a newsletter and not a book2, I'm going to ask
zsh 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.
So, how do
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
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.
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/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
compdef command in
complete command in bash are used for defining shell completions, there are some key differences between the two.
bash, the aptly named
complete used to define completions for commands. In
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
complete -W "option1 option2 option3" my-awesome-option-picker-utility
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
Remember, it's the weekend! So keep an eye out for the Bonus Drop! ☮
#bash #zsh #shellcompletion
First and only pun. 🤙 Pinky swear.
I realize that the length of some Drops might cause you to disagree with me on that point.