complete
command. For example, you can set completion up so that when you type the unzip
command and hit the TAB key, it only shows completions for files ending with the .zip
extension. Similarly, the completion for the ssh
command would display hosts taken from your known_hosts
file.
In this post, I will describe how you can write a custom completion function for a command foo
. Bash will execute this function when foo [TAB][TAB]
is typed at the prompt and will display possible completions.
Bash uses the following variables for completion:
COMPREPLY
: an array containing possible completions as a result of your functionCOMP_WORDS
: an array containing individual command arguments typed so farCOMP_CWORD
: the index of the command argument containing the current cursor positionCOMP_LINE
: the current command line
${COMP_WORDS[COMP_CWORD]}
.
So, how do you build the result array COMPREPLY
? The easiest way is to use the compgen
command. You can supply a list of words to compgen and a partial word, and it will show you all words that match it. Let's try it out:
sharfah@starship:~> compgen -W "mars twix twirl" tw twix twirlNow we have everything we need to write our completion function:
_foo() { local cur=${COMP_WORDS[COMP_CWORD]} COMPREPLY=( $(compgen -W "alpha beta bar baz" -- $cur) ) } complete -F _foo fooSave this. Mine is in
~/.bash_completion.d/foo
Demosharfah@starship:~> . ~/.bash_completion.d/foo sharfah@starship:~> foo ba[TAB][TAB] bar bazA Bigger Example
Here is a meatier example of Bash completion. It shows how to complete Autosys commands such as
sendevent
and autorep
. It completes command options, events which can be sent to jobs and job names which are obtained from a file. In some cases, the completions depend on the previous argument e.g. if the previous argument is -J
then we know that we have to complete job names.
# a file containing job names export AUTOSYS_JOBFILE=~/.autosysjobs # complete autosys jobs using the job file _autosysjobs() { local cur=${COMP_WORDS[COMP_CWORD]} [ ! -z ${AUTOSERV} ] && \ COMPREPLY=( $( compgen -W "$(cat ${AUTOSYS_JOBFILE}_${AUTOSERV})" -- $cur ) ) return 0 } # complete sendevent _sendevent() { local cur=${COMP_WORDS[COMP_CWORD]} local prev=${COMP_WORDS[COMP_CWORD-1]} case "$prev" in -S) COMPREPLY=( $( compgen -W "$(cat $AUTOSYS_HOSTFILE)" -- $cur ) ) return 0 ;; -E) COMPREPLY=( $( compgen -W "STARTJOB KILLJOB DELETEJOB \ FORCE_STARTJOB JOB_ON_ICE JOB_OFF_ICE \ JOB_ON_HOLD JOB_OFF_HOLD CHANGE_STATUS \ STOP_DEMON CHANGE_PRIORITY COMMENT \ ALARM SET_GLOBAL SEND_SIGNAL" -- $cur ) ) return 0 ;; -s) COMPREPLY=( $( compgen -W "RUNNING STARTING SUCCESS \ FAILURE INACTIVE TERMINATED" -- $cur ) ) return 0 ;; -J) _autosysjobs ;; esac # completing an option if [[ "$cur" == -* ]]; then COMPREPLY=( $( compgen -W "-E -S -A -J -s -P \ -M -q -G -C -U -T -K" -- $cur ) ) fi } complete -F _sendevent sendevent # complete autorep _autorep() { local cur=${COMP_WORDS[COMP_CWORD]} local prev=${COMP_WORDS[COMP_CWORD-1]} case "$prev" in -J) _autosysjobs ;; esac # completing an option if [[ "$cur" == -* ]]; then COMPREPLY=( $( compgen -W "-J -d -s -q -o \ -w -r -L -z -G -M -D" -- $cur ) ) fi } complete -F _autorep autorepRelated Posts:
My Bash Profile - Part III: Completions
Thanks for your post mate, it was enough to get me going writing my own complete functions!
ReplyDeleteFinally someone explains it a way a human being can understand it!
ReplyDeleteThis was great! I created a similar example on runnable so anyone who is interested can play around with it quickly http://runnable.com/Uug-FAUPXc4hAADF/autocomplete-for-bash
ReplyDeleteSimply amazing. Well written!
ReplyDeletefinally i understand how to make cli apps more useful with autocompletion. Thanks.
ReplyDeleteIt took me so long to find a straight forward explanation of this. Thanks for your write up.
ReplyDelete