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

Re: Replacing getopts with zparseopts



On May 15,  8:49pm, Thorsten Kampe wrote:
}
} So zparseopts is not a "better getopts". So what do people use to be 
} able to use (and parse) long options??

This might be helpful.  With the patch below, one can e.g. do

    zparseopts -M d=opt_d -debug=d

and have both the -d and the --debug options stashed in the $opt_d
array.  There's a remaining buglet here that I haven't decided how
to handle:  Given the above spec, the $d array is also created (or
reset) but is always empty.  The most straightforward fix for this
would be simply to assert that -M always implies -K.

The patch also fixes this bug:

torch% zparseopts -- -debug=d
zparseopts: missing option descriptions

The problem is that the generic command parser handles "--" natively,
removing it from the arguments passed to bin_zparseopts(), which
then caused "-debug=d" to be ignored.

Index: Doc/Zsh/mod_zutil.yo
===================================================================
diff -c -r1.6 mod_zutil.yo
--- Doc/Zsh/mod_zutil.yo	26 Nov 2007 17:38:13 -0000	1.6
+++ Doc/Zsh/mod_zutil.yo	16 May 2011 17:39:16 -0000
@@ -178,7 +178,7 @@
 This implements some internals of the tt(_regex_arguments) function.
 )
 findex(zparseopts)
-item(tt(zparseopts) [ tt(-D) ] [ tt(-K) ] [ tt(-E) ] [ tt(-a) var(array) ] [
tt(-A) var(assoc) ] var(specs))(
+item(tt(zparseopts) [ tt(-D) ] [ tt(-K) ] [ tt(-M) ] [ tt(-E) ] [ tt(-a)
var(array) ] [ tt(-A) var(assoc) ] var(specs))(
 This builtin simplifies the parsing of options in positional parameters,
 i.e. the set of arguments given by tt($*).  Each var(spec) describes one
 option and must be of the form `var(opt)[tt(=)var(array)]'.  If an option
@@ -255,6 +255,15 @@
 of the var(specs) for them is used.  This allows assignment of default
 values to them before calling tt(zparseopts).
 )
+item(tt(-M))(
+This changes the assignment rules to implement a map among equivalent
+option names.  If any var(spec) uses the `tt(=)var(array)' form, the
+string var(array) is interpreted as the name of another var(spec),
+which is used to choose where to store the values.  If no other var(spec)
+is found, the values are stored as usual.  This changes only the way the
+values are stored, not the way tt($*) is parsed, so results may be
+unpredicable if the `var(name)tt(+)' specifier is used inconsistently.
+)
 item(tt(-E))(
 This changes the parsing rules to em(not) stop at the first string
 that isn't described by one of the var(spec)s.  It can be used to test
@@ -288,5 +297,15 @@
 
 I.e., the option tt(-b) and its arguments are taken from the
 positional parameters and put into the array tt(bar).
+
+The tt(-M) option can be used like this:
+
+example(set -- -a -bx -c y -cz baz -cend
+zparseopts -A bar -M a=foo b+: c:=b)
+
+to have the effect of
+
+example(foo=(-a)
+bar=(-a '' -b xyz))
 )
 enditem()
Index: Src/Modules/zutil.c
===================================================================
diff -c -r1.11 zutil.c
--- Src/Modules/zutil.c	21 Dec 2010 16:41:16 -0000	1.11
+++ Src/Modules/zutil.c	16 May 2011 18:15:53 -0000
@@ -1405,6 +1405,7 @@
 #define ZOF_OPT  2
 #define ZOF_MULT 4
 #define ZOF_SAME 8
+#define ZOF_MAP 16
 
 struct zoptarr {
     Zoptarr next;
@@ -1466,6 +1467,12 @@
     char *n = dyncat("-", d->name);
     int new = 0;
 
+    while (d->flags & ZOF_MAP) {
+	Zoptdesc map = get_opt_desc(d->arr->name);
+	if (!map || !strcmp(map->name, n+1))
+	    break;
+	d = map;
+    }
     if (!(d->flags & ZOF_MULT))
 	v = d->vals;
     if (!v) {
@@ -1513,7 +1520,7 @@
 bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
 {
     char *o, *p, *n, **pp, **aval, **ap, *assoc = NULL, **cp, **np;
-    int del = 0, f, extract = 0, keep = 0;
+    int del = 0, flags = 0, extract = 0, keep = 0;
     Zoptdesc sopts[256], d;
     Zoptarr a, defarr = NULL;
     Zoptval v;
@@ -1531,6 +1538,7 @@
 	    case '-':
 		if (o[2])
 		    args--;
+		/* else unreachable, default parsing removes "--" */
 		o = NULL;
 		break;
 	    case 'D':
@@ -1557,6 +1565,14 @@
 		}
 		keep = 1;
 		break;
+	    case 'M':
+		if (o[2]) {
+		    args--;
+		    o = NULL;
+		    break;
+		}
+		flags |= ZOF_MAP;
+		break;
 	    case 'a':
 		if (defarr) {
 		    zwarnnam(nam, "default array given more than once");
@@ -1578,6 +1594,10 @@
 		opt_arrs = defarr;
 		break;
 	    case 'A':
+		if (assoc) {
+		    zwarnnam(nam, "associative array given more than once");
+		    return 1;
+		}
 		if (o[2]) 
 		    assoc = o + 2;
 		else if (*args)
@@ -1587,6 +1607,11 @@
 		    return 1;
 		}
 		break;
+	    default:
+		/* Anything else is an option description */
+		args--;
+		o = NULL;
+		break;
 	    }
 	    if (!o) {
 		o = "";
@@ -1602,11 +1627,11 @@
 	return 1;
     }
     while ((o = dupstring(*args++))) {
+	int f = 0;
 	if (!*o) {
 	    zwarnnam(nam, "invalid option description: %s", o);
 	    return 1;
 	}
-	f = 0;
 	for (p = o; *p; p++) {
 	    if (*p == '\\' && p[1])
 		p++;
@@ -1633,6 +1658,7 @@
 	a = NULL;
 	if (*p == '=') {
 	    *p++ = '\0';
+	    f |= flags;
 	    if (!(a = get_opt_arr(p))) {
 		a = (Zoptarr) zhalloc(sizeof(*a));
 		a->name = p;



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