I have a function mycmd
to launch a program that I wrote. The program needs the first argument to be foo
, ssh
or ls
. The second argument depends on the first argument as follows,
foo
-> No second argumentssh
-> Something to ssh tols
-> A fileI want to write zsh autocomplete function for mycmd
which suggest the second argument depending on the first argument. In the simplest form, I know that I can do the following for the first argument
_mycmd() {
compadd foo ssh ls
}
compdef _mycmd mycmd
I have a hard time understanding what to do for the second argument from here. How do I use _ssh
autocomplete for ssh
argument and _ls
autocomplete for ls
argument? (And nothing for foo
as well)
To inspect the current command line, it could be used $words
and $CURRENT
that are the completion special parameters.
CURRENT
This is the number of the current word, i.e. the word the cursor is currently on in the words array.
...
words
This array contains the words present on the command line curently being edited.--- zshcompwid(1), completion special parameters, zshcompwid - zsh completion widgets
The completion function could modify $words
and $CURRENT
(and/or other variables) and then start the entire completion system based with its modified command line. For example:
$ mycmd ls -al<TAB> ;# This is the input, and
;# $words == ("mycmd" "ls" "-al") ;# original value for $words.
;# $words=("ls" "-al") ;# We could update $words for making zsh
;# $ ls -al<TAB> ;# to start the completion system with
;# its modified command line.
;# Finally, _ls would be called.
The utility function _normal
could be used.
_normal
...
A second use is to reexamine the command line specified by the$words
array and the$CURRENT
parameter after those have been modified.
_mycmd
could be listed below:
_mycmd () {
if ((CURRENT == 2)); then
compadd foo ssh ls
elif ((CURRENT > 2)); then
case "$words[2]" in
(ssh|ls)
shift words
((CURRENT--))
_normal -p mycmd
;;
(foo)
_nothing
;;
(*)
_message "mycmd: invalid subcommand or arguments"
;;
esac
fi
return $?
}
or even, more use of the completion builtin/utility functions like below:
_mycmd () {
local curcontext="${curcontext}" state context line
local -A opt_args
_arguments '*:: :->subcmd'
if [[ "$state" == "subcmd" ]]; then
if ((CURRENT == 1)); then
_describe -t mycmd-subcmd "mycmd command" '(foo ssh ls)'
else
curcontext="${curcontext%:*:*}:mycmd-$words[1]:"
case "$words[1]" in
(ssh|ls)
compset -n 1
_normal -p $service
;;
(foo)
_nothing
;;
(*)
_message "mycmd: invalid subcommand or arguments"
;;
esac
fi
fi
return $?
}