Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: [BUG] Issue with _arguments !-x !+x
- X-seq: zsh-workers 49518
- From: Oliver Kiddle <okiddle@xxxxxxxxxxx>
- To: dana <dana@xxxxxxx>
- Cc: Zsh hackers list <zsh-workers@xxxxxxx>
- Subject: Re: [BUG] Issue with _arguments !-x !+x
- Date: Fri, 22 Oct 2021 21:50:52 +0200
- Archived-at: <https://zsh.org/workers/49518>
- In-reply-to: <BED65A01-95AA-473E-BCF8-3E5E19A66C7E@dana.is>
- List-id: <zsh-workers.zsh.org>
- References: <BED65A01-95AA-473E-BCF8-3E5E19A66C7E@dana.is>
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
Messages sorted by:
Reverse Date,
Date,
Thread,
Author