Educating yourself does not mean that you were stupid in the first place; it means that you are intelligent enough to know that there is plenty left to 'learn'. -Melanie Joy

Friday, 1 November 2013

Programmable Completion : Autocomplete the arguments of your program

November 01, 2013 Posted by Dinesh ,
Auto completion is one of the best features in bash. How good if it completes argument for your program as well !!

The Bash complete and compgen builtins make it possible for tab completion to recognize partial parameters and options to commands. In a very simple case, we can use complete from the command-line to specify a short list of acceptable parameters.

with complete [option] [command] you define the completion for some command.

A basic example to illustrate auto completion:

lets think we have a script called 'run.sh' which will take 4 arguments --all, --help, --html, --version.
as you type run.sh -[TAB] it should display all the above four option.
to make it work lets write a small function will will be loaded by complete when ever TAB is pressed.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# file: load_opt
_load_opt ()   
{                
  local cur
  COMPREPLY=()   
  cur=${COMP_WORDS[COMP_CWORD]}

  if [[ ${cur} == -* ]]
  then
    COMPREPLY=($(compgen -W "--all --help --html --version" -- $cur))
  return 0
  fi
}

complete -F _load_opt run.sh

save the file as load_opt.  and source it before running run.sh. then it shows the magic.

$  source load_opt

$  run.sh -[TAB][TAB]
--all --help --html --version

$ run.sh --h[TAB][TAB]
--help --html


How it works ?

Once the load_opt script is sourced, bash understands that run.sh arguments will be completed bye load_opt function which is specified by complete command at the end of load_opt file.
so when ever TAB is pressed  _load_opt function will be called.
This script has some special shell variables.

COMP_WORDS
An array variable consisting of the individual words in 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
a local 'cur' variable is used to point current completion word.

so if your option starts with - it will match -* and set the value of COMPREPLY to the output of compgen [ check here ] command. compgen will return the matching words of 'cur'
and those set of words are assigned to COMPLREPLY array.
bash will now print those word to console.


But it is not a good idea of sourcing the loader before running the script.
so create this load_opt file under /etc/bash_completion.d/ directory. all the scripts which are under  /etc/bash_completion.d/ will be loaded by bash in the start up.
After adding the file under that directory you can run bash then run the script or you can source that file alone and run the script.


Note:
above example work if you run your script run.sh[TAB] not ./run.sh[TAB]. if you want it to work with ./ as well add 'complete -F _load_opt ./run.sh' also at the end of load_opt file.