zsh-workers
 help / color / mirror / code / Atom feed
From: Oliver Kiddle <okiddle@yahoo.co.uk>
To: Zsh workers <zsh-workers@zsh.org>
Subject: PATCH: option exclusion within current word
Date: Thu, 05 Jan 2017 04:15:15 +0100	[thread overview]
Message-ID: <37342.1483586115@hydra.kiddle.eu> (raw)

With _arguments, exclusions don't apply for options within the current
word. This mainly affects clumped options (_arguments -s). So, e.g. with
_arguments -s : '(-b)-a' -b -c completion directly after -a offers both
-b and -c. The reasoning for this is specific handling added in 13999 to
prevent an option being excluded by an option that is a prefix of it:
things like -c excluding -conf or --long excluding --longer.

This patch replaces 13999 with a different, more indirect approach.
Within the current word, only exclusions to short options are
applied. The old code explicitly checks for prefixes.

There may be some case I've not thought of that this approach doesn't
handle (any ideas?) but we're right at the start of the release so I'd
prefer to try this to see and at least kill the known issue.

Oliver

diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c
index 8214465..12aa895 100644
--- a/Src/Zle/computil.c
+++ b/Src/Zle/computil.c
@@ -1790,16 +1790,17 @@ ca_get_arg(Cadef d, int n)
  *     opts: if set, all options excluded leaving only nornal/rest arguments */
 
 static void
-ca_inactive(Cadef d, char **xor, int cur, int opts, char *optname)
+ca_inactive(Cadef d, char **xor, int cur, int opts)
 {
     if ((xor || opts) && cur <= compcurrent) {
 	Caopt opt;
 	char *x;
 	int sl = (d->set ? (int)strlen(d->set) : -1), set = 0;
+        /* current word could be a prefix of a longer one so only do
+	 * exclusions for single-letter options (for option clumping) */
+	int single = (cur == compcurrent);
 
 	for (; (x = (opts ? "-" : *xor)); xor++) {
-            if (optname && optname[0] == x[0] && strcmp(optname, x))
-                continue;
 	    set = 0;
 	    if (sl > 0) {
 		if (strpfx(d->set, x)) {
@@ -1809,7 +1810,7 @@ ca_inactive(Cadef d, char **xor, int cur, int opts, char *optname)
 		    Caopt p;
 
 		    for (p = d->opts; p; p = p->next)
-			if (p->set)
+			if (p->set && !(single && *p->name && p->name[1] && p->name[2]))
 			    p->active = 0;
 			
 		    x = ":";
@@ -1831,7 +1832,7 @@ ca_inactive(Cadef d, char **xor, int cur, int opts, char *optname)
 		Caopt p;
 
 		for (p = d->opts; p; p = p->next)
-		    if (!set || p->set)
+		    if ((!set || p->set) && !(single && *p->name && p->name[1] && p->name[2]))
 			p->active = 0;
 	    } else if (x[0] == '*' && !x[1]) {
 		if (d->rest && (!set || d->rest->set))
@@ -1845,7 +1846,8 @@ ca_inactive(Cadef d, char **xor, int cur, int opts, char *optname)
 
 		if (a && a->num == n && (!set || a->set))
 		    a->active = 0;
-	    } else if ((opt = ca_get_opt(d, x, 1, NULL)) && (!set || opt->set))
+	    } else if ((opt = ca_get_opt(d, x, 1, NULL)) && (!set || opt->set) &&
+		    !(single && *opt->name && opt->name[1] && opt->name[2]))
 		opt->active = 0;
 
 	    if (opts)
@@ -2029,9 +2031,9 @@ ca_parse_line(Cadef d, Cadef all, int multi, int first)
         remnulargs(line);
         untokenize(line);
 
-	ca_inactive(d, argxor, cur, 0, NULL);
+	ca_inactive(d, argxor, cur, 0);
 	if ((d->flags & CDF_SEP) && cur != compcurrent && !strcmp(line, "--")) {
-	    ca_inactive(d, NULL, cur, 1, NULL);
+	    ca_inactive(d, NULL, cur, 1);
 	    continue;
 	}
 
@@ -2107,8 +2109,7 @@ ca_parse_line(Cadef d, Cadef all, int multi, int first)
 	    if (!state.oargs[state.curopt->num])
 		state.oargs[state.curopt->num] = znewlinklist();
 
-	    ca_inactive(d, state.curopt->xor, cur, 0,
-		    (cur == compcurrent ? state.curopt->name : NULL));
+	    ca_inactive(d, state.curopt->xor, cur, 0);
 
 	    /* Collect the argument strings. Maybe. */
 
@@ -2161,8 +2162,7 @@ ca_parse_line(Cadef d, Cadef all, int multi, int first)
 		    if (!state.oargs[tmpopt->num])
 			state.oargs[tmpopt->num] = znewlinklist();
 
-		    ca_inactive(d, tmpopt->xor, cur, 0,
-			    (cur == compcurrent ? tmpopt->name : NULL));
+		    ca_inactive(d, tmpopt->xor, cur, 0);
 		}
 	    }
 	    if (state.def &&
@@ -2190,7 +2190,7 @@ ca_parse_line(Cadef d, Cadef all, int multi, int first)
 		 (!napat || cur <= compcurrent || !pattry(napat, line))) {
 	    /* Otherwise it's a normal argument. */
 	    if (napat && cur <= compcurrent)
-		ca_inactive(d, NULL, cur + 1, 1, NULL);
+		ca_inactive(d, NULL, cur + 1, 1);
 
 	    arglast = 1;
 	    /* if this is the first normal arg after an option, may have been
diff --git a/Test/Y03arguments.ztst b/Test/Y03arguments.ztst
index 47f4747..5957bc3 100644
--- a/Test/Y03arguments.ztst
+++ b/Test/Y03arguments.ztst
@@ -479,12 +479,9 @@
 F:shouldn't offer -b as it is already on the command-line
 
  tst_arguments -s : '(-d)-a' -b -c -d
- comptest $'tst -ab\t -\t\eb\eb \C-b-\t'
+ comptest $'tst -ab\t\C-h -\t\eb\eb \C-b-\t'
 0:exclusion with clumped options, in, after and before
->line: {tst -ab}{}
->DESCRIPTION:{option}
->NO:{-c}
->NO:{-d}
+>line: {tst -abc}{}
 >line: {tst -ab -c }{}
 >line: {tst -}{ -ab -c}
 >DESCRIPTION:{option}
@@ -492,7 +489,23 @@ F:shouldn't offer -b as it is already on the command-line
 >NO:{-b}
 >NO:{-c}
 >NO:{-d}
-F:the first tab press shouldn't offer -d since -a is on the command line
+
+ tst_arguments -s '(-conf)-c' '-conf' '-f' '(-)--long' --longer
+ comptest $'tst -c\t\C-h-long\t'
+0:don't prematurely exclude option that current word is a prefix of
+>line: {tst -c}{}
+>DESCRIPTION:{option}
+>NO:{-conf}
+>NO:{-f}
+>line: {tst --long}{}
+>DESCRIPTION:{option}
+>NO:{--long}
+>NO:{--longer}
+
+ tst_arguments -s '(set)-c' - set '-conf' '-f'
+ comptest $'tst -c\t'
+0:don't prematurely exclude option that current word is a prefix of (with sets)
+>line: {tst -conf }{}
 
  tst_arguments -s : -ad '(-d)-a' -b -ca -d
  comptest $'tst -ad\t-b\t'


                 reply	other threads:[~2017-01-05  3:22 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=37342.1483586115@hydra.kiddle.eu \
    --to=okiddle@yahoo.co.uk \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).