* [RFC] Teach getopts to handle -o and +o separately
@ 2018-10-11 1:33 dana
2018-10-11 20:26 ` Daniel Shahaf
0 siblings, 1 reply; 2+ messages in thread
From: dana @ 2018-10-11 1:33 UTC (permalink / raw)
To: Zsh hackers list
I really like that zsh's getopts handles both -o and +o option variants, but a
major limitation is that the two variants are linked by the one letter
specification — there's no way to tell zsh that you don't want one or the other,
and more importantly there's no way to specify that one variant should take an
argument and one should not.
I'd like to propose that a - or + following an option letter (or preceding it,
if that seems nicer) restrict that letter specification to the - or + variant
respectively. With this change, the following sort of thing becomes possible:
% which testopts
testopts () {
local OPTARG OPTIND opt
while getopts a-a:+bc opt
do
print -r - $opt${OPTARG:+:$OPTARG}
done
}
% testopts -a +a
a
testopts:2: argument expected after +a option
:
% testopts -bab +bab
b
a
b
+b
+a:b
Of course, this eliminates - and + as valid 'letters' in the optstring. But it
seems unlikely that anyone actually needs +-, -+, or ++ (-- is already
effectively unusable for obvious reasons). Also, POSIX says:
>The use of other option characters that are not alphanumeric produces
>unspecified results.
So we're fine there.
Below is a kind of silly-looking patch that implements the change. If the idea
is sound i can try to make it nicer (along with adding docs and tests obv), but
in any case i think it can be done without too many LOC and without touching the
scarier parts of that function.
Does this seem viable at all?
dana
diff --git a/Src/builtin.c b/Src/builtin.c
index 8dcdcc024..f099e3263 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -5512,7 +5512,8 @@ bin_getopts(UNUSED(char *name), char **argv, UNUSED(Options ops), UNUSED(int fun
optbuf[lenoptbuf - 1] = opch;
/* check for legality */
- if(opch == ':' || !(p = memchr(optstr, opch, lenoptstr))) {
+ if(opch == ':' || opch == '?' || opch == '-' || opch == '+'
+ || !(p = memchr(optstr, opch, lenoptstr))) {
p = "?";
err:
zsfree(zoptarg);
@@ -5528,6 +5529,19 @@ bin_getopts(UNUSED(char *name), char **argv, UNUSED(Options ops), UNUSED(int fun
return 0;
}
+ scan:
+ if (!p) {
+ p = "?";
+ goto err;
+ }
+ if ((lenoptbuf == 1 && (p[1] == '+' || (p[1] == ':' && p[2] == '+')))
+ || (lenoptbuf == 2 && (p[1] == '-' || (p[1] == ':' && p[2] == '-')))
+ ) {
+ p++;
+ p = memchr(p, opch, strlen(p));
+ goto scan;
+ }
+
/* check for required argument */
if(p[1] == ':') {
if(optcind == lenstr) {
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2018-10-11 20:26 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-11 1:33 [RFC] Teach getopts to handle -o and +o separately dana
2018-10-11 20:26 ` Daniel Shahaf
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).