3

I have a bash script that uses getopts to parse command line arguments. One of the arguments, -l <name> is directed to an if statement that determines certain settings. Is it possible to have autocomplete work in the command line for entering the <name> parameter?

Here is the command line parsing part (getopts) of my script:

while getopts 'l:r:m:?h' c
do
  case $c in
    l) 
        library=$OPTARG 
        ;;
    r)  
        rename_config=$OPTARG 
        ;;
    m)  
        align_mm=$OPTARG
        ;;  
    h|?) usage 
        ;;
  esac
done

The library option (-l) refers to this part of the script:

if [ $library = "bassik" ];
    then
        read_mod="clip"
        clip_seq="GTTTAAGAGCTAAGCTGGAAACAGCATAGCAA"
        echo "Bassik library selected"
elif [ $library = "moffat_tko1" ];
    then
        read_mod="trim"
        sg_length=20    
        echo "Moffat TKO1 library selected"
elif [ $library = "sabatini" ];
    then
        read_mod="trim"
        sg_length=20    
        echo "Sabatini library selected"
fi

The part where the auto-completion should work are for "bassik", "moffat_tko1", and "sabatini" parameters. So far, I have tried just hitting <TAB> right after ./script.sh -l, but that does not work. I have googled it, but could not find anything that fits my situation (not sure also how to call this, new to bash).

Rachid K.
  • 4,490
  • 3
  • 11
  • 30
justinian482
  • 845
  • 2
  • 10
  • 18
  • Yes, it is possible. That's basically what an autocomplete script does. – KamilCuk Jan 15 '21 at 15:10
  • 1
    It is possible, but you have to give a few more specifics – what do you call your script like, what are the autocompletion options (is it a list of words, or somehow dynamically generated?) Have you tried something that didn't work? – Benjamin W. Jan 15 '21 at 15:12
  • Thank you for your comments. I have edited my question to make it clearer – justinian482 Jan 15 '21 at 15:20

1 Answers1

3

First I copied your script snippet in a file called auto.sh and set the execution permission on it:

#!/bin/bash

while getopts 'l:r:m:?h' c
do
  case $c in
    l) 
        library=$OPTARG 
        ;;
    r)  
        rename_config=$OPTARG 
        ;;
    m)  
        align_mm=$OPTARG
        ;;  
    h|?) usage 
        ;;
  esac
done


if [ $library = "bassik" ];
    then
        read_mod="clip"
        clip_seq="GTTTAAGAGCTAAGCTGGAAACAGCATAGCAA"
        echo "Bassik library selected"
elif [ $library = "moffat_tko1" ];
    then
        read_mod="trim"
        sg_length=20    
        echo "Moffat TKO1 library selected"
elif [ $library = "sabatini" ];
    then
        read_mod="trim"
        sg_length=20    
        echo "Sabatini library selected"
fi

Then, to set up an auto-completion for the -l option, you can begin with those basics steps (this can be future enhanced):

1. Create a completion script (e.g. ./auto-complete.sh) which contains the libs function to be called upon completion request (-F parameter of complete command). The function triggers the display of the library names (content of COMPREPLY array variable) if -l option is the word preceding the completion place ($3 argument):

function libs()
{
  # $1 is the name of the command 
  # $2 is the word being completed
  # $3 is the word preceding the word being completed

  case $3 in
    -l) COMPREPLY+=("bassi")
        COMPREPLY+=("moffat_tko1")
        COMPREPLY+=("sabatini");;
  esac
}

complete -F libs auto.sh

2. Source the script in your local shell:

$ source ./auto-complete.sh

3. Launch the shell script and type TAB key twice after a space behind the -l option:

$ ./auto.sh -l <tab><tab>
bassik       moffat_tko1  sabatini
$ ./auto.sh  -l bassik
Bassik library selected

4. The preceding systematically lists all the choices when you type TAB key. To have a more accurate completion when typing the first letters, the completion script can be enhanced to use compgen command:

function libs()
{
  # $1 is the name of the command 
  # $2 is the word being completed
  # $3 is the word preceding the word being completed

  case $3 in
    -l) COMPREPLY=($(compgen -W "bassik moffat_tko1 sabatini" "${COMP_WORDS[$COMP_CWORD]}"));;
  esac
}

complete -F libs auto.sh
Rachid K.
  • 4,490
  • 3
  • 11
  • 30