23
votes

I currently have a Bash completion file which completes a single parameter from a list of allowed commands for a script (called "pbt"). This is the working Bash Completion file:

_pbt_complete()
{
  local cur goals

  COMPREPLY=()
  cur=${COMP_WORDS[COMP_CWORD]}
  goals='asadmin clean deploy'
  cur=`echo $cur`
  COMPREPLY=($(compgen -W "${goals}" ${cur}))
}

complete -F _pbt_complete pbt

So if i call

pbt <tab>

Bash completes to all allowed commands (asadmin, clean, deploy), which is okay.

Now i want to add a "second" level to the completion. So for example if i type

pbt asadmin <tab>

it should complete all options that are only available inside the asadmin-"environment" (which i'll also define inside the bash completion file), say for example pbt asadmin [start-domain|stop-domain] But if i type

pbt deploy <tab>

it should complete to another set of options, for example pbt deploy [all|current]. So the options for the second command should always depend on the first command. How can i do that in the completion file?

2
Have you installed or looked at the bash-completion package? bash-completion.alioth.debian.org The p4 and apt modules do this. - Matt K

2 Answers

32
votes

Thanks to mkb's comment i looked into the p4-example, which was - unlike the Git example ;) - simple enough for me to adapt it to my case. Here is the working version which does exactly what i asked for:

have pbt &&
_pbt_complete()
{
  local cur prev

  COMPREPLY=()
  cur=${COMP_WORDS[COMP_CWORD]}
  prev=${COMP_WORDS[COMP_CWORD-1]}

  if [ $COMP_CWORD -eq 1 ]; then
    COMPREPLY=( $(compgen -W "asadmin deploy" -- $cur) )
  elif [ $COMP_CWORD -eq 2 ]; then
    case "$prev" in
      "asadmin")
        COMPREPLY=( $(compgen -W "start-domain stop-domain" -- $cur) )
        ;;
      "deploy")
        COMPREPLY=( $(compgen -W "all current" -- $cur) )
        ;;
      *)
        ;;
    esac
  fi

  return 0
} &&
complete -F _pbt_complete pbt
2
votes

You may want to look at how the completion for git is done, as an example. (This takes 2257 lines of function definitions and additional 14 variables in my bash setup.)