Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
[RFC] Teach getopts to handle -o and +o separately
- X-seq: zsh-workers 43670
- From: dana <dana@xxxxxxx>
- To: Zsh hackers list <zsh-workers@xxxxxxx>
- Subject: [RFC] Teach getopts to handle -o and +o separately
- Date: Wed, 10 Oct 2018 20:33:48 -0500
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dana-is.20150623.gappssmtp.com; s=20150623; h=from:content-transfer-encoding:mime-version:subject:message-id:date :to; bh=C/LDMc3ZkNTLCf97cxc1so4RJupFwVeXlQcJ+2+asVs=; b=bvN26pRrzbJ9UUQXzmTGX/uyX4koU2LEsHFmCxuKmlS0b1Qorlo+WPYjp4ZkjmtDgN hcluL9X/0vTMjPQRsIomLujNJiYSkS6jeX0bicnO85lQc1j2LTUxI2Fwl3xQPEfQ0f/n DIDaTtimhbgTfpCi8uJ1lKitKIYLl4PhMOnH2ym0LMLGRCX/6f0ksQpITRdy8aVvYVpZ qA/hR6qiBpV7ry3bm9tIKyS9BBKcEgaf5/wZRle0TvW3Km6kjWsTVIm+3P4LIHqg7NPt tq0IH9v03/nLTVtL8m+jl5rJXMDD97Y6OGgYm2GBAKlVeISiT3esPxu/5bUZBbpSSV3S LQmA==
- List-help: <mailto:zsh-workers-help@zsh.org>
- List-id: Zsh Workers List <zsh-workers.zsh.org>
- List-post: <mailto:zsh-workers@zsh.org>
- List-unsubscribe: <mailto:zsh-workers-unsubscribe@zsh.org>
- Mailing-list: contact zsh-workers-help@xxxxxxx; run by ezmlm
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) {
Messages sorted by:
Reverse Date,
Date,
Thread,
Author