ZSH completions
The zsh shell has a very powerful completions system, but the syntax for setting it up is complicated.
Some help can be found in zsh completions how to, the official zsh documentation, or the soruce code for the built-in completions.
In this page there are some quick reminders and examples.
Set up new completions
Completions for a command cmd can be defined in a file named _cmd, which should be in the $fpath and should start with
#compdef cmd
Alternatively, they can be defined in any file that is loaded by the shell in the following way:
function _cmd() {
# Place here the code that sets up the completion
}
compdef _cmd cmd # Tells the shell to use the _cmd function to complete command cmd
Customize style for existing completions
Many existing completions can be customised via the zstyle command. For example, in order to let the git completion know about a custom subcommand git mycommand, you can add to your ~/.zshrc:
zstyle ':completion:*:*:git:*' user-commands mycommand:'this is the help text for my subcommand'
The git completion is then set up to call the function _git-mycommand to complete the options for this sub-command (that you should define somewhere).
The simplest case
For simple cases where options are simple static string, and each one can be repeated, the _describe function allows to set up a completion.
function _cmd() {
local -a options
options=(
'a:help text for option a'
'b:help text for option b'
'c:help text for option c'
)
_describe 'simple options' options
}
Multiple categories with dynamic values
In cases where the command has multiple category of options, and the values for each of them is generated by calling another function, _alternative can be used.
function _cmd() {
_alternative \
'describe:values given as with _describe:(a b c)' \
'describe_help:with some help text:((help1\:"help text 1" help2\:"help text 2"))' \
"custom:completion given by custom function:my_custom_completion" `# We can defer the definition to another function` \
'interface:a newtork interface:_net_interfaces' # Some pre-defined functions exist for common things, like _net_itnerfaces, or _files
}
function my_custom_completion() {
local -a options
options=(
'custom_a:option a defined in another function'
'custom_b:option b defined in another function'
'custom_c:option c defined in another function'
)
_describe 'options defined in another function' options
}
The complete tool: _arguments
The _arguments function is the more complete (and complex to use), and allows to do pretty much everything.
function _cmd() {
_arguments \
'-a[option a]' \
'-b[option b]' \
{-i,--interface}'[a network interface]:interface:_net_interfaces' \
'1:first positional argument:(a b c)' \
':another positional argument:my_custom_completion' \
"::positional optional argument:(d e f)"
}
It can also accept some flags to modify its behaviour, (e.g. -s to allow single-letter options to be combined).
Many examples found online use the special value ->myvalue, which sets the variable $state to the value myvalue and then continue, with the actual possible values for completion given in a case statement futher in the function:
function _cmd() {
local state
_arguments \
":positional argument:->positional values" \
'--interface[a netwrok interface]:interface:->interfaces'
case ${state} in
"positional values")
_alternative 'values:some values:(a b c)'
;;
"interfaces")
_net_interfaces
;;
esac
}