hrbrmstr's Daily Drop

Share this post

Drop #217 (2023-03-10): Weekend Project Edition

dailyfinds.hrbrmstr.dev

Drop #217 (2023-03-10): Weekend Project Edition

You Complete Me

boB Rudis
Mar 10
Share this post

Drop #217 (2023-03-10): Weekend Project Edition

dailyfinds.hrbrmstr.dev

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 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

people sitting on chair
Photo by Sam Balye on Unsplash

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

2
, 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.

Completion 201

men's black long-sleeved top
Photo by Philippe Bout on Unsplash

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 fpaths.

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)

smiling woman wearing academic dress and black academic hat
Photo by Felipe Gregate on Unsplash

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!

    Share

Resources For Alternate Shells

  • fish

  • nushell

  • PowerShell

  • yash

FIN

Remember, it's the weekend! So keep an eye out for the Bonus Drop! ☮

#bash #zsh #shellcompletion #completion #shell #complete #compdef #cod

1

First and only pun. 🤙 Pinky swear.

2

I realize that the length of some Drops might cause you to disagree with me on that point.

Share this post

Drop #217 (2023-03-10): Weekend Project Edition

dailyfinds.hrbrmstr.dev
Previous
Next
Comments
TopNewCommunity

No posts

Ready for more?

© 2023 boB Rudis
Privacy ∙ Terms ∙ Collection notice
Start WritingGet the app
Substack is the home for great writing