开发者

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 p开发者_StackOverflow社区bt 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?


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


Btw, here are two useful tips on better tab completion:

  • use bind 'set show-all-if-ambiguous on' # this makes only one Tab necessary to show possible completions
  • use this Fish-like package for Bash that automatically shows possibles and history as you type: https://superuser.com/a/1644033/388883 (called ble.sh)

Here is more info on how to use the complete command to adjust tab completetion. This page has an incredible breakdown, and discusses known application using "cobra (Golang), click (Python) and clap (Rust) tools" https://echorand.me/posts/linux_shell_autocompletion/ (and how Git uses Compgen)


Here is a link the the GH repo for Debian bash-completion: https://github.com/scop/bash-completion

Q. What is the search order for the completion file of each target command?

A. The completion files of commands are looked up by the shell function __load_completion. Here, the search order in bash-completion >= 2.12 is explained.

  • BASH_COMPLETION_USER_DIR. The subdirectory completions of each paths in BASH_COMPLETION_USER_DIR separated by colons is considered for a completion directory.
  • The location of the main bash_completion file. The subdirectory completions in the same directory as bash_completion is considered.
  • The location of the target command. When the real location of the command is in the directory /bin or /sbin, the directory /share/bash-completion/completions is considered.
  • XDG_DATA_DIRS (or the system directories /usr/local/share:/usr/share if empty). The subdirectory bash-completion/completions of each paths in XDG_DATA_DIRS separated by colons is considered.

The completion files of the name or .bash, where is the name of the target command, are searched in the above completion directories in order. The file that is found first is used. When no completion file is found in any completion directories in this process, the completion files of the name _ is next searched in the completion directories in order.


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.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜