bashbash-completion

Multi Level Bash Completion


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>

I want it to complete only options that are available inside the asadmin "environment" (which I'll also define inside the Bash completion file). 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?


Solution

  • Thanks to mkb's comment, I looked into the p4 example, which was—unlike the Git example—simple enough for me to adapt 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