Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: Re: Assorted _arguments arguments



Bart Schaefer wrote:

> ...
> 
> Returning to the original topic, perhaps a better way to think of this
> is that -i and --ignore-case are synonyms and should get the same
> treatment and description.  E.g. your suggestion does not help with
> a case like
> 
> _bzip2:    '(--decompress --compress -z --test -t)-d[decompress]' \
> _bzip2:    '(-d --compress -z --test -t)--decompress[decompress]' \
> _bzip2:    '(--compress --decompress -d --test -t)-z[compress]' \
> _bzip2:    '(-z --decompress -d --test -t)--compress[compress]' \
> 
> where you have both options that have alternate names for each other and
> are mutually exclusive with other options.  Much better would be, say,
> 
> 	'-d(--decompress)' '-z(--compress)' '-t(--test)' \
> 	'(-z -t)-d[decompress]' \
> 	'(-d -t)-z[compress]' \
> 	'(-z -d)-t[test compressed file integrity]' \
> 
> It might even be able to compute this automatically from the comma-lists
> in --help output, or some such.  (No, I don't really like the `-x(--xxx)'
> syntax, but I haven't time to think harder about it just now.)

I said that I was thinking about using something like _argument_sets
for this. But, why not use _argument_sets itself? This allows the
set-strings be given as `(name)' meaning that all specifications in
that set are mutually exclusive with all other specs in the set. They
are mutually exclusive with the set in which they are, so to say.

Example:

  _argument_sets \
      -common -options ':and:(arguments)' \
    - '(compress)' \
      {-c,--compress}'[compress]' \
    - '(decompress)' \
      {-d,--decompress}'[decompress]'

Is that convenient enough? It is a bit slower than a only-_arguments-based
solution would have been, though. If nobody likes it, I can take it
out again (it is only a small part of the patch below).

The patch also contains some fixes in the C-code for this and in the
shell code -- to make listing of options defined by different sets
nicer.


Bye
 Sven

Index: Completion/Base/_argument_sets
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Base/_argument_sets,v
retrieving revision 1.2
diff -u -r1.2 _argument_sets
--- Completion/Base/_argument_sets	2000/05/09 09:52:27	1.2
+++ Completion/Base/_argument_sets	2000/05/11 08:52:00
@@ -1,11 +1,21 @@
 #autoload
 
 local all ret=1 end xor has_args had_args ostate ocontext oopt_args r
+local nm="$compstate[nmatches]"
 local opre="$PREFIX" oipre="$IPREFIX" ocur="$CURRENT"
 local osuf="$SUFFIX" oisuf="$ISUFFIX" owords
+local _ms_match _ms_opt _ms_soptmid _ms_soptmidadd _ms_soptend
+local _ms_optnext _ms_optdirect _ms_optequal
 
-owords="$words[@]"
+_ms_soptmid=()
+_ms_soptmidadd=()
+_ms_soptend=()
+_ms_optnext=()
+_ms_optdirect=()
+_ms_optequal=()
 
+owords=("$words[@]")
+
 end=$argv[(i)-]
 [[ end -gt $# ]] && return 1
 
@@ -16,14 +26,22 @@
 xor=()
 ostate=()
 ocontext=()
+oopt_args=()
 
 while true; do
   end=$argv[(i)-]
 
-  _arguments -m xor "$1" "$all[@]" "${(@)argv[2,end-1]}"
+  if [[ "$1" = \(*\) ]]; then
+    _arguments -m xor "${1[2,-2]}" "$all[@]" \
+               "$1${(@)^argv[2,end-1]:#\(*}" \
+               "${1[1,-2]} ${(@)${(@M)^argv[2,end-1]:#\(*}#?}"
+  else
+    _arguments -m xor "$1" "$all[@]" "${(@)argv[2,end-1]}"
+  fi
+  
   r=$?
 
-  oopt_args=( "$oopt_args[@]" "${(kv)opt_args}" )
+  oopt_args=( "$oopt_args[@]" "${(@kv)opt_args}" )
   if [[ r -eq 300 ]]; then
     ret=300
     ostate=( "$ostate[@]" "$state[@]" )
@@ -39,6 +57,14 @@
 
   shift end
 done
+
+[[ -n "$_ms_opt" ]] &&
+  _describe -o option \
+            _ms_soptmid _ms_soptmidadd -Q -S '' -- \
+	    _ms_soptend -Q -- \
+	    _ms_optnext -Q -M "$_ms_match" -- \
+	    _ms_optdirect -QS '' -M "$_ms_match" -- \
+	    _ms_optequal -QqS= -M "$_ms_match" && [[ ret -eq 1 ]] && ret=0
 
 opt_args=( "$oopt_args[@]" )
 
Index: Completion/Base/_arguments
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Base/_arguments,v
retrieving revision 1.14
diff -u -r1.14 _arguments
--- Completion/Base/_arguments	2000/05/09 09:52:27	1.14
+++ Completion/Base/_arguments	2000/05/11 08:52:01
@@ -163,11 +163,13 @@
 zstyle -s ":completion:${curcontext}:options" auto-description autod
 
 if (( $# )) && comparguments "$multi[@]" "$autod" "$@"; then
-  local nm="$compstate[nmatches]" action noargs aret expl local
+  local action noargs aret expl local
   local next direct odirect equal single match matched ws tmp1 tmp2 tmp3
   local opts subc tc prefix suffix descrs actions subcs
   local origpre="$PREFIX" origipre="$IPREFIX"
 
+  [[ -z "$ismulti" ]] && local nm="$compstate[nmatches]"
+
   if comparguments -D descrs actions subcs; then
     if comparguments -O next direct odirect equal; then
       opts=yes
@@ -314,17 +316,32 @@
 	    tmp1=( "${(M@)tmp1:#[-+]?(|:*)}" )
 	    tmp2=( "${PREFIX}${(@M)^${(@)${(@)tmp1%%:*}#[-+]}:#?}" )
 
-            _describe -o option \
-                      tmp1 tmp2 -Q -S '' -- \
-		      tmp3 -Q
+	    if [[ -n "$ismulti" ]]; then
+	      _ms_opt=yes
+	      _ms_soptmid=( "$_ms_soptmid[@]" "$tmp1[@]" )
+	      _ms_soptmidadd=( "$_ms_soptmidadd[@]" "$tmp2[@]" )
+	      _ms_soptend=( "$_ms_soptend[@]" "$tmp3[@]" )
+	    else
+              _describe -o option \
+                        tmp1 tmp2 -Q -S '' -- \
+		        tmp3 -Q
+            fi
           fi
           single=yes
         else
           next=( "$next[@]" "$odirect[@]" )
-          _describe -o option \
-            next -Q -M "$match" -- \
-            direct -QS '' -M "$match" -- \
-            equal -QqS= -M "$match"
+	  if [[ -n "$ismulti" ]]; then
+	    _ms_opt=yes
+	    _ms_match="$_ms_match $match"
+	    _ms_optnext=( "$_ms_optnext[@]" "$next[@]" )
+	    _ms_optdirect=( "$_ms_optdirect[@]" "$direct[@]" )
+	    _ms_optequal=( "$_ms_optequal[@]" "$equal[@]" )
+	  else
+            _describe -o option \
+                      next -Q -M "$match" -- \
+                      direct -QS '' -M "$match" -- \
+                      equal -QqS= -M "$match"
+          fi
         fi
 	PREFIX="$prevpre"
 	IPREFIX="$previpre"
Index: Doc/Zsh/compsys.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/compsys.yo,v
retrieving revision 1.44
diff -u -r1.44 compsys.yo
--- Doc/Zsh/compsys.yo	2000/05/11 08:40:10	1.44
+++ Doc/Zsh/compsys.yo	2000/05/11 08:52:08
@@ -3252,6 +3252,20 @@
 given, both sets will still be considered valid, because it appears
 before the first hyphen, so both sets contain this option.
 
+If the name-string is of the form `tt(LPAR())var(name)tt(RPAR())' then 
+all specifications in the set have an implicit exclusion list
+containing the name of the set, i.e. all specifications are mutual
+exclusive with all other specifications in the same set. This is
+useful for defining multiple sets of options which are mutual
+exclusive and in which the options are aliases for each other. E.g.:
+
+example(_argument_sets \ 
+    -a -b \ 
+  - '(compress)' \
+    {-c,--compress}'[compress]' \ 
+  - '(uncompress)' \ 
+    {-d,--decompress}'[decompress]')
+
 Don't expect too much with complicated options that get their
 arguments in the same string and `tt(->)var(state)' actions or with
 the tt(-C) option that is given to tt(_arguments), otherwise most
Index: Src/Zle/computil.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/computil.c,v
retrieving revision 1.18
diff -u -r1.18 computil.c
--- Src/Zle/computil.c	2000/05/10 11:53:06	1.18
+++ Src/Zle/computil.c	2000/05/11 08:52:11
@@ -1058,26 +1058,46 @@
     if ((xor || opts) && cur <= compcurrent) {
 	Caopt opt;
 	char *x;
-	int sl = (d->set ? strlen(d->set) : -1);
+	int sl = (d->set ? strlen(d->set) : -1), set = 0;
 
 	for (; (x = (opts ? "-" : *xor)); xor++) {
 	    if (ca_xor)
 		addlinknode(ca_xor, x);
+	    set = 0;
 	    if (sl > 0) {
-		if (strpfx(d->set, x))
+		if (strpfx(d->set, x)) {
 		    x += sl;
-		else if (!strncmp(d->set, x, sl - 1))
-		    return 1;
+		    set = 1;
+		} else if (!strncmp(d->set, x, sl - 1)) {
+		    Caopt p;
+
+		    for (p = d->opts; p; p = p->next)
+			if (p->set)
+			    p->active = 0;
+			
+		    x = ":";
+		    set = 1;
+		}
 	    }
-	    if (x[0] == ':' && !x[1])
-		d->argsactive = 0;
-	    else if (x[0] == '-' && !x[1]) {
+	    if (x[0] == ':' && !x[1]) {
+		if (set) {
+		    Caarg a;
+
+		    for (a = d->args; a; a = a->next)
+			if (a->set)
+			    a->active = 0;
+		    if (d->rest && (!set || d->rest->set))
+			d->rest->active = 0;
+		} else
+		    d->argsactive = 0;
+	    } else if (x[0] == '-' && !x[1]) {
 		Caopt p;
 
 		for (p = d->opts; p; p = p->next)
-		    p->active = 0;
+		    if (!set || p->set)
+			p->active = 0;
 	    } else if (x[0] == '*' && !x[1]) {
-		if (d->rest)
+		if (d->rest && (!set || d->rest->set))
 		    d->rest->active = 0;
 	    } else if (x[0] >= '0' && x[0] <= '9') {
 		int n = atoi(x);
@@ -1086,9 +1106,9 @@
 		while (a && a->num < n)
 		    a = a->next;
 
-		if (a && a->num == n)
+		if (a && a->num == n && (!set || a->set))
 		    a->active = 0;
-	    } else if ((opt = ca_get_opt(d, x, 1, NULL)))
+	    } else if ((opt = ca_get_opt(d, x, 1, NULL)) && (!set || opt->set))
 		opt->active = 0;
 
 	    if (opts)
@@ -1319,7 +1339,7 @@
 		state.nargbeg = cur - 1;
 		state.argend = argend;
 	    }
-	    if (!d->args && !d->rest)
+	    if (!d->args && !d->rest && *line != '-' && *line != '+')
 		return 1;
 	    if ((adef = state.def = ca_get_arg(d, state.nth)) &&
 		(state.def->type == CAA_RREST ||

--
Sven Wischnowsky                         wischnow@xxxxxxxxxxxxxxxxxxxxxxx



Messages sorted by: Reverse Date, Date, Thread, Author