From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 13163 invoked from network); 11 May 2000 08:53:05 -0000 Received: from sunsite.auc.dk (130.225.51.30) by ns1.primenet.com.au with SMTP; 11 May 2000 08:53:05 -0000 Received: (qmail 13252 invoked by alias); 11 May 2000 08:52:50 -0000 Mailing-List: contact zsh-workers-help@sunsite.auc.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 11320 Received: (qmail 13243 invoked from network); 11 May 2000 08:52:49 -0000 Date: Thu, 11 May 2000 10:52:46 +0200 (MET DST) Message-Id: <200005110852.KAA15526@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: > ... > > 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@informatik.hu-berlin.de