zsh-workers
 help / color / mirror / code / Atom feed
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


             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).