Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
[PATCH] comparguments: always parse optargs as optargs
- X-seq: zsh-workers 54889
- From: dana <dana@xxxxxxx>
- To: zsh-workers@xxxxxxx
- Subject: [PATCH] comparguments: always parse optargs as optargs
- Date: Tue, 30 Jun 2026 18:47:31 -0500
- Archived-at: <https://zsh.org/workers/54889>
- Feedback-id: i9be146f9:Fastmail
- List-id: <zsh-workers.zsh.org>
comparguments can incorrectly parse a separate optarg as an option or
terminator:
compdef _foo foo
_foo() { _arguments -S : -a: -b -c }
foo -a -b <TAB> # offers only -c
foo -a -- <TAB> # offers nothing
i think this fixes it
dana
diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c
index 3e7755156..e666d93ba 100644
--- a/Src/Zle/computil.c
+++ b/Src/Zle/computil.c
@@ -2125,6 +2125,7 @@ ca_parse_line(Cadef d, Cadef all, int multi, int first)
argxor = NULL;
}
if (cur != compcurrent && state.actopts &&
+ !(state.def && state.inopt) &&
(((d->flags & CDF_SEP) && !strcmp(line, "--")) ||
((d->flags & CDF_ZSEP) && !strcmp(line, "-")))) {
ca_inactive(d, NULL, cur, 1);
@@ -2154,6 +2155,7 @@ ca_parse_line(Cadef d, Cadef all, int multi, int first)
} else if ((state.def = state.def->next)) {
state.argbeg = cur;
state.argend = argend;
+ goto cont;
} else if (sopts && nonempty(sopts)) {
state.curopt = (Caopt) uremnode(sopts, firstnode(sopts));
state.def = state.curopt->args;
@@ -2168,6 +2170,7 @@ ca_parse_line(Cadef d, Cadef all, int multi, int first)
} else {
state.curopt = NULL;
state.opt = 1;
+ goto cont;
}
} else {
state.opt = state.arg = 1;
diff --git a/Test/Y03arguments.ztst b/Test/Y03arguments.ztst
index 14a786709..6ff9bf0a5 100644
--- a/Test/Y03arguments.ztst
+++ b/Test/Y03arguments.ztst
@@ -654,18 +654,77 @@ F:shouldn't offer -b as it is already on the command-line
>line: {tst -ab -}{}
>DESCRIPTION:{option}
>NO:{-b}
+>NO:{-c}
+
+ tst_arguments : -a:arg -b -c --d
+ comptest $'tst -a -b -\t'
+ comptest $'tst -a --d -\t'
+0:single optarg that looks like an option
+>line: {tst -a -b -}{}
+>DESCRIPTION:{option}
+>NO:{--d}
+>NO:{-b}
+>NO:{-c}
+>line: {tst -a --d -}{}
+>DESCRIPTION:{option}
+>NO:{--d}
+>NO:{-b}
+>NO:{-c}
+
+ tst_arguments : -a:arg1::arg2::arg3 -b -c -d: --e --f --g:
+ comptest $'tst -a -b -c -d -\t'
+ comptest $'tst -a --e --f --g -\t'
+0:multiple optargs that look like options
+>line: {tst -a -b -c -d -}{}
+>DESCRIPTION:{option}
+>NO:{--e}
+>NO:{--f}
+>NO:{--g}
+>NO:{-b}
+>NO:{-c}
+>NO:{-d}
+>line: {tst -a --e --f --g -}{}
+>DESCRIPTION:{option}
+>NO:{--e}
+>NO:{--f}
+>NO:{--g}
+>NO:{-b}
+>NO:{-c}
+>NO:{-d}
+
+ tst_arguments : - set1 -a: -b -c - set2 -d: -e -f
+ comptest $'tst -a -b -\t'
+ comptest $'tst -d -e -\t'
+0:optarg that look like an option in a set
+>line: {tst -a -b -}{}
+>DESCRIPTION:{option}
+>NO:{-b}
+>NO:{-c}
+>line: {tst -d -e -}{}
+>DESCRIPTION:{option}
+>NO:{-e}
+>NO:{-f}
+
+ tst_arguments -S -S : -a: -b -c
+ comptest $'tst -a - -\t'
+ comptest $'tst -a -- -\t'
+0:optarg that looks like a terminator
+>line: {tst -a - -}{}
+>DESCRIPTION:{option}
+>NO:{-b}
+>NO:{-c}
+>line: {tst -a -- -}{}
+>DESCRIPTION:{option}
+>NO:{-b}
>NO:{-c}
tst_arguments '-a:arg' -b '(-b)-c'
comptest $'tst -a -c -\t'
0:exclusion with option argument that looks like an option
>line: {tst -a -c -}{}
->MESSAGE:{no arguments}
-F:The current behaviour is wrong; the correct expected output is:
-F:>line: {tst -a -c -}{}
-F:>DESCRIPTION:{option}
-F:>NO:{-b}
-F:>NO:{-c}
+>DESCRIPTION:{option}
+>NO:{-b}
+>NO:{-c}
tst_arguments + grp1 -a -b - onlyset '(-a grp3--y grp2 grp4--)-m' -n + grp2 -u -v + grp3 -x -y + grp4 -0 ':rest'
comptest $'tst -m -\t'
Messages sorted by:
Reverse Date,
Date,
Thread,
Author