1

I have a command with a very structured input like

cmd --help cmd A -flagA1 X cmd A -flagA2 Y cmd B -flagB1 Z 

Where X,Y,Z are fixed values and depend on whether A or B is enabled.

Ideally, I'm trying to generate an autocomplete script for zsh to have the following behavior

cmd subA <tab> --> display X,Y cmd subA -<tab> --> display flagA1, flagA2 

My current script look like this

#compdef _cmd _cmd () { typeset -A opt_args local state line curcontext="$curcontext" state_descr _arguments -C \ ': :->command' \ ': :->subcmd' \ && ret=0 case $state in (command) # local array variable local -a subcommands subcommands=( 'A:Do A' 'B:Do B' ) _describe -t commands 'subcommands' subcommands && ret=0 ;; (subcmd) case $line[1] in (A) _cmd_A_cmd ;; (B) ;; esac ;; esac } _cmd_A_cmd () { typeset -A opt_args local state line curcontext="$curcontext" state_descr _arguments -C \ ':: :->options' \ ': :->subcmd' \ && ret=0 case $state in (options) _arguments '-flagA1:the flag A1' \ '-flagA2:flag A2' ;; (subcmd) _values "A subcommand"\ 'X[X option]' \ 'Y[Y option]' ;; esac } 

It works to get command A and B, and within A to get option X,Y, but I can't get the flags to work.

Any help appreciated.

    1 Answer 1

    2

    To use _arguments with below in mind could help especially in some completion codes with subcommands completion:

    1. describe options (for example --help[show help]--flag[some flag] etc).
    2. put subcommands definitions (: :->command).
    3. more arguments (*:: :->arg) which means some more subcommands specified or no more arguments.
    #compdef _cmd _cmd () { typeset -A opt_args local state line curcontext="$curcontext" state_descr ret=1 _arguments -C : \ '--help[show help]' \ ': :->command' \ '*:: :->arg' \ && ret=0 case $state in (command) local -a commands commands=( 'A:Do A' 'B:Do B') _describe -t commands 'subcommands' commands && ret=0 ;; (arg) _call_function ret _cmd-"$line[1]" ;; esac return ret } _cmd-A () { typeset -A opt_args local state line curcontext="$curcontext" state_descr ret=1 _arguments -C : \ '-flagA1[the flag A1]' \ '-flagA2[the flag A2]' \ ': :->command' \ '*:: :->arg' \ && ret=0 case $state in (command) _values "A subcommand"\ 'X[X option]' \ 'Y[Y option]' && ret=0 # local -a commands # commands=( # 'X:X option' # 'Y:Y option') # _describe -t commands 'A subcommands' commands && ret=0 ;; (arg) _nothing ;; esac return ret } 

    If *:: :->arg specified, this is described in zsh manual (from _arguments):

    *::MESSAGE:ACTION
    ...
    With two colons before the MESSAGE, the words special array and the CURRENT special parameter are modified to refer only to the normal arguments when the ACTION is executed or evaluated.

    like this: (*) denotes the cursor's position,

    $ cmd A --(*)<TAB> ;; words=(cmd A --), CURRENT=3 ;; encounters `*:: ->arg` then, ;; words=(A --), CURRENT=2 ;; eventually the function `_cmd-A` gets called 

    so the function _cmd-A could be written like an A command's completion.

      Start asking to get answers

      Find the answer to your question by asking.

      Ask question

      Explore related questions

      See similar questions with these tags.