about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Kiddle <opk@zsh.org>2017-01-04 14:50:56 +0100
committerOliver Kiddle <opk@zsh.org>2017-01-04 14:50:56 +0100
commit8be732cbcc248abfa82ee1b4d0031f684e79aa8b (patch)
tree3b48189e1d637fbce77bc2471e6d31b804620228
parenta69b19d215798c7cfd89a307abd959fb970dd679 (diff)
downloadzsh-8be732cbcc248abfa82ee1b4d0031f684e79aa8b.tar.gz
zsh-8be732cbcc248abfa82ee1b4d0031f684e79aa8b.tar.xz
zsh-8be732cbcc248abfa82ee1b4d0031f684e79aa8b.zip
40227: handle _arguments sets and rest arguments starting with a dash
This is a new approach to the problem first covered by 39611: checking
to see if an option-like argument belongs to one of the other sets.
-rw-r--r--ChangeLog3
-rw-r--r--Src/Zle/computil.c37
-rw-r--r--Test/Y03arguments.ztst16
3 files changed, 36 insertions, 20 deletions
diff --git a/ChangeLog b/ChangeLog
index 2f6023fdc..dee6ad7dd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
 2017-01-04  Oliver Kiddle  <opk@zsh.org>
 
+	* 40227: Src/Zle/computil.c, Test/Y03arguments.ztst: new approach
+	to 39611 (_arguments sets and rest arguments starting with a dash)
+
 	* 40226: Src/Zle/computil.c, Test/Y03arguments.ztst:
 	tidy up some of the _arguments set code
 
diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c
index cc879c445..82144656d 100644
--- a/Src/Zle/computil.c
+++ b/Src/Zle/computil.c
@@ -1741,6 +1741,27 @@ ca_get_sopt(Cadef d, char *line, char **end, LinkList *lp)
     return pp;
 }
 
+/* Search for an option in all sets except the current one.
+ * Return true if found */
+
+static int
+ca_foreign_opt(Cadef curset, Cadef all, char *option)
+{
+    Cadef d;
+    Caopt p;
+
+    for (d = all; d; d = d->snext) {
+	if (d == curset)
+	    continue;
+
+	for (p = d->opts; p; p = p->next) {
+	    if (!strcmp(p->name, option))
+		return 1;
+	}
+    }
+    return 0;
+}
+
 /* Return the n'th argument definition. */
 
 static Caarg
@@ -1917,7 +1938,7 @@ ca_opt_arg(Caopt opt, char *line)
  * existing options on the line. */
 
 static int
-ca_parse_line(Cadef d, int multi, int first)
+ca_parse_line(Cadef d, Cadef all, int multi, int first)
 {
     Caarg adef, ddef;
     Caopt ptr, wasopt = NULL, dopt;
@@ -2163,13 +2184,7 @@ ca_parse_line(Cadef d, int multi, int first)
 	    else
 		state.curopt = NULL;
 	} else if (multi && (*line == '-' || *line == '+') && cur != compcurrent
-#if 0
-		   /**** Ouch. Using this will disable the mutual exclusion
-			 of different sets. Not using it will make the -A
-			 pattern be effectively ignored with multiple sets. */
-		   && (!napat || !pattry(napat, line))
-#endif
-		   )
+		&& (ca_foreign_opt(d, all, line)))
 	    return 1;
 	else if (state.arg &&
 		 (!napat || cur <= compcurrent || !pattry(napat, line))) {
@@ -2515,20 +2530,20 @@ bin_comparguments(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
          * auto-description string, the optional -s, -S, -A and -M options
          * given to _arguments and the specs. */
 	if (compcurrent > 1 && compwords[0]) {
-	    Cadef def;
+	    Cadef def, all;
 	    int cap = ca_parsed, multi, first = 1, use, ret = 0;
 	    Castate states = NULL, sp;
 
 	    ca_parsed = 0;
 
-	    if (!(def = get_cadef(nam, args + 1)))
+	    if (!(def = all = get_cadef(nam, args + 1)))
 		return 1;
 
 	    multi = !!def->snext; /* if we have sets */
 	    ca_parsed = cap;
 
 	    while (def) { /* for each set */
-		use = !ca_parse_line(def, multi, first);
+		use = !ca_parse_line(def, all, multi, first);
 		def = def->snext;
 		if (use && def) {
 		    /* entry needed so save it into list */
diff --git a/Test/Y03arguments.ztst b/Test/Y03arguments.ztst
index 0b797ac03..47f4747b8 100644
--- a/Test/Y03arguments.ztst
+++ b/Test/Y03arguments.ztst
@@ -358,26 +358,24 @@
 0:repeatable options
 >line: {tst -v -v }{}
 
-# necessary to exclude the rest arguments for the other set because
-# it is currently any unknown option rather than options from another
-# set that causes a set to be excluded
  tst_arguments -A '-*' - help -h -V - other -a '*: :(-x more)'
  comptest $'tst -a -x m\t'
 0:continue completion after rest argument that looks like an option (with sets)
->line: {tst -a -x m}{}
-#>line: {tst -a -x more }{}
+>line: {tst -a -x more }{}
 
   tst_arguments - '(help)' -h -V - other -a '*:rest:(1 2 3)'
-  comptest $'tst -h \t'
-0:unknown option disables whole set (without -A)
+  comptest $'tst -h \t-a \t'
+0:foreign option disables whole set (without -A)
 >line: {tst -h }{}
 >MESSAGE:{no arguments}
+>line: {tst -h -a }{}
 
   tst_arguments -A "-*" - '(help)' -h -V - other -a '*:rest:(1 2 3)'
-  comptest $'tst -h \t'
-0:unknown option disables whole set (with -A)
+  comptest $'tst -h \t-a \t'
+0:foreign option disables whole set (with -A)
 >line: {tst -h }{}
 >MESSAGE:{no arguments}
+>line: {tst -h -a }{}
 
  tst_arguments '(-C)-a' - set1 -C -v - set2 '(-a)-C' -w
  comptest $'tst -a -\t' $'\C-w\C-w-C -\t'