# -*- mode: sh -*- # # Provides bash programmable completion for rtg commands and flags. # To use this, you need to source the file. e.g.: # # . /path/to/rtg/scripts/rtg-bash-completion # # To enable permanently, put that command into your $HOME/.bashrc # # NOTE: Some distro bash-completion systems install a _minimal # completion function that is hooked up dynamically when you try # completing a command that has no completion function defined yet. On # these systems, if you've already accidentally attempted to # tab-complete rtg *before* sourcing this file, it can block us from # working now. It's easiest to just start a new shell with this file # sourced before you do any tab completion. if complete | grep "rtg$" | grep -q -v _complete_rtg; then echo "WARNING: It looks like some other form of completion has been registered for rtg commands in this shell. It may be best to start a new shell to avoid unpredictable behaviour." fi # Main bash completion function function _complete_rtg() { local rtg=$1 local cur prev opts cmd flagtype enumvar enumval local IFS=$'\n' local cmdi=0 COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" if [ "$COMP_CWORD" -gt 1 ]; then # Scan to look for a subcommand name, skipping RTG_MEM/RTG_JAVA_OPTS being split on = by bash for ((cmdi=1, cmdl=0; cmdi < "$COMP_CWORD"; cmdi++, cmdl++)); do cmd="${COMP_WORDS[$cmdi]}" if [ "${cmd:0:4}" == "RTG_" ]; then continue; elif [ "${cmd}" == "=" ]; then continue; elif [ "${COMP_WORDS[$cmdl]}" == "=" ]; then continue; fi break; done fi if [[ "${prev}" == "$rtg" ]] || [[ "$cmdi" -ge "$COMP_CWORD" ]]; then _complete_rtgcommands "$rtg" COMPREPLY=($(compgen -W "${_rtg_cmds// /$'\n'}" -- "${cur}")) return 0 elif [ "$COMP_CWORD" -gt 1 ]; then case "${cur}" in --XX*) _complete_rtghelp "$rtg" "$cmd" --XXhelp opts="$(echo "$_rtg_help" | sed -n '/^ *-/s/.*\(--XX[^= ][^= ]*\)[= ].*/\1/p')" COMPREPLY=($(compgen -W "${opts}" -- "${cur}")) return 0 ;; --X*) _complete_rtghelp "$rtg" "$cmd" --Xhelp opts="$(echo "$_rtg_help" | sed -n '/^ *-/s/.*\(--X[^= ][^= ]*\)[= ].*/\1/p')" COMPREPLY=($(compgen -W "${opts}" -- "${cur}")) return 0 ;; -*) _complete_rtghelp "$rtg" "$cmd" --help opts="$(echo "$_rtg_help" | sed -n '/^ *-/s/.*\(--[^= ][^= ]*\)[= ].*/\1/p')" COMPREPLY=($(compgen -W "${opts}" -- "${cur}")) return 0 ;; *) _complete_rtghelp "$rtg" "$cmd" --help if [ "${prev:0:1}" == "-" ]; then flagtype="$(echo "$_rtg_help" | sed -E -n -e "/ *${prev}.*=[A-Z][A-Z]*/s/.*=([A-Z][A-Z]*)[[:blank:]].*/\1/p")" else # Completion for anonymous flags flagtype="$(echo "$_rtg_help" | sed -E -n -e "/^ *[A-Z][A-Z]*\+? */s/^ *([A-Z][A-Z]*).*/\1/p")" fi case ${flagtype} in FILE) COMPREPLY=( $(compgen -o dirnames -f "${cur}") ) return 0 ;; DIR|SDF) COMPREPLY=( $(compgen -o dirnames -d "${cur}") ) return 0 ;; *) enumvar="_rtg_${cmd}_${prev//-/_}" enumval="${!enumvar}" if [ "$enumval" ]; then COMPREPLY=( $(compgen -W "${enumval// /$'\n'}" -- "${cur}") ) else oifs="$IFS" IFS=$'\n' COMPREPLY=( $(compgen -f -- "${cur}") ) IFS="$oifs" fi return 0 ;; esac ;; esac fi } # Helper for completion that caches list of RTG subcommands. Use cache # whenever it exists and we are running the same rtg as last time. function _complete_rtgcommands () { local rtg=$1 if [ -z "$_rtg_cmds" ] || [ -z "$_rtg_lastrtg" ] || [ "$_rtg_lastrtg" != "$rtg" ]; then _rtg_lastrtg="$rtg" _rtg_cmds="$("$rtg" --Xhelp 2>&1 | sed -E -n '/^'$'\t''[a-z]/s/^[[:blank:]][[:blank:]]*([[:graph:]][[:graph:]]*).*/\1/p') RTG_MEM RTG_JAVA_OPTS" fi } # Helper for completion that caches help output per command. Use cache # whenever it exists and we are running the same command as last time. # Also automatically works out options for enums (e.g. --sex, --format # --machine) and stashes for later enum expansion into variables named # e.g. _rtg_format___quality_format="illumina solexa sanger" function _complete_rtghelp () { local rtg=$1 local cmd=$2 local help=$3 local enumvar if [ -z "$_rtg_help" ] || [ -z "$_rtg_lastcmd" ] || [ "$_rtg_lastrtg" != "$rtg" ] || [ "$_rtg_lastcmd" != "$cmd$help" ]; then _rtg_lastrtg="$rtg" _rtg_lastcmd="$cmd$help" _rtg_help="$("$rtg" "$cmd" "$help" 2>/dev/null | tr '\n' '\a' | sed -e "s/"$'\a'" */ /g" | tr '\a' '\n' | sed -n "/^ *[-A-Z]/p")" while IFS=' ' read flag rest; do enumvar="_rtg_${cmd}___${flag//-/_}" # Kind of yuk setting of dynamic variables. Can't use declare -g with bash <4.2 eval "${enumvar}=\"${rest}\"" done < <(echo "$_rtg_help" | sed -n -e "s/,//g" -e "/.*--[^=]*=.*Allowed values are/s/.*--\([^=]*\)=.*Allowed values are \[\([^]]*\)\].*/\1 \2/p") fi } _rtg_lastrtg= _rtg_cmds= _rtg_help= _rtg_lastcmd= complete -o filenames -F _complete_rtg rtg