Autocompletion in Bash for a simple CLI

🤐

Currently, I’ve been developing a CLI for DEV Community in Go. During this journey I’ve learned a lot of really cool stuffs :sunglasses:. After having the devto almost completed, I started wondering, “How can I make autocompletion possible?”, so I started looking for information related. Here I’ll try to explain how to achieve this in Bash, no idea how would be the case for cmd or PowerShell :thinking:.

CLI commands

Now, devto-cli has these commands:

  • articles
  • auth
  • comments
  • followers
  • listings
  • organizations
  • podcasts
  • reading_lists
  • tags
  • webhooks

and other sub commands as well, but for simplicity I’ll focus on how to achieve the autocompletion with these commands only.

Wanted behavior

The idea is to give the user some feedback after running devto <TAB>, for example in this case, the user would see the following suggestions:

articles auth comments followers listings organizations podcasts reading_lists tags webhooks

Which are all the commands available, but if the user start typing devto a<TAB>, the suggestions would be the commands: articles auth

Given that these two are the only ones that start with the letter a.

The general idea is that the completion is triggered after <TAB> been pressed.

The programmable completion feature in Bash

One of the many cool features in bash is the programmable completion, bash have two builtins that will help me, one is complete and the other one is compgen. The documentation of these two commands can be found in man bash.

Jumping to code

After reading several articles, including the mentioned previously, I could manage to adapt that information to my problem. In other words, I made use of the ancestral technique of Copy, Paste and Adapt. The third step of this technique is crucial, given that it is on this step, when you really start understanding other people code. Never skip this part, even if your Copy and Paste works at the first.

Get prepare to read other people code, here we go:


_complete_devto () {
    # word that is been typed
    local word=${COMP_WORDS[COMP_CWORD]}
    local line=${COMP_LINE}

    # local variable to store the list of commands
    # that are going to be passed to compgen
    local xpat

    # List of all the commands available
    local commands="articles auth comments followers listings organizations podcasts reading_lists tags webhooks"

    # simple switch case when program is devto
    case "$1" in 
    devto)
        case "$line" in
        *)
            xpat="$commands"
            ;;
        esac
    esac

    # commands to reply to the user
    COMPREPLY=($(compgen -W "$xpat" -- "${word}"))
}

complete -F _complete_devto devto

Several variables in detail here:

  • COMP_WORDS > An array variable consisting of the individual words in the current command line.

  • COMP_LINE > The current command line.

  • COMP_CWORD > An index into ${COMP_WORDS} of the word containing the current cursor position.

  • COMPREPLY > An array variable from which bash reads the possible completions generated by a shell function invoked by the programmable
    > completion facility.

All the definitions taken from man bash.

Now just one final step, store that code on a file, let’s call it devto.sh and source the file.

source devto.sh

Just try to type devto a<Tab>. This should give you articles and auth as suggestions.

That’s all folks👋

Bibliography