Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
[PATCH] zparseopts -M: use last as-given option name in arrays
- X-seq: zsh-workers 54381
- From: dana <dana@xxxxxxx>
- To: zsh-workers@xxxxxxx
- Cc: "Bart Schaefer" <schaefer@xxxxxxxxxxxxxxxx>
- Subject: [PATCH] zparseopts -M: use last as-given option name in arrays
- Date: Tue, 21 Apr 2026 01:21:24 -0500
- Archived-at: <https://zsh.org/workers/54381>
- Feedback-id: i9be146f9:Fastmail
- List-id: <zsh-workers.zsh.org>
something i noticed with `zparseopts -M`:
% fn() { local -a v; zparseopts -av -M - a:=-aaa -aaa:; typeset -p v }
% fn -a foo
typeset -a v=( -a foo )
% fn --aaa foo -a bar
typeset -a v=( --aaa bar )
with -a+ it uses the as-given option name in the array each time, but
with -a (as above) it uses whatever name was used first
this feels weird to me. i think it should either (a) always use the
mapped-to name like it does for the association keys or (b) use the
last/effective as-given name like it does in arrays with +
both options sound good to me and they're both very simple changes, so
i'm torn. but based on users/16032 i think the latter is closer to what
bart intended? so i've done that here. tell me if we'd like it better
another way though
dana
diff --git a/Doc/Zsh/mod_zutil.yo b/Doc/Zsh/mod_zutil.yo
index a18985a4b..6e5403d70 100644
--- a/Doc/Zsh/mod_zutil.yo
+++ b/Doc/Zsh/mod_zutil.yo
@@ -396,7 +396,10 @@ item(tt(-M))(
This changes the assignment rules to implement a map among equivalent
option names. If any var(spec) uses the `tt(=)var(array)' form, the
string var(array) is interpreted as the name of another var(spec),
-which is used to choose where to store the values. If no other var(spec)
+which is used to choose where to store the values.
+Values stored in an associative array (tt(-A)) use the name of the
+mapped-to option, whereas values stored in an array use the last
+as-given option name. If no other var(spec)
is found, the values are stored as usual. This changes only the way the
values are stored, not the way tt($*) is parsed, so results may be
unpredictable if the `var(name)tt(+)' specifier is used inconsistently.
diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c
index f13ac95ac..72cc5ee54 100644
--- a/Src/Modules/zutil.c
+++ b/Src/Modules/zutil.c
@@ -1654,9 +1654,9 @@ add_opt_val(Zoptdesc d, char *arg)
if (!v) {
v = (Zoptval) zhalloc(sizeof(*v));
v->next = v->onext = NULL;
- v->name = n;
new = 1;
}
+ v->name = n; // insert the last given name into arrays
v->arg = arg;
if ((d->flags & ZOF_ARG) && !(d->flags & (ZOF_OPT | ZOF_SAME))) {
v->str = NULL;
diff --git a/Test/V12zparseopts.ztst b/Test/V12zparseopts.ztst
index 6a880b49c..17b0a01d2 100644
--- a/Test/V12zparseopts.ztst
+++ b/Test/V12zparseopts.ztst
@@ -127,13 +127,20 @@
>ret: 0, opts: -a '' -b 1 -z '', argv: 1 2 3
>ret: 0, opts: -b 1 -z '', argv: 1 2 3
- () {
+ fn() {
local -a optv
local -A opts
zparseopts -D -M -a optv -A opts - a:=-aaa -aaa:
print -r - ret: $?, optv: $optv, opts: "$( order_assoc opts )", argv: $argv
- } --aaa foo -a bar 1 2 3
+ }
+ fn -a foo 1 2 3
+ fn --aaa foo 1 2 3
+ fn --aaa foo -a bar 1 2 3
+ fn -a foo --aaa bar 1 2 3
0:zparseopts -M
+>ret: 0, optv: -a foo, opts: --aaa foo, argv: 1 2 3
+>ret: 0, optv: --aaa foo, opts: --aaa foo, argv: 1 2 3
+>ret: 0, optv: -a bar, opts: --aaa bar, argv: 1 2 3
>ret: 0, optv: --aaa bar, opts: --aaa bar, argv: 1 2 3
() {
Messages sorted by:
Reverse Date,
Date,
Thread,
Author