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

PATCH: _arguments



Ok, here's the patch for _arguments. To repeat:

- -A now takes a pattern as argument. All words matching that pattern
  are *not* taken to be normal arguments and hence don't keep it from
  completing options (i.e. it will often be called as `-A "-*"').
- -s with option strings that contain more than one option with
  arguments in the next word should work now.
- The unrecognised option bug from 11801 should be fixed now. Those
  tests were very restrictive, and if I remember correctly, I did that 
  because of some ugly interaction between _arguments and
  _argument_sets when that was still a separate function.
  If anyone sees weird results when completing options from multiple
  sets, please tell me.


Bye
 Sven

Index: Doc/Zsh/compsys.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/compsys.yo,v
retrieving revision 1.63
diff -u -r1.63 compsys.yo
--- Doc/Zsh/compsys.yo	2000/06/13 11:55:07	1.63
+++ Doc/Zsh/compsys.yo	2000/06/13 12:06:46
@@ -2931,10 +2931,15 @@
     {-d,--decompress}'[decompress]')
 
 To simplify the specifications for commands with standard option
-parsing, the options tt(-A) and tt(-S) may be given. With tt(-A) no
-options will be completed after the first non-option argument on the
-line. With tt(-S), no option will be completed after a `tt(-)tt(-)' on 
-the line and this argument will otherwise be ignored.
+parsing, the options tt(-S) and tt(-A) may be given.  With tt(-S), no
+option will be completed after a `tt(-)tt(-)' on the line and this
+argument will otherwise be ignored. With tt(-A), no options will be
+completed after the first non-option argument on the line.  The tt(-A) 
+has to be followed by a pattern matching all strings which are not to
+be taken as arguemnts. For example, to make tt(_arguments) stop
+completing options after the first normal argument, but ignoring all
+strings starting with a hyphen even if they are not described by one
+of the var(optspec)s, one would use: `tt(-A "-*")'.
 
 Note that using multiple sets will be slower than using only one set
 because the completion code has to parse the command line once for
Index: Src/Zle/computil.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/computil.c,v
retrieving revision 1.28
diff -u -r1.28 computil.c
--- Src/Zle/computil.c	2000/06/13 09:05:37	1.28
+++ Src/Zle/computil.c	2000/06/13 12:06:47
@@ -308,10 +308,10 @@
     char *set;			/* set name prefix (<name>-), shared */
     char *sname;		/* set name */
     int flags;			/* see CDF_* below */
+    char *nonarg;		/* pattern for non-args (-A argument) */
 };
 
 #define CDF_SEP 1
-#define CDF_ARG 2
 
 /* Description for an option. */
 
@@ -423,6 +423,7 @@
 	}
 	freecaargs(d->args);
 	freecaargs(d->rest);
+	zsfree(d->nonarg);
 	if (d->single)
 	    zfree(d->single, 256 * sizeof(Caopt));
 	zfree(d, sizeof(*d));
@@ -518,7 +519,7 @@
 }
 
 static Cadef
-alloc_cadef(char **args, int single, char *match, int flags)
+alloc_cadef(char **args, int single, char *match, char *nonarg, int flags)
 {
     Cadef ret;
 
@@ -526,6 +527,7 @@
     ret->next = ret->snext = NULL;
     ret->opts = NULL;
     ret->args = ret->rest = NULL;
+    ret->nonarg = ztrdup(nonarg);
     if (args) {
 	ret->defs = zarrdup(args);
 	ret->ndefs = arrlen(args);
@@ -569,6 +571,7 @@
     Caopt *optp;
     char **oargs = args, *p, *q, *match = "r:|[_-]=* r:|=*", **xor, **sargs;
     char *adpre, *adsuf, *axor = NULL, *doset = NULL, **setp = NULL;
+    char *nonarg = NULL;
     int single = 0, anum = 1, xnum, nopts, ndopts, nodopts, flags = 0;
     int state = 0;
 
@@ -591,10 +594,10 @@
     args++;
     while ((p = *args) && *p == '-' && p[1]) {
 	for (q = ++p; *q; q++)
-	    if (*q == 'M') {
+	    if (*q == 'M' || *q == 'A') {
 		q = "";
 		break;
-	    } else if (*q != 's' && *q != 'S' && *q != 'A')
+	    } else if (*q != 's' && *q != 'S')
 		break;
 
 	if (*q)
@@ -605,10 +608,16 @@
 		single = 1;
 	    else if (*p == 'S')
 		flags |= CDF_SEP;
-	    else if (*p == 'A')
-		flags |= CDF_ARG;
-	    else if (*p == 'M') {
+	    else if (*p == 'A') {
 		if (p[1]) {
+		    nonarg = p + 1;
+		    p = "" - 1;
+		} else if (args[1])
+		    nonarg = *++args;
+		else
+		    break;
+	    } else if (*p == 'M') {
+		if (p[1]) {
 		    match = p + 1;
 		    p = "" - 1;
 		} else if (args[1])
@@ -625,9 +634,12 @@
     if (!*args)
 	return NULL;
 
+    if (nonarg)
+	tokenize(nonarg = dupstring(nonarg));
+
     /* Looks good. Optimistically allocate the cadef structure. */
 
-    all = ret = alloc_cadef(oargs, single, match, flags);
+    all = ret = alloc_cadef(oargs, single, match, nonarg, flags);
     optp = &(ret->opts);
     anum = 1;
 
@@ -662,7 +674,7 @@
 		ret->ndopts = ndopts;
 		ret->nodopts = nodopts;
 		set_cadef_opts(ret);
-		ret = ret->snext = alloc_cadef(NULL, single, NULL, flags);
+		ret = ret->snext = alloc_cadef(NULL, single, NULL, nonarg, flags);
 		optp = &(ret->opts);
 		nopts = ndopts = nodopts = 0;
 		anum = 1;
@@ -1064,21 +1076,21 @@
 /* Same as above, only for single-letter-style. */
 
 static Caopt
-ca_get_sopt(Cadef d, char *line, int full, char **end)
+ca_get_sopt(Cadef d, char *line, char **end, LinkList *lp)
 {
     Caopt p;
     char pre = *line++;
+    LinkList l = NULL;
 
-    if (full) {
-	for (p = NULL; *line; line++)
-	    if (!(p = d->single[STOUC(*line)]) || !p->active ||
-		(line[1] && p->args))
-		return NULL;
-	return p;
-    } else {
-	for (p = NULL; *line; line++)
-	    if ((p = d->single[STOUC(*line)]) && p->active &&
-		p->args && p->type != CAO_NEXT && p->name[0] == pre) {
+    *lp = NULL;
+    for (p = NULL; *line; line++)
+	if ((p = d->single[STOUC(*line)]) && p->active &&
+	    p->args && p->name[0] == pre) {
+	    if (p->type == CAO_NEXT) {
+		if (!l)
+		    *lp = l = newlinklist();
+		addlinknode(l, p);
+	    } else {
 		if (end) {
 		    line++;
 		    if ((p->type == CAO_OEQUAL || p->type == CAO_EQUAL) &&
@@ -1087,14 +1099,12 @@
 		    *end = line;
 		}
 		break;
-	    } else if (!p || !p->active || (line[1] && p->args) ||
-		       p->name[0] != pre)
-		return NULL;
-	if (p && end)
-	    *end = line;
-	return p;
-    }
-    return NULL;
+	    }
+	} else if (!p || (!p->active && p->name[0] != pre))
+	    return NULL;
+    if (p && end)
+	*end = line;
+    return p;
 }
 
 /* Return the n'th argument definition. */
@@ -1228,7 +1238,8 @@
     struct castate state;
     char *line, *pe, **argxor = NULL;
     int cur, doff, argend, arglast;
-    Patprog endpat = NULL;
+    Patprog endpat = NULL, napat = NULL;
+    LinkList sopts = NULL;
 
     /* Free old state. */
 
@@ -1279,6 +1290,9 @@
 
 	goto end;
     }
+    if (d->nonarg)
+	napat = patcompile(d->nonarg, 0, NULL);
+
     /* Loop over the words from the line. */
 
     for (line = compwords[1], cur = 2, state.curopt = NULL, state.def = NULL;
@@ -1315,6 +1329,15 @@
 	    } else if ((state.def = state.def->next)) {
 		state.argbeg = cur;
 		state.argend = argend;
+	    } else if (sopts && nonempty(sopts)) {
+		state.curopt = (Caopt) uremnode(sopts, firstnode(sopts));
+		state.def = state.curopt->args;
+		state.opt = 0;
+		state.argbeg = state.optbeg = state.inopt = cur;
+		state.argend = argend;
+		doff = state.doff = 0;
+		state.singles = 1;
+		goto cont;
 	    } else {
 		state.curopt = NULL;
 		state.opt = 1;
@@ -1378,12 +1401,16 @@
 		state.curopt = NULL;
 	    }
 	} else if (state.opt == 2 && d->single &&
-		   (state.curopt = ca_get_sopt(d, line, 0, &pe))) {
+		   ((state.curopt = ca_get_sopt(d, line, &pe, &sopts)) ||
+		    (sopts && nonempty(sopts)))) {
 	    /* Or maybe it's a single-letter option? */
 
 	    char *p;
 	    Caopt tmpopt;
 
+	    if (sopts && nonempty(sopts))
+		state.curopt = (Caopt) uremnode(sopts, firstnode(sopts));
+
 	    ddef = state.def = state.curopt->args;
 	    dopt = state.curopt;
 	    doff = pe - line;
@@ -1419,9 +1446,9 @@
 		state.curopt = NULL;
 	} else if (multi && (*line == '-' || *line == '+') && cur != compcurrent)
 	    return 1;
-	else if (state.arg) {
+	else if (state.arg && (!napat || !pattry(napat, line))) {
 	    /* Otherwise it's a normal argument. */
-	    if ((d->flags & CDF_ARG) && ca_inactive(d, NULL, cur + 1, 1))
+	    if (napat && ca_inactive(d, NULL, cur + 1, 1))
 		return 1;
 
 	    arglast = 1;
@@ -1438,9 +1465,7 @@
 		state.inrest = 0;
 		state.opt = (cur == state.nargbeg + 1 &&
 			     (!multi || !*line || 
-			      ((*line == '-' || *line == '+') &&
-			       (!line[1] ||
-				(*line == '-' && line[1] == '-' && !line[2])))));
+			      *line == '-' || *line == '+'));
 		state.optbeg = state.nargbeg;
 		state.argbeg = cur - 1;
 		state.argend = argend;
@@ -1517,9 +1542,7 @@
 	    } else {
 		ca_laststate.def = adef;
 		ca_laststate.opt = (!arglast || !multi || !*line || 
-				    ((*line == '-' || *line == '+') &&
-				     (!line[1] ||
-				      (*line == '-' && line[1] == '-' && !line[2]))));
+				    *line == '-' || *line == '+');
 		ca_laststate.ddef = NULL;
 		ca_laststate.dopt = NULL;
 		ca_laststate.optbeg = state.nargbeg;

--
Sven Wischnowsky                         wischnow@xxxxxxxxxxxxxxxxxxxxxxx



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