Завершение, когда программа имеет подкоманды - PullRequest
15 голосов
/ 25 января 2012

Я написал инструмент командной строки, который использует подкоманды, очень похожие на Mercurial, Git, Subversion и т. Д., В общем его использование:

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

Е.Г.

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

Сейчас я нахожусь в процессе завершения строительства Zsh для него, но быстро обнаружил, что это очень сложный зверь. Я рассмотрел дополнения _hg и _git, но они очень сложны и различны в подходе (я изо всех сил пытаюсь понять их), но оба, похоже, обрабатывают каждую подкоманду отдельно.

Кто-нибудь знает, есть ли способ использовать встроенные функции (_arguments, _values, pick_variant и т. Д.) Для правильной обработки концепции подкоманд, включая обработку общих опций и опций подкоманд надлежащим образом? Или лучше всего было бы вручную обрабатывать общие параметры и подкоманду?

Хороший пример был бы очень признателен.

Большое спасибо.

1 Ответ

23 голосов
/ 25 января 2012

Вы правы в том, что написание скриптов завершения для zsh может быть довольно сложным.Лучше всего использовать существующую в качестве руководства.Один для мерзавца это слишком много для начинающего, 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 вы можете найти больше информации обо всей системе, хотя она несколько плотная.

...