How to use autotools to enable bash completion for your program?
I want to enable auto-completion for DEploid for a long time.
Finally got time to do it this Christmas break. I use autotools for DEploid
, which made the process extremely simple.
This post is a short summary for what is needed for enabling bash auto-completion. Basically, you first need to check and enable (step 1) bash-complete as part of the install (step 2). Most importantly, you need a bash script (step 3) to instruct the shell what should pop up the next when you press the “Tab”.
Step 0. Dependencies
You can use apt-get install
to get the following:
- For autotools:
autoconf
autoconf-archive
- For bash-completion:
bash-completion
,pkg-config
is needed for Docker - For DEploid:
build-essential
libcppunit-dev
zlib1g-dev
Step 1. Add the following to `configure.ac’.
# bash complete
AC_ARG_WITH([bash-completion-dir],
AS_HELP_STRING([--with-bash-completion-dir[=PATH]],
[Install the bash auto-completion script in this directory. @<:@default=yes@:>@]),
[],
[with_bash_completion_dir=yes])
if test "x$with_bash_completion_dir" = "xyes"; then
PKG_CHECK_MODULES([BASH_COMPLETION], [bash-completion >= 2.0],
[BASH_COMPLETION_DIR="`pkg-config --variable=completionsdir bash-completion`"],
[BASH_COMPLETION_DIR="$datadir/bash-completion/completions"])
else
BASH_COMPLETION_DIR="$with_bash_completion_dir"
fi
AC_SUBST([BASH_COMPLETION_DIR])
AM_CONDITIONAL([ENABLE_BASH_COMPLETION],[test "x$with_bash_completion_dir" != "xno"])
Step 2. Add the following to `Makefile.am’.
if ENABLE_BASH_COMPLETION
bashcompletiondir = $(BASH_COMPLETION_DIR)
dist_bashcompletion_DATA = src/dEploid_completion.sh
endif
Step 3. Create a bash file src/dEploid_completion.sh
.
There are two main parts for the auto-completion here:
- Completing a flag, of which the list “opts” contains.
- Completing what files followed by the flag (e.g. -ref, -alt, etc), which
compgen
will provide a list of possible files and directories.
#/usr/bin/env bash
_dEploid_completions()
{
local cur prev opts
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
opts="-h -help \
-ref -alt -plaf -panel -exclude\
-vcf -sample -plafFromVcf \
-o -seed -noPanel\
-ibd -lasso -best"
if [[ ${cur} == -* || ${prev} == "dEploid" ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
else
if [[ ${prev} == "-ref" || ${prev} == "-alt" || ${prev} == "-plaf" || ${prev} == "-panel" || ${prev} == "-exclude" ]] ; then
COMPREPLY=( $(compgen -o plusdirs -f -X '!*.@(txt|gz)' -- ${cur}) )
for ((i=0; i < ${#COMPREPLY[@]}; i++)); do
[ -d "${COMPREPLY[$i]}" ] && COMPREPLY[$i]=${COMPREPLY[$i]}/
done
return 0
else
if [[ ${prev} == "-vcf" ]] ; then
COMPREPLY=( $(compgen -o plusdirs -f -X '!*.@(vcf|gz)' -- ${cur}) )
for ((i=0; i < ${#COMPREPLY[@]}; i++)); do
[ -d "${COMPREPLY[$i]}" ] && COMPREPLY[$i]=${COMPREPLY[$i]}/
done
return 0
else
return 0
fi
fi
fi
return 0
}
complete -o filenames -o nospace -o bashdefault -F _dEploid_completions dEploid
Done!