zsh-workers
 help / color / mirror / code / Atom feed
* [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

* Re: [RFC] Teach getopts to handle -o and +o separately
  2018-10-11  1:33 [RFC] Teach getopts to handle -o and +o separately dana
@ 2018-10-11 20:26 ` Daniel Shahaf
  0 siblings, 0 replies; 2+ messages in thread
From: Daniel Shahaf @ 2018-10-11 20:26 UTC (permalink / raw)
  To: zsh-workers

dana wrote on Wed, 10 Oct 2018 20:33 -0500:
> 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:

FWIW, ezmlm-make(1) has a -+ flag.  Not saying it's a deal breaker; just a datapoint.

^ 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).