Programmable Completion for Bash on macOS

Well, it actually does two things.

First, it provides a script called bash_completion.

You can find it here on GitHub.

It is a Bash script that, among some other things, provides convenience functions for other completion scripts.

Second, it provides a set of completion scripts in the completions directory for commonly used tools like ssh, wget, curl, gzip, and many others.

You can see the full list of completion scripts here on GitHub.

These completion scripts typically use functions that are defined in the bash_completion script.

Actually, the bash_completion script also sources all the completion scripts in the completions directory.

This means, if you install the bash-completion project on your system, and source the bash_completion script (for example, in your .

bashrc file), then you immediately enable all the completion scripts in the completions directory.

As mentioned, bash-completion became like a standard.

That means that today not only the project’s own completion scripts use the functions defined in the bash_completion script, but also third-party completion scripts.

This means that these third-party completion scripts depend on bash-completion.

In other words, sourcing a third-party completion script that depends on bash-completion only works if bash_completion has been sourced previously.

Otherwise, you will get a command not found error, because the script invokes functions that are unknown to Bash, because they are defined in bash_completion.

This is the case, for example, for the docker and kubectl completion scripts that were mentioned above.

They invoke a couple of functions that are defined in the bash_completion script.

Thus, these completion scripts depend on bash-completion.

This means that to ensure that all completion scripts can be successfully sourced on your system, you should install bash-completion and ensure that the bash_completion script is sourced in your .

bashrc file.

You can look at bash-completion as the “operating system” for programmable completion in Bash, and you should have it on your machine before seriously attempting to use programmable completion in general.

The next section explains how to install bash-completion.

The subsequent section explains how to best use completion scripts of third-party commands so that they work properly with bash-completion.

Installing bash-completionAs you can see from the README of the bash-completion GitHub repository, bash-completion can be installed via various package managers.

Among them is Homebrew, which I highly recommend to use for installing software on macOS in general.

Installing bash-completion with Homebrew is extremely easy:$ brew install bash-completion@2The @2 token indicates the major version 2 of bash-completion (the latest version, at the time of this writing, is 2.

8) which must be used for Bash 4.

1 and higher.

If you (hopefully) upgraded the default shell on your Mac to the latest version of Bash, then this is the right command for you.

If you still use Bash 4.

0 or lower, you have to use brew install bash-completion to install version 1 of bash-completion.

The output of the above command includes the following:Add the following to your ~/.

bash_profile: if [ -f /usr/local/share/bash-completion/bash_completion ]; then .

/usr/local/share/bash-completion/bash_completion fiThis code snippet simply expresses to source a certain file, if it exists.

This file is the bash_completion script that was described in the last section.

You have to add this snippet to your .

bashrc (or .

bash_profile) file so that the bash_completion script is sourced in every shell that is launched.

Because, as mentioned, sourcing the bash_completion script is what effectively “activates” bash-completion on your system.

Let’s see what the above command actually installed on your system.

The base directory for the bash-completion installation is /usr/local/share/bash-completion (assuming that your Homebrew prefix is /usr/local which you can find out with brew –prefix).

The content of the /usr/local/share/bash-completion directory should contain the following:bash_completion (file)completions (directory)The first item is the bash_completion script that was discussed in the previous section.

The second item is the directory containing all the completion scripts provided by bash-completion for commonly used commands, like ssh, wget, curl, and many others.

Since bash_completion sources the completion scripts in the completions directory, these completion functionalities should already work now.

You can test it, for example, with wget by typing wget –f[tab][tab], which should display a list of all the wget options that start with f.

Because you added the code snippet for sourcing the bash_completion script to your .

bashrc file, it will be sourced in every shell that you launch.

This means that the functions defined in bash_completion will now be also available to any third-party completion scripts that depend on them.

That means, now your system is ready to use any third-party completion scripts, including those that depend on bash-completion.

The next section explains the best way to get and manage such completion scripts.

Using Completion ScriptsOnce bash-completion is installed, using third-party completion scripts that depend on bash-completion is easy.

There are actually multiple ways to do it, and three of them are explained in the following subsections in increasing order of user-friendliness.

Simply Source ItTwo completion scripts that depend on bash-completion are the ones for docker and kubectl (of course, there are dozens of others for other popular command-line tools, but these are just two examples).

The Bash completion script for docker can be found here on GitHub, and the Bash completion script for kubectl can be conveniently generated with the kubectl command itself by running kubectl completion bash.

Let’s take kubectl as an example.

In the previous section I claimed that after installing bash-completion, your system is set up so that third-party completion scripts that depend on bash-completion can be successfully sourced.

If this is true, then sourcing the output of kubectl completion bash (i.

e.

the kubectl completion script) should now enable the completion functionality for kubectl.

Let’s test it:$ source <(kubectl completion bash)Now try to auto-complete kubectl arguments, and you should see that it indeed works:$ kubectl [tab][tab] # Lists sub-commands of "kubectl"$ kubectl -[tab][tab] # Lists applicable options for "kubectl"$ kubectl get -[tab][tab] # Lists applicable options for "get"Of course, you can do the same with the Bash completion script of any other command.

For example, with the one for docker located here.

Just get the completion script, source it, and completion should work.

To not have to manually source the completion script in each new shell, you could just add the source command to your .

bashrc file, and completion would be permanently enabled.

However, there’s an even simpler way to enable completion scripts, which is explained next.

Simply Drop ItA nice property of the bash_completion script is that it it sources all the files in a couple of locations.

One of these locations, as we have seen, is the completions directory within the bash-completion project that contains the completion scripts provided by the bash-completion project.

Another such location is a directory with a basename of bash_completions.

d.

If you installed bash-completion with Homebrew, then the exact location of this directory is /usr/local/etc/bash_completions.

d (assuming that your Homebrew prefix is /usr/local, which is the default).

This means that any completion script that you drop into this directory will be sourced by bash_completion.

So, instead of sourcing the kubectl completion script yourself, you can just drop it as a file into this directory (the name of the file doesn’t matter):$ kubectl completion bash >/usr/local/etc/bash_completion.

d/kubectlNow, whenever you start a new shell, the kubectl completion script (and any other completion script in this directory) will be sourced, and completion will work.

Try it out (just don’t forget to start a new shell after copying the script)!That’s pretty easy now.

But you are still responsible for tracking down the completion scripts for each command.

The next section explains how even this can be automated.

Simply Use HomebrewHomebrew is a package manager that provides programs as nice bundles (called formulas in Homebrew terminology) that contain everything you need.

One of these things that many Homebrew formulas contain are the completion scripts for the corresponding command-line tools.

Moreover, if a Homebrew formula contains a completion script, then Homebrew saves it in the /usr/local/etc/bash_completions.

d directory.

In many cases, this is even indicated in the output of the brew install command.

This is the case, for example, for the kubectl formula, as shown in the following:$ brew install kubectl.

Bash completion has been installed to: /usr/local/etc/bash_completion.

dAs you can see, the output indicates that a Bash completion script has been installed to /usr/local/etc/bash_completions.

d.

If you check this directory, you see that there is a new file called kubectl.

This file is the Bash completion script of kubectl, that is, the same as the output of the kubectl completion bash command.

That’s really nice, because you don’t need to take care of obtaining the completion script and installing it at the right location anymore.

If you also have bash-completion installed with Homebrew, the completion scripts in this directory will furthermore be automatically sourced by the bash_completion script.

That means, the completion functionality is enabled by simply installing a package, without any further actions from your side.

The completion scripts of Homebrew formulas are independent from bash-completion.

Completion scripts of Homebrew formulas are always installed to /usr/local/etc/bash_completions.

d, even if bash-completion is not installed.

In this case, the completion scripts are just unused.

However, as soon as you install bash-completion with Homebrew, the completion scripts get sourced by the bash_completion script.

Because of this, the order in which you install bash-completion and other Homebrew formulas doesn’t matter.

Using Homebrew to install programs makes it really easy to get completion support for the corresponding command-line tools.

Of course, there are always programs that you can’t, or don’t want, to install with Homebrew.

In this case, you can still simply drop the corresponding completion scripts in the /usr/local/etc/bash_completions.

d directory to enable completion support for these commands (provided that you have installed, or will install, bash-completion with Homebrew).

SummaryIn this article we covered quite some ground.

Programmable completion is a Bash feature that allows to define command-specific auto-completions.

This works by completion specifications that are tied to commands by the means of the complete builtin.

In practice, completion support is provided in the form of completion scripts by the creators of command-line tools.

macOS includes an old version of Bash that doesn’t support many of the programmable completion features that are used by modern completion scripts.

Therefore, it is crucial that you install a newer version of Bash on your Mac before working with programmable completion.

Furthermore, many completion script depend on the bash-completion project, thus you should install this project too.

The best way to install bash-completion is with Homebrew.

This allows to simply drop third-party completion scripts in a specific folder, and the corresponding completion functionality gets automatically enabled by bash-completion.

If you install Homebrew packages that come bundled with completion scripts, then Homebrew automatically installs these completion scripts in this folder too, so that the completion functionality gets enabled by bash-completion without any further actions from your side.

ReferencesProgrammable Completionhttps://www.

gnu.

org/software/bash/manual/html_node/Programmable-Completion.

htmlhttps://www.

gnu.

org/software/bash/manual/html_node/Programmable-Completion-Builtins.

htmlhttp://freshmeat.

sourceforge.

net/projects/bashcompletionhttps://www.

tldp.

org/LDP/abs/html/tabexpansion.

htmlGNU Bashhttps://www.

gnu.

org/software/bash/https://www.

gnu.

org/software/bash/manual/html_node/https://tiswww.

case.

edu/php/chet/bash/bashtop.

htmlbash-completionhttps://github.

com/scop/bash-completionCommand-Specific Completionshttps://github.

com/git/git/blob/master/contrib/completion/git-completion.

bashhttps://kubernetes.

io/docs/tasks/tools/install-kubectl/#enabling-shell-autocompletionhttps://docs.

docker.

com/docker-for-mac/#install-shell-completionhttps://github.

com/docker/cli/blob/master/contrib/completion/bash/dockerAppendixEnabling and Disabling Programmable CompletionProgrammable completion is enabled by default in Bash, and it can be explicitly turned on and off with the following commands:$ shopt -s progcomp # Enable programmable completion$ shopt -u progcomp # Disable programmable completionIf you disable it, then all completion specifications are ignored, but the default Bash completion (as described above) still remains active.

.

. More details

Leave a Reply