Zsh completion arguments

From wikinotes

The _arguments function is one method available for producing completions.

Syntax

Basics

arguments \
  '( ${excludes} )${param}:[:]${message}:${action}'
# ${excludes} is an array of param ${state_descr}s
#    arguments \
#      '::one:_normal' \
#      '::two:_normal' \
#      '(one)::three:(foo bar baz)'   
#
# don't complete 'three' if 'one' has been used
# ${param} has different formats depending the param
# (or the next param, depending on param type)
#    ex: '-h[show help]'  # flag
#    ex: '1'              # positional
#    ex: ''               # optional
# ':' vs '::' 
#    here ${param}:${message}:${action}  is a required param
#    here ${param}::${message}:${action} is an optional param
# ${message} is the name of the param
#    this is the name of the param, when referred to in other completer functions.
#    it gets bound to ${state_descr}.
# ${action} is instructions on how to complete the next param
#    '1:one:'                  # ? valid ?
#    '1:one:(one two three)'   # argument must be one, two, or three
#    '1:one:_user'             # argument uses '_user' (function) to provide completions

Flag Arguments

_arguments \
   {-h,--help}'[show help]' \
       # param:   -h/--help
       # desc:    show help
       # action:  (none)
   '-o[output file]:::_files' \
       # param:   -o
       # desc:    output file
       # action:  (complete any file)

Positional Arguments

# ex: ${position}:${state_descr}:${action}

_arguments \
    '1:user:_users' \              # 1st positional arg (required)
    '2:priority:(low med high)' \  # 2nd positional arg (required) (complete to low/med/high)
    '3::group:_groups' \           # 3nd positional arg (optional)

The argument-name is bound to $state_descr.

Value for last defined Param

:${message}:${action}   # reqd completion for prev command
::${message}:${action}  # optional completion for prev command
_arguments \
    {-h,--help}'[show help]' \
    '*::extra:(foo bar baz)' \  # any extra parameters, (complete to (foo bar baz))
    ':value:(foo bar baz)'      # after prev param (extra), always complete one of these words

Rest Arguments

Any arguments not consumed earlier use this completer.

*:${message}:${action}    # 
*::${message}:${action}   # 
*:::${message}:${action}  #

State Setting/Parsing

The -C argument enables state-setting.
This lets you determine the parser that gets used based on the state you set.

local state               # scope state locally

_arguments -C \
    '*:extra:->my-state'  # sets `$state='my-state'`

case $state in
    (my-state)
        _arguments '1:foo:(one two three four)'
        ;;
esac

Strategies

TODO:

This section is unclear, requires experimentation and clarity

Subparsers

Dynamic Arguments

Generate autocomplete options based on the options that were entered previously. This can do just about anything you need it to, it's really cool. This isn't my example, and I haven't yet needed this level of flexibility yet. This example is just so clear, I had to add it.

Some Background Info:

  • $words[] is an array of all arguments used so far
  • $state is set in _arguments. In the below example. If completion is used for '1', the value of $state will be 'country'
#compdef hello
 
_hello() { 
    local curcontext="$curcontext" state line                ## These two lines are required, 
    typeset -A opt_args                                                ## they initialize some internal variables
                                                                             ## for your function

    _arguments \                                                        ## Initial Arguments
        '1: :->country'\
        '*: :->city'
 
    case $state in                                                    ## Expand Arguments based on their category
    country)
        _arguments '1:Countries:(France Germany Italy)'
    ;;
    *)
        case $words[2] in
        France)
            compadd "$@" Paris Lyon Marseille
        ;;
        Germany)
            compadd "$@" Berlin Munich Dresden
        ;;
        Italy)
            compadd "$@" Rome Napoli Palermo
        ;;
        *)
            _files 
        esac
    esac
}
 
_hello "$@"                                                            ## Passes _hello() function all arguments that was passed to the script.