zsh-workers
 help / color / mirror / code / Atom feed
* [BUG] Issue with _arguments !-x !+x
@ 2020-02-12 22:57 dana
  2020-03-01 21:36 ` Oliver Kiddle
  2021-10-22 19:50 ` Oliver Kiddle
  0 siblings, 2 replies; 4+ messages in thread
From: dana @ 2020-02-12 22:57 UTC (permalink / raw)
  To: Zsh hackers list

I noticed something unexpected when i have both !-x and !+x type option specs
and then i try to complete stacked options containing the -x ones:

  # Only !-x
  % _foo() { _arguments -s -S : -{a,b,c} \!-{d,e,f} }
  % compdef _foo foo
  % foo -ad<TAB>
  completing option:
  -b  -c
  % foo -da<TAB>
  completing option:
  -b  -c
  % foo -def<TAB>
  completing option:
  -a  -b  -c

  # Both !-x and !+x
  % _foo() { _arguments -s -S : -{a,b,c} \!-{d,e,f} \!+{d,e,f} }
  % compdef _foo foo
  % foo -ad<TAB>
  completing no arguments:
  % foo -da<TAB>
  completing option:
  -b  -c
  % foo -def<TAB>
  completing no arguments:

All i can figure out so far is that comparguments doesn't think there's
anything to complete. But i'm not sure why. Something to do with how ca_doff
is calculated, i think?

dana


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [BUG] Issue with _arguments !-x !+x
  2020-02-12 22:57 [BUG] Issue with _arguments !-x !+x dana
@ 2020-03-01 21:36 ` Oliver Kiddle
  2020-03-02  6:04   ` dana
  2021-10-22 19:50 ` Oliver Kiddle
  1 sibling, 1 reply; 4+ messages in thread
From: Oliver Kiddle @ 2020-03-01 21:36 UTC (permalink / raw)
  To: dana; +Cc: Zsh hackers list

On 12 Feb, dana wrote:
> I noticed something unexpected when i have both !-x and !+x type option specs
> and then i try to complete stacked options containing the -x ones:

> All i can figure out so far is that comparguments doesn't think there's
> anything to complete. But i'm not sure why. Something to do with how ca_doff
> is calculated, i think?

The problem is the single array in struct cadef. In effect this gets
overloaded for both + and - options. For both -d and +d, we look up the
entry with 'd' in unsigned form as the index. A quick hack to add 128 to
the index for + options appears to fix the issues you list.

But I wonder whether we should go for a somewhat different approach.
Instead of: d->single[STOUC(*line) + (pre == '-' ? 0 : 128)]
Have a macro for: d->single[SINGLEIDX(*line, pre)]
Allowing 256 entries was simple and efficient before multibyte character
sets was an issue. I don't think there is any point supporting
clumping of options that use non-ASCII characters. So the single array
doesn't need to be a hash or list. It could even be smaller if we skip
populating it for control characters in addition to those with the high
bit set.

Any thoughts?

Oliver

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [BUG] Issue with _arguments !-x !+x
  2020-03-01 21:36 ` Oliver Kiddle
@ 2020-03-02  6:04   ` dana
  0 siblings, 0 replies; 4+ messages in thread
From: dana @ 2020-03-02  6:04 UTC (permalink / raw)
  To: Oliver Kiddle; +Cc: Zsh hackers list

On 1 Mar 2020, at 15:36, Oliver Kiddle <okiddle@yahoo.co.uk> wrote:
> Any thoughts?

Thanks for looking, i never got back to it.

Off the top of my head, i like your idea. I agree that there's probably no
need to support non-ASCII characters (nor control characters, if it's
worth-while to skip those)

dana


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [BUG] Issue with _arguments !-x !+x
  2020-02-12 22:57 [BUG] Issue with _arguments !-x !+x dana
  2020-03-01 21:36 ` Oliver Kiddle
@ 2021-10-22 19:50 ` Oliver Kiddle
  1 sibling, 0 replies; 4+ messages in thread
From: Oliver Kiddle @ 2021-10-22 19:50 UTC (permalink / raw)
  To: dana; +Cc: Zsh hackers list

On 12 Feb 2020, dana wrote:
> I noticed something unexpected when i have both !-x and !+x type option specs
> and then i try to complete stacked options containing the -x ones:

Sorry, this has been on my todo list for a while. Implementation is
essentially as I outlined in 45505 but using a function rather than a
macro to get array indices. The example dana used to reproduce it is
also added as a test case.

Oliver

diff --git a/Etc/BUGS b/Etc/BUGS
index f1f8e44f8..5624fb24d 100644
--- a/Etc/BUGS
+++ b/Etc/BUGS
@@ -37,8 +37,6 @@ See test case in Test/C03traps.ztst.
 ------------------------------------------------------------------------
 44850 terminal issues with continuation markers
 ------------------------------------------------------------------------
-45422 _arguments !-x !+x
-------------------------------------------------------------------------
 users/24765 -direct terminals. Not a bug as such but we may need to do
   something if -direct values in TERM are ever common
 ------------------------------------------------------------------------
diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c
index e08788e89..b21033eb4 100644
--- a/Src/Zle/computil.c
+++ b/Src/Zle/computil.c
@@ -1035,7 +1035,7 @@ freecadef(Cadef d)
 	freecaargs(d->rest);
 	zsfree(d->nonarg);
 	if (d->single)
-	    zfree(d->single, 256 * sizeof(Caopt));
+	    zfree(d->single, 188 * sizeof(Caopt));
 	zfree(d, sizeof(*d));
 	d = s;
     }
@@ -1079,6 +1079,21 @@ bslashcolon(char *s)
     return r;
 }
 
+/* Get an index into the single array used in struct cadef
+ * opt is the option letter and pre is either - or +
+ * we only keep an array for the 94 ASCII characters from ! to ~ so
+ * with - and + prefixes, the array is double that at 188 elements
+ * returns -1 if opt is out-of-range
+ */
+static int
+single_index(char pre, char opt)
+{
+    if (opt <= 20 || opt > 0x7e)
+	return -1;
+
+    return opt + (pre == '-' ? -21 : 94 - 21);
+}
+
 /* Parse an argument definition. */
 
 static Caarg
@@ -1151,8 +1166,8 @@ alloc_cadef(char **args, int single, char *match, char *nonarg, int flags)
     ret->lastt = time(0);
     ret->set = NULL;
     if (single) {
-	ret->single = (Caopt *) zalloc(256 * sizeof(Caopt));
-	memset(ret->single, 0, 256 * sizeof(Caopt));
+	ret->single = (Caopt *) zalloc(188 * sizeof(Caopt));
+	memset(ret->single, 0, 188 * sizeof(Caopt));
     } else
 	ret->single = NULL;
     ret->match = ztrdup(match);
@@ -1558,9 +1573,10 @@ parse_cadef(char *nam, char **args)
 	     * pointer for the definition in the array for fast lookup.
 	     * But don't treat '--' as a single option called '-' */
 
-
-	    if (single && name[1] && !name[2] && name[1] != '-')
-		ret->single[STOUC(name[1])] = opt;
+	    if (single && name[1] && !name[2] && name[1] != '-') {
+		int sidx = single_index(*name, name[1]);
+		if (sidx >= 0) ret->single[sidx] = opt;
+	    }
 
 	    if (again == 1) {
 		/* Do it all again for `*-...'. */
@@ -1738,11 +1754,12 @@ ca_get_sopt(Cadef d, char *line, char **end, LinkList *lp)
     Caopt p, pp = NULL;
     char pre = *line++;
     LinkList l = NULL;
+    int sidx;
 
     *lp = NULL;
     for (p = NULL; *line; line++) {
-	if ((p = d->single[STOUC(*line)]) && p->active &&
-	    p->args && p->name[0] == pre) {
+	if ((sidx = single_index(pre, *line)) != -1 &&
+	    (p = d->single[sidx]) && p->active && p->args) {
 	    if (p->type == CAO_NEXT) {
 		if (!l)
 		    *lp = l = newlinklist();
@@ -2190,6 +2207,7 @@ ca_parse_line(Cadef d, Cadef all, int multi, int first)
 
 	    char *p;
 	    Caopt tmpopt;
+	    int sidx;
 
 	    if (cur != compcurrent && sopts && nonempty(sopts))
 		state.curopt = (Caopt) uremnode(sopts, firstnode(sopts));
@@ -2207,7 +2225,8 @@ ca_parse_line(Cadef d, Cadef all, int multi, int first)
 	    state.singles = (!pe || !*pe);
 
 	    for (p = line + 1; p < pe; p++) {
-		if ((tmpopt = d->single[STOUC(*p)])) {
+		if ((sidx = single_index(*line, *p)) != -1 &&
+		    (tmpopt = d->single[sidx])) {
 		    if (!state.oargs[tmpopt->num])
 			state.oargs[tmpopt->num] = znewlinklist();
 
diff --git a/Test/Y03arguments.ztst b/Test/Y03arguments.ztst
index bf41aead5..0690b3629 100644
--- a/Test/Y03arguments.ztst
+++ b/Test/Y03arguments.ztst
@@ -102,6 +102,28 @@
 >NO:{+o}
 >NO:{-o}
 
+ tst_arguments -s -{a,b,c} \!-{d,e,f} \!+{d,e,f}
+ comptest $'tst -ad\t\024\t\bef\t'
+0:mix of + and - and exclusion of stacked options
+>line: {tst -ad}{}
+>DESCRIPTION:{option}
+>NO:{-b}
+>NO:{-c}
+>line: {tst -da}{}
+>DESCRIPTION:{option}
+>NO:{-b}
+>NO:{-c}
+>line: {tst -def}{}
+>DESCRIPTION:{option}
+>NO:{-a}
+>NO:{-b}
+>NO:{-c}
+
+ tst_arguments -s -{a,b,c} +{a,b,c}
+ comptest $'tst -a +b +c\t'
+0:mix of + and - and exclusion of stacked options
+>line: {tst -a +b +ca}{}
+
  tst_arguments '-o:1:(a):2:(b)'
  comptest $'tst \t\t\t'
 0:two option arguments


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2021-10-22 19:52 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-12 22:57 [BUG] Issue with _arguments !-x !+x dana
2020-03-01 21:36 ` Oliver Kiddle
2020-03-02  6:04   ` dana
2021-10-22 19:50 ` Oliver Kiddle

Code repositories for project(s) associated with this 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).