Skip to content

Bash autocompletion

Published:

Having to write and, even worse, remember all commands and options for a script can be a pain.
Luckily, the most common shell, bash, allows for autocompletion, provided it is set up accordingly.

I will skip the details on how to set up autocompletion for a script, as it is already well documented in the bash manual.
The thing I want to focus on is how to create the completion script for something you created in an easy and automated way.

Argparse

Before diving into the autocompletion script, let’s see how to create a script that can be autocompleted.
Although you may be a bash wizard, this approach uses Python and the argparse module to parse the command line arguments. The script does not have to be functional.
We only need to create the argparse.ArgumentParser object with the parameters the script expects. I find this is a much easier way to also create the help message in a consistent way.

Using argparse well and knowing all the features it offers is a topic in itself, so I will not go into details here. Make sure to check out the documentation if you want to know more.

#!/usr/bin/env python3
# Simple example of a script that can be autocompleted
import argparse

parser = argparse.ArgumentParser(
    description="A script that does something",
)
parser.add_argument(
    "-i",
    "--input",
    type=str,
    required=True,
    help="The input file",
)
parser.add_argument(
    "-t",
    "--type",
    type=str,
    required=True,
    choices=["a", "b", "c"],
)

shtab

shtab is a python library that automatically generates shell tab completion scripts for Python CLI apps. What is does is taking the argparse.ArgumentParser object and generating the completion script for it.

After installing it, you can generate the completion script for your script with the following command:

# Install shtab
pip3 install shtab
# Generate the completion script (from their documentation)
shtab --shell=bash shtab.main.get_main_parser --error-unimportable \
  | sudo tee "$BASH_COMPLETION_COMPAT_DIR"/shtab

Personally, I prefer to include the shtab library in my script and generate the completion script from there.

#!/usr/bin/env python3
# Simple example of a script that can be autocompleted
import argparse
import shtab

parser = argparse.ArgumentParser(
    description="A script that does something",
)
# ...
# Add the shtab subparser
autocomplete_script = shtab.complete_bash(parser)
print(autocomplete_script)

Running the script will print the completion script to the terminal, which you can then save to a file.

# Generate the completion script
./script.py > my_script_completion.sh

Again, we are only scratching the surface of what shtab can do. Make sure to check out the documentation if you want to know more.

Final steps

After obtaining the completion script, you can source it in your .bashrc file to enable autocompletion for your script. Instead of doing it directly, it is preferable to put it in a specific folder where this kind of scripts are stored.
For example, on Arch Linux, the completion scripts are stored in /usr/share/bash-completion/completions/.
On Ubuntu, the folder is /etc/bash_completion.d/.

# Move the the completion script to the correct folder
mv my_script_completion.sh /usr/share/bash-completion/completions/my_script