20

我编写了一个命令行工具,它使用与 Mercurial、Git、Subversion 等类似的子命令,它的一般用法是:

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

例如

>myapp --verbose speak --voice=samantha --quickly "hello there"

我现在正在为它构建 Zsh 完成,但很快发现它是一个非常复杂的野兽。我看过_hgand_git完成,但它们非常复杂且方法不同(我很难理解它们),但两者似乎都分别处理每个子命令。

有谁知道是否有办法使用内置函数 ( _arguments, _values, pick_variant&c.) 来正确处理子命令的概念,包括适当地处理一般选项和子命令特定选项?或者最好的方法是手动处理一般选项和子命令?

一个点头的例子将非常感激。

非常感谢。

4

1 回答 1

27

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

https://github.com/zsh-users/zsh-completions

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

_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您可以找到有关整个系统的更多信息,尽管它有些密集。

于 2012-01-25T10:15:27.540 回答