Completions for your own tools and scripts make them as pleasant to use as git or docker.
A completion is a function named after the command with a leading underscore, _deploy, stored in a file of the same name in a directory on fpath. The file's first line #compdef deploy tells compinit which commands it completes. compinit scans fpath when it builds ~/.zcompdump, so add your directory to fpath before calling compinit.
Most completions are built on _arguments, which takes one spec per option or argument:
'-v[verbose output]'an option with a description,'(-v --verbose)'{-v,--verbose}'[...]'both spellings, excluding each other,'--config=[config file]:file:_files'an option with a value and an action that completes it,'1:environment:->env'the first positional argument, handled in acase $stateblock,'*:service:(api web worker)'any further arguments from a fixed list.
_describe offers values with descriptions ('staging:test environment'), and helpers like _files, _hosts and _users complete common things. For a tool whose --help lists its options, compdef _gnu_generic mytool gives decent completion for free.
Styles use the context :completion:function:completer:command:argument:tag, for example zstyle ':completion:*:*:deploy:*' .... Press Ctrl-X then ? to run _complete_debug, which writes a trace of the completion to a file. After changing completion files, remove ~/.zcompdump and start a new shell.
Example
#compdef deploy
# file: ~/.zsh/completions/_deploy
local state
local -a envs=('staging:test environment' 'production:live site')
_arguments -s \
'(-v --verbose)'{-v,--verbose}'[print more output]' \
'(-t --tag)'{-t+,--tag=}'[image tag to deploy]:tag:' \
'--config=[config file]:file:_files -g "*.(yml|yaml)"' \
'1:environment:->env' \
'*:service:(api web worker)'
case $state in
env) _describe -t envs 'environment' envs ;;
esac
# In ~/.zshrc, BEFORE compinit:
# fpath=(~/.zsh/completions $fpath)
# autoload -Uz compinit && compinit
# compdef _gnu_generic mytool # free completion from mytool --help
# deploy <Tab> -> production -- live site / staging -- test environment
# deploy -<Tab> -> --config --tag --verbose -t -vRemember
- A _cmd file with #compdef cmd on fpath, loaded by compinit
- _arguments specs describe options, values and positional arguments
- ->state plus case $state for custom logic; _describe for described values
Watch out for
- Adding the completions directory to fpath after compinit has already run.