Command completion

While working on a command line, everyone has to do a common task such as typing, which includes commands, its options, input/output file path, and other arguments. Sometimes, we write a wrong command name because of a spelling error in the command name. Also, typing a long file path will be very difficult to remember. For example, if we want to look recursively into the contents of a directory present at the path /dir1/dir2/dir3/dir4/dir5/dir6, we will have to run the following command:

$ ls -R /dir1/dir2/dir3/dir4/dir5/dir6

We can see that the path of this directory is very long and there is a high chance of making an error while typing the full path. Due to these issues, working on a command line will take a longer time than expected.

To solve all these problems, shell supports a very nice feature called command completion. Along with the other shell, bash also has a very good support of command completion.

Most of the Linux distributions, for example, Fedora, Ubuntu, Debian, and CentOS have a pre-installed bash completion for core commands. If not available, it can be downloaded using the corresponding distribution package manager with the package name bash-completion.

Command completion in shell allows you to autocomplete the rest of the characters of the partially typed command, suggesting possible options associated with the given command. It also suggests and autocompletes the partially typed file path.

To enable autocompletion feature in bash, the Tab key is used. While typing a command, a single TAB autocompletes the command if the single command matches, and double [TAB] lists all the possible commands starting with a partially typed command.

For example:

$ gr[TAB]      # Nothing happens
$ gre[TAB]      # Autocompletes to grep
$ grep[TAB][TAB]  # Lists commands installed in system and starts with grep
grep            grep-changelog  grepdiff 

Now, suppose we want to see the contents of the /usr/share/man/ directory, we will have to type ls /usr/share/man/. Using bash completion, type the following command:

$ ls /u[TAB]/sh[TAB]/man

Bash completion will auto-complete the missing partial path and the command will become:

$ ls /usr/share/man

Managing bash completion with complete

The complete is a shell builtin that can be used to see the available bash completion specification for the available commands in a system. It is also used to modify, delete, and create bash completion.

Viewing the existing bash completion

To know the existing bash completion, use the complete command with or without the–p option:

$ complete -p

The following are some of the outputs of the preceding command:

complete cat  # No completion output
complete -F _longopt grep  # Completion as files from current directory
complete -d pushd  # Completion as directories from current directory
complete -c which  # Completion as list of all available commands

To see bash completion on these commands, type the following command:

This lists all files/directories, including hidden files/directories:

$ grep [TAB][TAB]

This lists all files/directories, including hidden files/directories:

$ cat [TAB][TAB]

This tries to list all the available commands in a system. Pressing y will display commands and n will display nothing.

$ complete -c which [TAB][TAB]
     Display all 3205 possibilities? (y or n)

Modifying default bash completion behavior

We can also modify the existing bash completion behavior of a given command using the complete shell builtin command.

The following command is used to change the behavior of the which command to not display any options:

$ complete which
$ which [TAB][TAB]  # No auto completion option will be shown

The following command is used to change the ls command tab behavior to show only the directories list as bash completion:

$ ls ~/[TAB][TAB]    # Displays directories and file as  auto-completion
file1.sh file2.txt dir1/ dir2/ dir3/
$ complete -d ls
$ ls ~/[TAB][TAB]    # Displays only directory name as  auto-completion
dir1/ dir2/ dir3/

Removing bash completion specification

We can remove bash completion specification for a command using the shell builtin complete with the –r option.

The syntax is as follows:

complete -r command_name

Consider the following as an example:

$ complete | grep which  # Viewing bash completion specification for which
complete -c which
$ complete -r which     # Removed bash completion specification for which
$ complete | grep which  # No output

If no command_name is given as an argument to complete -r, all the completion specifications are removed:

$ complete -r
$ complete

Writing bash completion for your own application

The bash-completion package doesn't provide autocompletion feature for any external tools. Suppose that we want to create a tool that has multiple options and arguments. To add a bash-completion feature to its options, we will have to create our own bash completion file and source into it.

For example, package managers such as dnf and apt-get have its own bash completion file to support autocompletion for its options:

$ dnf up[TAB][TAB]
update      updateinfo  update-to   upgrade     upgrade-to 
$ apt-get up[TAB][TAB]
update upgrade

Consider the following shell script as an example:

#!/bin/bash
# Filename: bash_completion_example.sh
# Description: Example demonstrating bash completion feature for command options

function help()
{
  echo "Usage: print [OPTIONS] [arg ...]"
  echo "-h|--help    Display help"
  echo "-v|--version Display version of script"
  echo "-p|--print     Print arguments"
}

function version()
{
  echo "Version of shell script application is 0.1"
}

function print()
{
  echo "Arguments are: $*"
}

# Parsing command line arguments

while [ "$1" != "" ]
do
   case $1 in
        -h | --help ) 
             help
             exit 1
            ;;
        -v | --version )
             version
             exit 1
             ;;
        -p | --print )
             shift
             print $@
             exit 1
            ;;
    *)
    help
    exit 1
   esac
done

To know about the supported options in bash_completion_example.sh, we will run the --help option:

$ chmod +x bash_completion_example.sh	# Adding execute permission to script
$ ./bash_completion_example.sh --help
Usage: print [OPTIONS] [arg ...]
-h|--help    Display help
-v|--version Display version of script
-p|--print     Print arguments

So, the supported options are -h, --help, -v, --version, -p, and --print.

To write bash completion, information of the following bash internal variables are required:

Bash variables

Description

COMP_WORDS

An array of words that is typed on the command line

COMP_CWORD

An index of the word containing the current cursor position.

COMPREPLY

An array that holds the completion results that get displayed after pressing [TAB][TAB]

The compgen is a shell builtin command that displays the possible completions depending on the options. It is used in shell functions to generate possible completions.

An example of bash completion

A bash-completion file for our shell script bash_completion_example will be as follows:

# Filename: bash_completion_example
# Description: Bash completion for bash_completion_example.sh

_bash_completion_example()
{
    # Declaring local variables
    local cur prev opts
    # An array variable storing the possible completions
    COMPREPLY=()
    # Save current word typed on command line in  cur variable
    cur="${COMP_WORDS[COMP_CWORD]}"
    # Saving previous word typed on command line in prev variable
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    # Save all options provided by application in variable opts
    opts="-h -v -p --help --verbose --print"

    # Checking "${cur} == -*" means that perform completion only if current
    # word starts with a dash (-), which suggest that user is trying to complete an option.
    # Variable COMPREPLY contains the match of the current word "${cur}" against the list
    if [[ ${cur} == -* ]] ; then
        COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
        return 0
    fi
}

# Register _bash_completion_example to provide completion
# on running script bash_completion_example.sh
complete -F _bash_completion_example ./bash_completion_example.sh

As per convention, a bash-completion function name should start with an underscore (_) followed by the name of the application—that is, _bash_completion_example. Furthermore, we reset the bash variable COMPREPLY to clean up any previous left out data. Then, we declare and set the cur variable to the current word of the command line and the prev variable to the previous word in the command line. Another variable opts is declared and initialized with all the options that are recognized by an application; in our case, they are -h -v -p --help --verbose –print. The condition if [[ ${cur} == -* ]] checks whether the current word is equal to -* because our option starts with - followed by any other character. If true, then display all the matching options using the compgen shell builtin with the -W option.

Running the created bash completion

In order to run the created bash completion, the easiest way is to source into source bash_completion_example shell script and then run the script or command:

$ source ./bash_completion_example
Now,  execute shell script:
$ ./bash_completion_example.sh -[TAB][TAB]
-h         --help     -p         --print    -v         --verbose
$ ./bash_completion_example.sh --[TAB][TAB]
--help     --print    --verbose
$  ./bash_completion_example.sh –-p[TAB]

Here, --p[TAB] gets auto-completed to -–print.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.16.81.14