Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Writing completion for non-GNU-style command
- X-seq: zsh-users 22022
- From: Alexander Groß <agross@xxxxxxxxxxxxxxxx>
- To: zsh-users@xxxxxxx
- Subject: Writing completion for non-GNU-style command
- Date: Sun, 23 Oct 2016 15:56:53 +0200
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=therightstuff.de; s=google; h=mime-version:from:date:message-id:subject:to; bh=Pvskeopz6/1tCTs8+f6QrBmBEU1KPx74zaeq9TUJNcA=; b=N5P+V9HPq5H9NeJ54kEqDEJryoSpMqbOn+tWW+dcDj9aTM2en9oV94u3sMndchlI2n nShppG9D2CHAzITgPFNhXgPQyx+C/CKVZzT3rSpQaasUeWtKuRD3XA6FMbGTHu91vLns 5bLyGvoiX0BOi6/RKmJZoraQ2JNeH75JT4eAQ=
- List-help: <mailto:zsh-users-help@zsh.org>
- List-id: Zsh Users List <zsh-users.zsh.org>
- List-post: <mailto:zsh-users@zsh.org>
- Mailing-list: contact zsh-users-help@xxxxxxx; run by ezmlm
Hi all,
I'm about to write my first completion script and it seems I picked a
program that is not easy to implement completions for.
The project is question is called Paket
(https://github.com/fsprojects/Paket). Its command line supports
arguments that don't follow the standard GNU conventions. For example,
a valid Paket invocation might look like this:
paket add nuget <package id> [group <group name>] [project <project
file>] [version <version>] [--verbose] [--more-args ...]
e.g.
paket add nuget NUnit group Test --verbose
The command is the "paket add nuget NUnit" part and the rest of the
command line are arguments, despite that "group Test" doesn't look
like one. Apart from "group" there might be more optional arguments
without dashes (i.e. project and version) and with dashes (--verbose).
I'm struggling to find a solution to this as none of the completions I
found (e.g. git) implement a similar command line.
I tried combining _describe (for group etc.) and _arguments (for
--verbose etc.) but then I would need to deduplicate the non-GNU
arguments myself as group can only appear once. _arguments alone
chokes on "group" not starting with a dash. _values won't work because
"group" etc. aren't just values.
What also puzzles me is that zsh removes anything on $line that was
parsed successfully, but doesn't do that for the word following
"nuget" (the package id).
I've attached my current appoach below. There's one additional issue
with it, as options after the line
paket add nuget NUnit group Test -<tab>
don't show up at all.
Any pointers into the right direction are greatly appreciated!
Thanks!
Alex
_paket-add() {
local curcontext=$curcontext state line ret=1
local -A opt_args
local context state_descr
typeset -A val_args
local -a args
args=(
'(--verbose)'--verbose'[Be verbose]'
'(--no-install)'--no-install'[Skip install process (patching of
project files) after the generation of paket.lock file]'
)
_arguments -C \
'--help[Display paket add help]' \
': :->command' \
'*:: :->option-or-argument' \
&& ret=0
case $state in
(command)
local -a commands
commands=(
nuget:'Add NuGet package by its package ID'
)
_describe -t commands command commands && ret=0
;;
(option-or-argument)
curcontext=${curcontext%:*}-$line[1]:
case $line[1] in
(nuget)
_arguments -C \
':package ID: ' \
'*::: :->option-or-argument' \
&& ret=0
case $state in
(option-or-argument)
case $line[$CURRENT] in
(group)
_arguments '*: :_paket_groups' && ret=0
return ret
;;
(project)
_arguments '*:project:_path_files -g "**/*.??proj"' && ret=0
return ret
;;
(version)
_arguments '*:version: ' && ret=0
return ret
;;
esac
local -a should_be_args
should_be_args=(
group:'Add the package to the given group. Default: Main group'
project:'Add the package to a single project only'
version:'Version of the package'
)
# Remove entries from should_be_args that match words.
# _arguments would have done this automatically, but we can't
# use it because they are not args (i.e. not starting with -).
local word
for word in $words; do
should_be_args=(${(R)should_be_args:#$word:*})
done
((${#should_be_args} != 0)) && _describe -t
should-be-args 'command option' should_be_args && ret=0
_arguments $args && ret=0
;;
esac
;;
esac
;;
esac
return $ret
}
Messages sorted by:
Reverse Date,
Date,
Thread,
Author