多级 Bash 完成

发布于 2024-10-22 01:34:27 字数 1004 浏览 1 评论 0原文

我目前有一个 Bash 完成文件,它从名为 pbt 的脚本的允许命令列表中完成单个参数。这是工作的 Bash 完成文件:

_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

因此,如果我调用

pbt <tab>

Bash 完成所有允许的命令(asadmincleandeploy),这是可以的。 现在我想添加一个第二级来完成。例如,如果我输入,

pbt asadmin <tab>

我希望它只完成asadmin“环境”(我还将在 Bash 完成文件中定义)。例如pbt asadmin [启动域|停止域]。但如果我输入

pbt deploy <tab>

It 应该完成另一组选项。例如,pbt 部署 [all|current]。因此第二个命令的选项应始终取决于第一个命令。

我怎样才能在完成文件中做到这一点?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

我们的影子 2024-10-29 01:34:27

感谢mkb的评论,我研究了p4 示例,与 Git 示例不同——简单到足以让我适应我的情况。这是工作版本,它完全符合我的要求:

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

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
泼猴你往哪里跑 2024-10-29 01:34:27

顺便说一句,这里有两个关于更好的 Tab 补全的有用技巧:

  • 使用 bind 'set show-all-if-ambigously on' # 这使得只需要一个 Tab 来显示可能的补全
  • 使用这个类似 Fish 的包当您键入时,Bash 会自动显示可能的情况和历史记录: https://superuser.com/a/1644033/388883 (称为ble.sh)

以下是有关如何使用 complete 命令调整选项卡补全的更多信息 。此页面有令人难以置信的细分,并讨论使用“cobra (Golang)、click (Python) 和 clap (Rust) 工具”的已知应用程序
https://echorand.me/posts/linux_shell_autocompletion/ (以及 Git 如何使用 Compgen)


这里是Debian bash-completion 的 GH 存储库链接:https://github .com/scop/bash-completion

问:每个目标命令的完成文件的搜索顺序是什么?

A. 命令的补全文件由shell函数__load_completion查找。这里,解释 bash-completion >= 2.12 中的搜索顺序。

  • BASH_COMPLETION_USER_DIR。 BASH_COMPLETION_USER_DIR 中用冒号分隔的每个路径的子目录补全被视为补全目录。
  • 主 bash_completion 文件的位置。考虑与 bash_completion 位于同一目录中的子目录补全。
  • 目标命令的位置。当命令的实际位置在目录 /bin 或 /sbin 中时,会考虑目录 /share/bash-completion/completions。
  • XDG_DATA_DIRS(或系统目录 /usr/local/share:/usr/share 如果为空)。考虑 XDG_DATA_DIRS 中以冒号分隔的每个路径的子目录 bash-completion/completions。

依次在上述补全目录中查找name或.bash的补全文件,其中是目标命令的名称。使用最先找到的文件。当本过程中任何补全目录都没有找到补全文件时,接下来依次在补全目录中查找名称为_的补全文件。

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.

咽泪装欢 2024-10-29 01:34:27

作为示例,您可能想看看 git 的补全是如何完成的。 (这在我的 bash 设置中需要 2257 行函数定义和额外的 14 个变量。)

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文