From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14839 invoked from network); 9 May 2000 09:03:24 -0000 Received: from sunsite.auc.dk (130.225.51.30) by ns1.primenet.com.au with SMTP; 9 May 2000 09:03:24 -0000 Received: (qmail 12712 invoked by alias); 9 May 2000 09:03:05 -0000 Mailing-List: contact zsh-workers-help@sunsite.auc.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 11270 Received: (qmail 12666 invoked from network); 9 May 2000 09:03:02 -0000 Date: Tue, 9 May 2000 11:02:57 +0200 (MET DST) Message-Id: <200005090902.LAA14162@beta.informatik.hu-berlin.de> From: Sven Wischnowsky To: zsh-workers@sunsite.auc.dk In-reply-to: "Bart Schaefer"'s message of Mon, 8 May 2000 17:58:14 +0000 Subject: PATCH: Re: Assorted _arguments arguments Bart Schaefer wrote: > On May 8, 11:00am, Sven Wischnowsky wrote: > > ... > > } But before I start writing it: should the default for _arguments be > } changed? And would someone be willing to check all uses of _arguments > } and add the option to the calls that need them? > > I don't think it makes a lot of difference which way the default goes; > do whatever would require the fewest changes to _arguments and to all > the other functions that call it. I didn't have much time yesterday and won't have any time today, so this is only the change to _arguments. It adds the `-A' and `-S' options (I couldn't think of better characters, but that's easy to change). `-A' means: no options after the first argument and `-S' means no options after the `--' separator. As with `-s' they can be given to _arguments before the specs. Changing the default behaviour would be implemented in _arguments (this patch mostly changes the builtin behind it). Then there is a change for this option-equal thing. I've chosen the syntax `-opt=-' to mean: the option has to come after the equal sign, not in a separate word. I didn't use `-opt=?' because, at least to me, this looks like making the `=' optional, i.e. the old behaviour, which is still the default. This, too, would be easy to change if we find out that we will have to change more `-opt='s (to `-opt=-') than we can leave untouched. I haven't had a look at the completion functions to see which we have to change and I preferred to not change the default behaviour. No patches for the other two things, yet... > ... > > } Exactly, the existence of `=' is the criteria used by getopt_long. So > } it's good. But I vote `-opt=?' instead of `-opt=='. > > I think we should try to make the syntax consistent with `getopts' and > `zparseopts' if possible. Maybe that _isn't_ possible do to conflicting > use of colons ... and maybe we should have thought of that before we used > colons everywhere, but ... Maybe, I hope we (ok, I) can be excused for not making this more consistent because _arguments does a whole lot more than getopts and because of that I didn't think of getopts at that time. > } Note that another common criteria is that a optional argument must be > } some set of strings: `yes' or `no' for example. At least, xset > } handles optional arguments in this way. If we can specify a pattern > } addition to the current optional argument syntax, it can be handled. > > If there's a known set of strings that can be the optional argument, then > I think this can be handled with state changes and/or alternation and we > don't need any more patterns jammed into the opt-spec. I was thinking the same yesterday. Maybe someone can think of a nice utility function that plays together with _arguments in such cases (this is not entirely trivial because the optional option-argument that's causing the trouble is *not* returned by the builtin, but maybe we could make... or something). > ... > > 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.) When thinking about this yesterday, I was reminded of _argument_sets. This does something entirely different, but the point is that this already works with `sets'. For _argument_sets they are mutually exclusive, but maybe we could get something similar (a wrapper function for _arguments) with the opposite meaning, i.e. you define multiple sets of options and the options in each set are mutually exclusive. That with some sharing of descriptions, arguments etc. should be enough. And even easier to read than the possibly longish comma lists. I've got to think some more about this (and look at the code), but it sounds promising. Bye Sven Index: Doc/Zsh/compsys.yo =================================================================== RCS file: /cvsroot/zsh/zsh/Doc/Zsh/compsys.yo,v retrieving revision 1.38 diff -u -r1.38 compsys.yo --- Doc/Zsh/compsys.yo 2000/05/08 18:14:46 1.38 +++ Doc/Zsh/compsys.yo 2000/05/09 08:42:13 @@ -2951,7 +2951,10 @@ separate argument after the option, a plus sign should be used instead. If the argument may be given as the next string or in same string as the option name but separated from it by an equal sign, a -`tt(=)' should be used instead of the minus or plus sign. +`tt(=)' should be used instead of the minus or plus sign and if the +argument to the option has to be given in the same string after an +equal sign and may not be given in the next argument, `tt(=-)' should +be used. Note that this and the shortcut syntax with a leading tt(-+) or tt(+-) means that for options like tt(-+) the second character has to be @@ -3092,6 +3095,12 @@ `tt(-)tt(-prefix)') are still considered to contain only one option name. This allows the use of the `tt(-s)' option to describe single-letter options together with such long option names. + +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. Another option supported is `tt(-O) var(name)'. The var(name) will be taken as the name of an array and its elements will be given to Index: Src/Zle/computil.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/Zle/computil.c,v retrieving revision 1.14 diff -u -r1.14 computil.c --- Src/Zle/computil.c 2000/05/08 10:37:58 1.14 +++ Src/Zle/computil.c 2000/05/09 08:42:14 @@ -305,8 +305,12 @@ int argsactive; /* if arguments are still allowed */ /* used while parsing a command line */ char *set; /* set name, shared */ + int flags; /* see CDF_* below */ }; +#define CDF_SEP 1 +#define CDF_ARG 2 + /* Description for an option. */ struct caopt { @@ -325,6 +329,7 @@ #define CAO_DIRECT 2 #define CAO_ODIRECT 3 #define CAO_EQUAL 4 +#define CAO_OEQUAL 5 /* Description for an argument */ @@ -515,7 +520,7 @@ Caarg argp; char **oargs = args, *p, *q, *match = "r:|[_-]=* r:|=*", **xor; char *adpre, *adsuf, *set = NULL, *doset = NULL; - int single = 0, anum = 1, xnum, nopts, ndopts, nodopts; + int single = 0, anum = 1, xnum, nopts, ndopts, nodopts, flags = 0; nopts = ndopts = nodopts = 0; @@ -536,23 +541,40 @@ } else adpre = adsuf = NULL; - /* Now get the -s and -M options. */ + /* Now get the -s, -A, -S and -M options. */ args++; - while ((p = *args)) { - if (!strcmp(p, "-s")) - single = 1; - else if (p[0] == '-' && p[1] == 'M') { - if (p[2]) - match = p + 2; - else if (args[1]) - match = *++args; - else { - args++; + while ((p = *args) && *p == '-') { + for (q = ++p; *q; q++) + if (*q == 'M') { + q = ""; + break; + } else if (*q != 's' && *q != 'S' && *q != 'A') break; + + if (*q) + break; + + for (; *p; p++) { + if (*p == 's') + single = 1; + else if (*p == 'S') + flags |= CDF_SEP; + else if (*p == 'A') + flags |= CDF_ARG; + else if (*p == 'M') { + if (p[1]) { + match = p + 1; + p = "" - 1; + } else if (args[1]) + match = *++args; + else + break; } - } else + } + if (*p) break; + args++; } if (!*args) @@ -574,6 +596,7 @@ } else ret->single = NULL; ret->match = ztrdup(match); + ret->flags = flags; /* Get the definitions. */ @@ -659,8 +682,10 @@ /* Skip over the name. */ for (p++; *p && *p != ':' && *p != '[' && - ((*p != '-' && *p != '+' && *p != '=') || - (p[1] != ':' && p[1] != '[')); p++) + ((*p != '-' && *p != '+') || + (p[1] != ':' && p[1] != '[')) && + (*p != '=' || + (p[1] != ':' && p[1] != '[' && p[1] != '-')); p++) if (*p == '\\' && p[1]) p++; @@ -674,8 +699,11 @@ otype = CAO_ODIRECT; c = *++p; } else if (c == '=') { - otype = CAO_EQUAL; - c = *++p; + otype = CAO_OEQUAL; + if ((c = *++p) == '-') { + otype = CAO_EQUAL; + c = *++p; + } } /* Get the optional description, if any. */ if (c == '[') { @@ -797,9 +825,9 @@ opt->args = oargs; opt->num = nopts++; - if (otype == CAO_DIRECT) + if (otype == CAO_DIRECT || otype == CAO_EQUAL) ndopts++; - else if (otype == CAO_ODIRECT || otype == CAO_EQUAL) + else if (otype == CAO_ODIRECT || otype == CAO_OEQUAL) nodopts++; /* If this is for single-letter option we also store a @@ -952,7 +980,8 @@ /* Return a pointer to the end of the option. */ int l = strlen(p->name); - if (p->type == CAO_EQUAL && line[l] == '=') + if ((p->type == CAO_OEQUAL || p->type == CAO_EQUAL) && + line[l] == '=') l++; *end = line + l; @@ -983,7 +1012,8 @@ p->args && p->type != CAO_NEXT && p->name[0] == pre) { if (end) { line++; - if (p->type == CAO_EQUAL && *line == '=') + if ((p->type == CAO_OEQUAL || p->type == CAO_EQUAL) && + *line == '=') line++; *end = line; } @@ -1022,14 +1052,14 @@ static LinkList ca_xor; static int -ca_inactive(Cadef d, char **xor, int cur) +ca_inactive(Cadef d, char **xor, int cur, int opts) { - if (xor && cur <= compcurrent) { + if ((xor || opts) && cur <= compcurrent) { Caopt opt; char *x; int sl = (d->set ? strlen(d->set) : -1); - for (; (x = *xor); xor++) { + for (; (x = (opts ? "-" : *xor)); xor++) { if (ca_xor) addlinknode(ca_xor, x); if (sl > 0) { @@ -1059,6 +1089,9 @@ a->active = 0; } else if ((opt = ca_get_opt(d, x, 1, NULL))) opt->active = 0; + + if (opts) + break; } } return 0; @@ -1145,10 +1178,13 @@ ddef = adef = NULL; doff = state.singles = 0; - if (ca_inactive(d, argxor, cur)) - return 1; - - /* We've a definition for an argument, skip to the next. */ + if (ca_inactive(d, argxor, cur, 0) || + ((d->flags & CDF_SEP) && !strcmp(line, "--"))) { + if (ca_inactive(d, NULL, cur, 1)) + return 1; + continue; + } + /* We've got a definition for an argument, skip to the next. */ if (state.def) { state.arg = 0; @@ -1186,10 +1222,14 @@ /* See if it's an option. */ if (state.opt == 2 && (state.curopt = ca_get_opt(d, line, 0, &pe)) && - (state.curopt->type != CAO_EQUAL || - compwords[cur] || pe[-1] == '=')) { - - ddef = state.def = state.curopt->args; + (state.curopt->type == CAO_OEQUAL ? + (compwords[cur] || pe[-1] == '=') : + (state.curopt->type == CAO_EQUAL ? + (pe[-1] == '=' || !pe[0]) : 1))) { + + ddef = state.def = ((state.curopt->type != CAO_EQUAL || + pe[-1] == '=') ? + state.curopt->args : NULL); doff = pe - line; state.optbeg = state.argbeg = state.inopt = cur; state.singles = (d->single && (!pe || !*pe) && @@ -1197,15 +1237,16 @@ state.oargs[state.curopt->num] = znewlinklist(); - if (ca_inactive(d, state.curopt->xor, cur)) + if (ca_inactive(d, state.curopt->xor, cur, 0)) return 1; /* Collect the argument strings. Maybe. */ if (state.def && (state.curopt->type == CAO_DIRECT || + state.curopt->type == CAO_EQUAL || (state.curopt->type == CAO_ODIRECT && pe[0]) || - (state.curopt->type == CAO_EQUAL && + (state.curopt->type == CAO_OEQUAL && (pe[0] || pe[-1] == '=')))) { if (state.def->type != CAA_REST && state.def->type != CAA_RARGS && @@ -1237,14 +1278,15 @@ if ((tmpopt = d->single[STOUC(*p)])) { state.oargs[tmpopt->num] = znewlinklist(); - if (ca_inactive(d, tmpopt->xor, cur)) + if (ca_inactive(d, tmpopt->xor, cur, 0)) return 1; } } if (state.def && (state.curopt->type == CAO_DIRECT || + state.curopt->type == CAO_EQUAL || (state.curopt->type == CAO_ODIRECT && pe[0]) || - (state.curopt->type == CAO_EQUAL && + (state.curopt->type == CAO_OEQUAL && (pe[0] || pe[-1] == '=')))) { if (state.def->type != CAA_REST && state.def->type != CAA_RARGS && @@ -1261,6 +1303,9 @@ return 1; else if (state.arg) { /* Otherwise it's a normal argument. */ + if ((d->flags & CDF_ARG) && ca_inactive(d, NULL, cur + 1, 1)) + return 1; + if (state.inopt) { state.inopt = 0; state.nargbeg = cur - 1; @@ -1541,7 +1586,7 @@ ca_xor = newlinklist(); if ((xor = getaparam(args[1]))) { if (arrcontains(xor, args[2], 0) || - ca_inactive(def, xor, compcurrent)) { + ca_inactive(def, xor, compcurrent, 0)) { ca_xor = cax; return 1; } @@ -1645,7 +1690,8 @@ ztrdup(ca_laststate.ddef ? (ca_laststate.ddef->type == CAO_DIRECT ? "direct" : - (ca_laststate.ddef->type == CAO_EQUAL ? + ((ca_laststate.ddef->type == CAO_OEQUAL || + ca_laststate.ddef->type == CAO_EQUAL) ? "equal" : "next")) : "")); return 0; } -- Sven Wischnowsky wischnow@informatik.hu-berlin.de