I'm writing a zsh completion script for the swift tools (compiler and package manager). This command can be used with or without specifying a subcommand. For example
# calls to the compiler
# usage: swift [options] <inputs>
1> swift my_file.swift
2> swift -a 1 -b 2 my_file.swift
# calls to build subcommand
3> swift build
4> swift build -c 1
# calls to test subcommand
5> swift test
6> swift test -d 4
So far, I've got the following completion script. It mostly works, however for the bare call the autocomplete doesn't quite work allright. It does enter the _compiler method, but it doesn't autocomplete correctly after swift -a
. It autocompletes as if it has forgotten about -a
. So swift -a <TAB><TAB>
should show the menu for picking 1-2-3; but instead it shows a file listing. For swift -a -a <TAB><TAB>
it shows the correct completions, but repeating -a
is not valid.
It probably has something to do with the state that has been altered, while it shouldn't have for this specific use-case. However for the subcommands (build & test), the state should be altered for their respective completions to work correctly.
I've went through the documentation, but it is very cryptic. I've checked various other completion scripts, but couldn't figure out the missing link. So how can I specify a completion for a command that has optional subcommands which have separate sets of flags (and also having subsubcommands themselves)?
#compdef swift
local context state state_descr line
typeset -A opt_args
_swift() {
_arguments -C \
': :->command' \
'*:: :->arg'
case $state in
(command)
local tools
tools=(
'build:description for build'
'test:description for test'
)
_alternative \
'tools:common:{_describe "tool" tools }' \
'compiler: :_compiler'
;;
(arg)
case ${words[1]} in
(build)
_build
;;
(test)
_test
;;
(*)
_compiler
;;
esac
;;
esac
}
_compiler() {
_arguments -C \
'(-a)-a[description for a]: :(1 2 3)' \
'(-b)-b[description for b]: :(4 5 6)' \
'*: :_files'
}
_build() {
_arguments -C \
'-c[description for c]: :(1 2 3)'
}
_test() {
_arguments -C \
'-d[description for d]: :(4 5 6)'
}