function inArray() { declare -a arr1=("${!1}") declare -a arr2=("${!2}") for i in ${arr1[@]}; do for j in ${arr2[@]}; do if [[ $i == $j ]] ; then echo $i break fi done done echo "" } _ctt() { local cur prev opts COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" # ctt available commands cmds="listprojects track report" # current command, if the user supplied any curr_cmd=$(inArray COMP_WORDS[@] cmds[@]) # various options, # generics and command specific declare -A cmdopts opts="--help --debug --verbose " cmdopts[_shared]="--start --end " cmdopts[report]="--all --regexp --ignorecase --format " cmdopts[report]+=${cmdopts[_shared]} cmdopts[track]="--no-comment " cmdopts[track]+=${cmdopts[_shared]} cmdopts[listprojects]="" # expand options based on given command # or only generic ones if [[ "$cur" == -* ]]; then if [ ! -z $curr_cmd ]; then COMPREPLY=( $(compgen -W "${opts} ${cmdopts[${curr_cmd}]}" -- ${cur}) ) else COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) fi return 0 fi # expand project names if a # suitable command is specified # also do not expand more than one project if one already expanded if [[ ! -z $curr_cmd ]]; then projects=$(for p in ~/.ctt/*; do basename "$p"; done ) curr_proj=$(inArray COMP_WORDS[@] projects[@]) if [ ! -z $curr_proj ]; then return 0 fi case "${curr_cmd}" in track) COMPREPLY=( $(compgen -W "${projects}" -- ${cur}) ) ;; report) COMPREPLY=( $(compgen -W "${projects}" -- ${cur}) ) ;; listprojects) COMPREPLY=( $(compgen -W "" -- ${cur}) ) ;; esac else COMPREPLY=( $(compgen -W "${cmds}" -- ${cur}) ) fi return 0 } complete -F _ctt ctt