We all use tab completion in the shell, but what's not so well known is that it's programmable. If you think about it, you realise that it must be programmable, because how else would you be able to use tab completion for git branches and the like.
I recently had an annoyance. I use a tool called I came up with this:
complete -o bashdefault -o default -F __ts_bash_completions ts
__ts_bash_completions () {
COMPREPLY=()
if [ "$COMP_CWORD" -eq 1 ]; then
COMPREPLY=($(compgen -c -- "${COMP_WORDS[COMP_CWORD]}"))
else
local command_completion_function="$(complete -p ${COMP_WORDS[1]} 2>/dev/null|sed 's/.*-F \([^ ]*\) .*/\1/')"
if [ ! -z "$command_completion_function" ]; then
COMP_CWORD=$(( COMP_CWORD - 1 ))
COMP_LINE=$(echo $COMP_LINE|sed "s/^${COMP_WORDS[0]} //")
COMP_WORDS=( "${COMP_WORDS[@]:1}" )
$command_completion_function "${COMP_WORDS[0]}" "$2" "$3"
fi
fi
}
Let's go through it in detail. The first line tells the shell to use the function __ts_bash_completions when the user is typing the ts command and its subsequent arguments:
complete -F __ts_bash_completions ts
We then define that function.
__ts_bash_completions () {
COMPREPLY=()
and the first thing we do is create an empty array COMPREPLY. bash completions populate this global variable to tell the shell what options are available. We then see how many complete words there are on the command line:
if [ "$COMP_CWORD" -eq 1 ]; then
COMP_CWORD is another global variable that contains the number of complete words currently in the command. If that is 1 then the only word currently in the command is ts itself, we want to autocomplete the name of a command:
COMPREPLY=($(compgen -c -- "${COMP_WORDS[COMP_CWORD]}"))
compgen (completion generator) generates a list of all the commands available in the $PATH which begin with ${COMP_WORDS[COMP_CWORD]}. This introduces yet another magic global variable, COMP_WORDS is an array (zero indexed) of all the words currently on the command line, including the one currently being typed, which may be empty. We pick the last one and pass that to compgen for it to use as a filter.
At this point we've tab completed the name of the command that ts is to run and deserve a beer. and it's also in the ts mercurial repo so will no doubt be in a future release.
SOCIAL SHARE CARD GENERATOR