From: Peter Stephenson <pws@csr.com>
To: zsh-workers@sunsite.dk (Zsh hackers list)
Subject: PATCH: Set index of first non-option argument in _arguments
Date: Wed, 27 Sep 2006 17:29:46 +0100 [thread overview]
Message-ID: <200609271629.k8RGTkll031019@news01.csr.com> (raw)
One thing that's annoyed me about _arguments (let's stick at that for now,
shall we?) is that although it, or rather the comparguments builtin,
knows perfectly well where the first argument after the options
started, it won't tell you. This makes it unnecessarily difficult to
handle commands with subcommands with different arguments (such as cvs
or svn); you basically have to reparse the command line yourself to do
it properly.
This adds the option -n to _arguments to set NORMARG to the index of
first non-option argument, and uses it in _todo.sh to illustrate.
My first reaction to this was "OH MY *@!@! IT WORKS!", so I haven't
dared to peer too deeply into the code, where there could easily be
funnies.
_arguments still needs better documentation, in particular for the other
of its own options, whose documentation is hidden away.
There's a possible incompatibility if you don't use : to end _arguments'
option list, but that was always a difficulty and we'll have to pick up
the pieces as they fall. The fact that : ends the list of options sucks
quite badly even by the standards of _arguments syntax. OK, *now* I'm
rambling.
Index: Completion/Base/Utility/_arguments
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Base/Utility/_arguments,v
retrieving revision 1.16
diff -u -r1.16 _arguments
--- Completion/Base/Utility/_arguments 18 Jun 2004 09:49:00 -0000 1.16
+++ Completion/Base/Utility/_arguments 27 Sep 2006 16:26:31 -0000
@@ -5,6 +5,7 @@
local long cmd="$words[1]" descr mesg subopts opt usecc autod
local oldcontext="$curcontext" hasopts rawret optarg singopt alwopt
+local setnormarg
long=$argv[(I)--]
if (( long )); then
@@ -189,12 +190,13 @@
subopts=()
singopt=()
-while [[ "$1" = -(O*|[CRWsw]) ]]; do
+while [[ "$1" = -(O*|[CRWnsw]) ]]; do
case "$1" in
-C) usecc=yes; shift ;;
-O) subopts=( "${(@P)2}" ); shift 2 ;;
-O*) subopts=( "${(@P)${1[3,-1]}}" ); shift ;;
-R) rawret=yes; shift;;
+ -n) setnormarg=yes; NORMARG=-1; shift;;
-w) optarg=yes; shift;;
-s) singopt=(-s); shift;;
-W) alwopt=arg; shift;;
@@ -251,6 +253,10 @@
descr="$descrs[anum]"
subc="$subcs[anum++]"
+ if [[ $subc = argument* && -n $setnormarg ]]; then
+ comparguments -n NORMARG
+ fi
+
if [[ -n "$matched" ]] || _requested "$subc"; then
curcontext="${oldcontext%:*}:$subc"
Index: Completion/Unix/Command/_todo.sh
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Unix/Command/_todo.sh,v
retrieving revision 1.2
diff -u -r1.2 _todo.sh
--- Completion/Unix/Command/_todo.sh 27 Sep 2006 14:50:35 -0000 1.2
+++ Completion/Unix/Command/_todo.sh 27 Sep 2006 16:26:31 -0000
@@ -11,8 +11,9 @@
local expl curcontext="$curcontext" state line pri nextstate
local -a cmdlist itemlist
+integer NORMARG
-_arguments -s \
+_arguments -s -n : \
'-d[alternate config file]:config file:_files' \
'-f[force, no confirmation]' \
'-h[display help]' \
@@ -20,8 +21,7 @@
'-v[verbose mode, confirmation messages]' \
'-V[display version etc.]' \
'1:command:->commands' \
- '2:first argument:->firstarg' \
- '3:second argument:->secondarg' && return 0
+ '*:arguments:->arguments' && return 0
local txtmsg="text, can include p:<project> and @<where>"
@@ -45,11 +45,25 @@
_describe -t todo-commands 'todo.sh command' cmdlist
;;
- (firstarg)
- case $words[CURRENT-1] in
+ (arguments)
+ case $words[NORMARG] in
(append|del|do|prepend|pri|replace)
- itemlist=(${${(M)${(f)"$(todo.sh list)"}##<-> *}/(#b)(<->) (*)/${match[1]}:${match[2]}})
- _describe -t todo-items 'todo item' itemlist
+ if (( NORMARG == CURRENT - 1 )); then
+ itemlist=(${${(M)${(f)"$(todo.sh list)"}##<-> *}/(#b)(<->) (*)/${match[1]}:${match[2]}})
+ _describe -t todo-items 'todo item' itemlist
+ else
+ case $words[NORMARG] in
+ (pri)
+ nextstate=pri
+ ;;
+ (append|prepend)
+ _message $txtmsg
+ ;;
+ (replace)
+ compadd -Q -- "${(qq)$(todo.sh list "^0*${words[CURRENT-1]} ")##<-> }"
+ ;;
+ esac
+ fi
;;
(add)
@@ -59,9 +73,6 @@
(list|listall)
# This completes stuff beginning with p: (projects) or @ (contexts);
# these are todo.sh conventions.
- # We should do it for any argument after list or listall, but
- # _arguments doesn't make that easy. We need it to tell us
- # the position of the first non-option argument.
_wanted search expl 'context or project' \
compadd ${${=${${(M)${(f)"$(todo.sh list)"}##<-> *}##<-> }}:#^(p:*|@*)}
;;
@@ -75,23 +86,6 @@
;;
esac
;;
-
- (secondarg)
- case $words[CURRENT-2] in
- (append|prepend)
- _message $txtmsg
- ;;
- (pri)
- nextstate=pri
- ;;
- (replace)
- compadd -Q -- "${(qq)$(todo.sh list "^0*${words[CURRENT-1]} ")##<-> }"
- ;;
- (*)
- return 1
- ;;
- esac
- ;;
esac
case $nextstate in
Index: Doc/Zsh/compsys.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/compsys.yo,v
retrieving revision 1.192
diff -u -r1.192 compsys.yo
--- Doc/Zsh/compsys.yo 21 Sep 2006 19:54:31 -0000 1.192
+++ Doc/Zsh/compsys.yo 27 Sep 2006 16:26:32 -0000
@@ -3237,12 +3237,21 @@
different name for the argument context field.
)
findex(_arguments)
-item(tt(_arguments) [ tt(-swWACRS) ] [ tt(-O) var(name) ] [ tt(-M) var(matchspec) ] [ tt(:) ] var(spec) ...)(
+item(tt(_arguments) [ tt(-nswWACRS) ] [ tt(-O) var(name) ] [ tt(-M) var(matchspec) ] [ tt(:) ] var(spec) ...)(
This function can be used to give a complete specification for
completion for a command whose arguments follow standard UNIX option and
argument conventions. The following forms specify individual sets of
options and arguments; to avoid ambiguity, these may be separated from the
-options to tt(_arguments) itself by a single colon.
+options to tt(_arguments) itself by a single colon. Options to
+tt(_arguments) itself must be in separate words, i.e. tt(-s -w), not
+tt(-sw).
+
+With the option tt(-n), tt(_arguments) sets the parameter tt(NORMARG)
+to the position of the first normal argument in the tt($words) array,
+i.e. the position after the end of the options. If that argument
+has not been reached, tt(NORMARG) is set to tt(-1). The caller
+should declare `tt(integer NORMARG)' if the tt(-n) option is passed;
+otherwise the parameter is not used.
startitem()
xitem(var(n)tt(:)var(message)tt(:)var(action))
Index: Src/Zle/computil.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/computil.c,v
retrieving revision 1.96
diff -u -r1.96 computil.c
--- Src/Zle/computil.c 23 Sep 2006 14:43:58 -0000 1.96
+++ Src/Zle/computil.c 27 Sep 2006 16:26:33 -0000
@@ -2371,6 +2371,7 @@
case 'M': min = 1; max = 1; break;
case 'a': min = 0; max = 0; break;
case 'W': min = 2; max = 2; break;
+ case 'n': min = 1; max = 1; break;
default:
zwarnnam(nam, "invalid option: %s", args[0]);
return 1;
@@ -2665,6 +2666,20 @@
sethparam(args[2], ret);
}
return 0;
+ case 'n':
+ /*
+ * This returns the array index of the word where normal
+ * arguments began. It uses optbeg rather than nargbeg
+ * (the value used when parsing) because nargbeg is assigned
+ * to optbeg in the returned value and nargbeg isn't
+ * used.
+ *
+ * -->PLEASE DON'T ASK<--
+ *
+ * Thank you.
+ */
+ setiparam(args[1], (zlong)ca_laststate.optbeg + !isset(KSHARRAYS));
+ return 0;
}
return 1;
}
--
Peter Stephenson <pws@csr.com> Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK Tel: +44 (0)1223 692070
To access the latest news from CSR copy this link into a web browser: http://www.csr.com/email_sig.php
next reply other threads:[~2006-09-27 16:37 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-09-27 16:29 Peter Stephenson [this message]
2006-09-27 17:09 ` Peter Stephenson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200609271629.k8RGTkll031019@news01.csr.com \
--to=pws@csr.com \
--cc=zsh-workers@sunsite.dk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/zsh/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).