Reputation: 25187
compdef cmd1=service
can be used to define a completion alias, however, that works only when the arguments are going to be the same.
For example, consider a helper script which rewrites some arguments before executing another command:
| What is typed | What is executed |
|---------------+----------------------------|
| s | systemctl |
| s q | systemctl status |
| s q foo | systemctl status foo |
| s j foo | journalctl --unit foo |
| s r foo | sudo systemctl restart foo |
We can ask the script to print the arguments it would execute, so e.g. PRINT_ONLY=1 s
would print just systemctl
.
Assuming completion is already set up for systemctl
/ journalctl
/ sudo
, how would one define a zsh completion for such a script? Rather than redundantly reimplementing completion for those commands, how to implement completion for s
such that the completion system is invoked with a transformed command -- i.e. something like function _s() { get_completions $(PRINT_ONLY=1 s "$@") ; }
?
Upvotes: 3
Views: 905
Reputation: 3064
This should go in a file named _s
somewhere on your $fpath
:
#compdef s
local -a orig_command new_words
orig_command=("${words[@]}")
if [[ $words[-1] == '' ]]; then
# remove an empty word at the end, which the completion system cares about
orig_command[-1]=()
fi
# split the rewritten command into words using the shell parser
new_words=("${(z)$(PRINT_ONLY=1 "${orig_command[@]}")}")
if [[ $words[-1] == '' ]]; then
# restore the empty word if we removed it
new_words+=('')
fi
# update the cursor position
CURRENT=$(( CURRENT - $#words + $#new_words ))
words=("${new_words[@]}")
# restart completion with the rewritten command
_normal
Note: this doesn't do any error handling and just assumes that any unknown arguments will be passed to the default command (e.g. s start foo
-> systemctl start foo
). If that's not the case, let me know how s
behaves in those cases and I can update the completion script.
Upvotes: 2