* Advanced option parsing across zsh commands
@ 2016-01-26 9:20 Sebastian Gniazdowski
2016-01-26 18:28 ` Bart Schaefer
0 siblings, 1 reply; 6+ messages in thread
From: Sebastian Gniazdowski @ 2016-01-26 9:20 UTC (permalink / raw)
To: Zsh hackers list
Hello,
This will bind to current keymap, not to "a":
% bindkey -N a main
% bindkey -s '^[t' 'echo test' -M a
I like zparseopts because of -E option, which allows to mix options
with strings and handles --. Is it expected that one day zsh will do
the same? It's a matter of providing one well written options parsing
function, isn't it.
That said, following zparseopts apparently fails:
% set -- a -b something -- -c
% typeset -A opts
% zparseopts -A opts -DE b: c
% echo "${(kv)opts}"
% # $1, $2, ... $5 are still the same
I once (12 years ago) used zparseopts this way and it worked great.
The call had to be different then.
Best regards,
Sebastian Gniazdowski
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Advanced option parsing across zsh commands
2016-01-26 9:20 Advanced option parsing across zsh commands Sebastian Gniazdowski
@ 2016-01-26 18:28 ` Bart Schaefer
2016-01-26 18:59 ` Sebastian Gniazdowski
0 siblings, 1 reply; 6+ messages in thread
From: Bart Schaefer @ 2016-01-26 18:28 UTC (permalink / raw)
To: Zsh hackers list
On Jan 26, 10:20am, Sebastian Gniazdowski wrote:
} Subject: Advanced option parsing across zsh commands
}
} I like zparseopts because of -E option, which allows to mix options
} with strings and handles --. Is it expected that one day zsh will do
} the same?
No, this is not expected.
} % set -- a -b something -- -c
} % typeset -A opts
} % zparseopts -A opts -DE b: c
} % echo "${(kv)opts}"
}
} % # $1, $2, ... $5 are still the same
You can't stack the options of zparseopts itself, i.e, you can't use -DE,
you have to use -D -E.
zparseopts also doesn't handle "negated options" in the +X format, only
those introduced with "-". There's a fairly convoluted issue with making
"+" work for the associative array case because of the way zparseopts
gathers up the arguments of each option before assigning to the array.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Advanced option parsing across zsh commands
2016-01-26 18:28 ` Bart Schaefer
@ 2016-01-26 18:59 ` Sebastian Gniazdowski
2016-01-26 19:09 ` Sebastian Gniazdowski
2016-01-27 6:56 ` Bart Schaefer
0 siblings, 2 replies; 6+ messages in thread
From: Sebastian Gniazdowski @ 2016-01-26 18:59 UTC (permalink / raw)
To: Bart Schaefer; +Cc: Zsh hackers list
On 26 January 2016 at 19:28, Bart Schaefer <schaefer@brasslantern.com> wrote:
> } % set -- a -b something -- -c
> } % typeset -A opts
> } % zparseopts -A opts -DE b: c
> } % echo "${(kv)opts}"
> }
> } % # $1, $2, ... $5 are still the same
>
> You can't stack the options of zparseopts itself, i.e, you can't use -DE,
> you have to use -D -E.
Thanks, this works
> zparseopts also doesn't handle "negated options" in the +X format, only
> those introduced with "-". There's a fairly convoluted issue with making
> "+" work for the associative array case because of the way zparseopts
> gathers up the arguments of each option before assigning to the array.
This sounded like if there would a workaround for +X. I tried the
following: define option "+", which takes argument. Then replace "+X"
with "-+X" in the command line. However:
% unset opts
% typeset -A opts
% set -- a -b something -+X -- -c
% zparseopts -A opts -D -E b: c +:
% echo "${(k)opts}"
% echo "${(v)opts}"
b+X
Weird, isn't it? With also a regular array:
% unset opts
% unset optsa
% typeset -A opts
% typeset -a optsa
% set -- a -b something -+X -- -c
% zparseopts -a optsa -A opts -D -E b: c +:
% echo ${(k)opts}
% echo ${(v)opts}
b+X
% echo $optsa
b - +X
With only regular array it's the same
Best regards,
Sebastian Gniazdowski
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Advanced option parsing across zsh commands
2016-01-26 18:59 ` Sebastian Gniazdowski
@ 2016-01-26 19:09 ` Sebastian Gniazdowski
2016-01-27 7:07 ` Bart Schaefer
2016-01-27 6:56 ` Bart Schaefer
1 sibling, 1 reply; 6+ messages in thread
From: Sebastian Gniazdowski @ 2016-01-26 19:09 UTC (permalink / raw)
To: Bart Schaefer; +Cc: Zsh hackers list
Here is how it works if order of option specification is changed:
% unset opts
% unset optsa
% typeset -A opts
% typeset -a optsa
% set -- a -b something -+X -- -c
% zparseopts -a optsa -A opts -D -E +: b: c
% echo "${(k)opts}"
-b -
% echo "${(v)opts}"
something +X
% echo "${opts[-]}"
+X
% echo $optsa
-b something - +X
That's quite a work around, but I wonder what's going on internally?
Tested (the previous runs too) on 5.2
Best regards,
Sebastian Gniazdowski
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Advanced option parsing across zsh commands
2016-01-26 18:59 ` Sebastian Gniazdowski
2016-01-26 19:09 ` Sebastian Gniazdowski
@ 2016-01-27 6:56 ` Bart Schaefer
1 sibling, 0 replies; 6+ messages in thread
From: Bart Schaefer @ 2016-01-27 6:56 UTC (permalink / raw)
To: Zsh hackers list
On Jan 26, 7:59pm, Sebastian Gniazdowski wrote:
} Subject: Re: Advanced option parsing across zsh commands
}
} > zparseopts also doesn't handle "negated options" in the +X format
}
} This sounded like if there would a workaround for +X. I tried the
} following: define option "+", which takes argument. Then replace "+X"
} with "-+X" in the command line. However:
}
} % zparseopts -A opts -D -E b: c +:
That does not define an option "+" which takes an argument. That in
fact defines an option (empty string) which may be repeated multiple
times and takes an argument, because the "+" invokes the NAME+ form
of option description.
There's not a lot of internal consistency checking in zparseopts. Old
code that has not been reviewed since it was written.
To define an option named "+" instead of an option named "", you are
intended to use:
zparseopts -A opts -D -E b: c '\+:'
However, because of a bug, you can't actually do that. The backslash
causes everything after it to shift one character to the left, but
the NUL-terminator is not also shifted, so the above accidentally
defines the option "++" instead of the option "+".
torch% typeset -A opts
torch% set -- a -b something -++X -- -c
torch% zparseopts -A opts -D -E b: c \\+:
torch% print -lr -- $@
a
--
-c
torch% print -r -- ${(kv)opts}
-b something -++ X
torch%
With the patch below, the very first character of the option spec is
always taken to be part of the option name (unless that first char is
is a backslash, in which case it is shifted off as usual). So you
no longer need to escape a "+" (though it doesn't hurt to do so):
torch% typeset -A opts
torch% set -- a -b something -+X -- -c
torch% zparseopts -A opts -D -E b: c +:
torch% print -r -- ${(kv)opts}
-b something -+ X
And using "++" does the expected thing:
torch% typeset -A opts=()
torch% set -- a -b something -+X -+Y -+Z -- -c
torch% zparseopts -A opts -D -E b: c ++:
torch% print -r -- ${(kv)opts}
-b something -+ XYZ
torch%
For pre-5.3 zsh I suggest you use a different character than "+" for
your proposed workaround, e.g.
set -- a -b something -\*X -\*Y -\*Z -- -c
zparseopts -A opts -D -E b: c '*+:'
should work.
diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c
index d98028a..12a4c03 100644
--- a/Src/Modules/zutil.c
+++ b/Src/Modules/zutil.c
@@ -1745,13 +1745,15 @@ bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
for (p = o; *p; p++) {
if (*p == '\\' && p[1])
p++;
- else if (*p == '+') {
- f |= ZOF_MULT;
- *p = '\0';
- p++;
- break;
- } else if (*p == ':' || *p == '=')
- break;
+ else if (p > o) { /* At least one character of option name */
+ if (*p == '+') {
+ f |= ZOF_MULT;
+ *p = '\0';
+ p++;
+ break;
+ } else if (*p == ':' || *p == '=')
+ break;
+ }
}
if (*p == ':') {
f |= ZOF_ARG;
@@ -1789,6 +1791,7 @@ bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
p++;
*n++ = *p;
}
+ *n = '\0';
if (get_opt_desc(o)) {
zwarnnam(nam, "option defined more than once: %s", o);
return 1;
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Advanced option parsing across zsh commands
2016-01-26 19:09 ` Sebastian Gniazdowski
@ 2016-01-27 7:07 ` Bart Schaefer
0 siblings, 0 replies; 6+ messages in thread
From: Bart Schaefer @ 2016-01-27 7:07 UTC (permalink / raw)
To: Zsh hackers list
On Jan 26, 8:09pm, Sebastian Gniazdowski wrote:
}
} Here is how it works if order of option specification is changed:
}
} % zparseopts -a optsa -A opts -D -E +: b: c
All you've done there is manage to get the empty-string option to
be tested after any of the others (the specs are tested against
$argv in reverse of the order they appear as zparseopts arguments).
It's almost certainly coincidental that this created options that
seem to be named "-" and assigned "+X" as the value; this effect
no longer occurs with my patch from 37810, and is probably not
reliable with any zsh prior to that patch.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2016-01-27 7:06 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-26 9:20 Advanced option parsing across zsh commands Sebastian Gniazdowski
2016-01-26 18:28 ` Bart Schaefer
2016-01-26 18:59 ` Sebastian Gniazdowski
2016-01-26 19:09 ` Sebastian Gniazdowski
2016-01-27 7:07 ` Bart Schaefer
2016-01-27 6:56 ` Bart Schaefer
Code repositories for project(s) associated with this public 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).