Zsh 当程序有子命令时完成

Zsh 当程序有子命令时完成,zsh,zsh-completion,Zsh,Zsh Completion,我编写了一个命令行工具,它使用子命令,非常像Mercurial、Git、Subversion&c,因为它的一般用法是: >myapp [OPTS] SUBCOMMAND [SUBCOMMAND-OPTS] [ARGS] 例如 我现在正在为它构建Zsh completion,但很快发现它是一个非常复杂的野兽。我已经看过了\u hg和\u git补全,但它们非常复杂,方法也不同(我很难理解它们),但它们似乎都分别处理每个子命令 是否有人知道是否有办法使用内置函数(\u参数,\u值,选择变量&

我编写了一个命令行工具,它使用子命令,非常像Mercurial、Git、Subversion&c,因为它的一般用法是:

>myapp [OPTS] SUBCOMMAND [SUBCOMMAND-OPTS] [ARGS]
例如

我现在正在为它构建Zsh completion,但很快发现它是一个非常复杂的野兽。我已经看过了
\u hg
\u git
补全,但它们非常复杂,方法也不同(我很难理解它们),但它们似乎都分别处理每个子命令

是否有人知道是否有办法使用内置函数(
\u参数
\u值
选择变量
&c.)正确处理子命令的概念,包括适当处理常规选项和子命令特定选项?或者最好的方法是手动处理常规选项和子命令

请举个简单的例子


非常感谢。

您说得对,为zsh编写完成脚本可能相当困难。您最好的选择是使用现有的一个作为指南。对于初学者来说,git的版本太多了,imo。您可以使用以下版本:

至于你的问题,你已经使用了国家的概念。在列表中定义子命令,然后通过$state标识所处的命令。然后定义每个命令的选项。您可以在游戏的完成脚本中看到这一点。简化版本如下:

_play() {
  local ret=1

  _arguments -C \
    '1: :_play_cmds' \
    '*::arg:->args' \
  && ret=0

  case $state in
    (args)
       case $line[1] in
         (build-module|list-modules|lm|check|id)
           _message 'no more arguments' && ret=0
         ;;
         (dependencies|deps)
           _arguments \
             '1:: :_play_apps' \
             '(--debug)--debug[Debug mode (even more informations logged than in verbose mode)]' \
             '(--jpda)--jpda[Listen for JPDA connection. The process will  suspended until a client is plugged to the JPDA port.]' \
             '(--sync)--sync[Keep lib/ and modules/ directory synced. Delete unknow dependencies.]' \
             '(--verbose)--verbose[Verbose Mode]' \
             && ret=0
         ;;
       esac
   esac
(如果要粘贴此文件,请使用原始源文件,因为这不起作用)

这看起来令人望而生畏,但总体思路并没有那么复杂。首先是子命令(_play_cmds是子命令列表,每个子命令都有描述),然后是参数。参数是基于您选择的子命令生成的。请注意,如果多个子命令共享参数,则可以将它们分组


使用man zshcompsys,您可以找到有关整个系统的更多信息,尽管它有点密集。

太棒了,非常感谢。我很高兴你说
zshcompsys
很密集,因为我开始认为是我;)20年后,这段代码对我来说就像今天的二进制代码一样。
_play() {
  local ret=1

  _arguments -C \
    '1: :_play_cmds' \
    '*::arg:->args' \
  && ret=0

  case $state in
    (args)
       case $line[1] in
         (build-module|list-modules|lm|check|id)
           _message 'no more arguments' && ret=0
         ;;
         (dependencies|deps)
           _arguments \
             '1:: :_play_apps' \
             '(--debug)--debug[Debug mode (even more informations logged than in verbose mode)]' \
             '(--jpda)--jpda[Listen for JPDA connection. The process will  suspended until a client is plugged to the JPDA port.]' \
             '(--sync)--sync[Keep lib/ and modules/ directory synced. Delete unknow dependencies.]' \
             '(--verbose)--verbose[Verbose Mode]' \
             && ret=0
         ;;
       esac
   esac