Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

[PATCH] zparseopts -G: accept only '--' as parsing terminator



another change to `zparseopts -G` i was sitting on. this is not a bug,
just something i didn't consider before:

normally zparseopts accepts either '-' or '--' to explicitly terminate
argument parsing. although i normally like that feature, it is a
zsh-specific quirk that i think many are unfamiliar with, and since -G
is aiming for better consistency with getopt_long(3) i feel like it's
probably best if it only takes '--'

dana


diff --git a/Doc/Zsh/mod_zutil.yo b/Doc/Zsh/mod_zutil.yo
index 76907352f..19f9989f4 100644
--- a/Doc/Zsh/mod_zutil.yo
+++ b/Doc/Zsh/mod_zutil.yo
@@ -242,8 +242,8 @@ Note that it is an error to give any var(spec) without an
 
 Unless the tt(-E) option is given, parsing stops at the first string
 that isn't described by one of the var(spec)s.  Even with tt(-E),
-parsing always stops at a positional parameter equal to `tt(-)' or
-`tt(-)tt(-)'. See also tt(-F).
+parsing always stops at a positional parameter equal to `tt(-)tt(-)' or
+(without tt(-G)) `tt(-)'. See also tt(-F).
 
 The var(opt) description must be one of the following.  Any of the special
 characters can appear in the option name provided it is preceded by a
@@ -314,9 +314,9 @@ as the values.
 item(tt(-D))(
 If this option is given, all options found are removed from the positional
 parameters of the calling shell or shell function, up to but not including
-any not described by the var(spec)s.  If the first such parameter is `tt(-)'
-or `tt(-)tt(-)', it is removed as well.  This is similar to using the
-tt(shift) builtin.
+any not described by the var(spec)s.  If the first such parameter is
+`tt(-)tt(-)' or (without tt(-G)) `tt(-)', it is removed as well.  This is
+similar to using the tt(shift) builtin.
 )
 item(tt(-E))(
 This changes the parsing rules to em(not) stop at the first string
@@ -364,6 +364,10 @@ A mandatory option-argument given in a separate parameter from its
 option (as in `tt(-)tt(-foo) tt(bar)'), or any option-argument given to
 a short option in the same parameter, is always treated the same
 regardless of whether this option is in effect.
+
+Lastly, when this option is active, only `tt(-)tt(-)' is treated as an
+explicit option-parsing terminator in the parsed arguments; a single
+`tt(-)' is considered a normal operand.
 )
 item(tt(-K))(
 With this option, the arrays specified with the tt(-a) option and with the
diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c
index ef99303d2..676fe1872 100644
--- a/Src/Modules/zutil.c
+++ b/Src/Modules/zutil.c
@@ -1955,8 +1955,8 @@ bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
     params = getaparam((paramsname = paramsname ? paramsname : "argv"));
     np = cp = pp = ((extract && del) ? arrdup(params) : params);
     for (; (o = *pp); pp++) {
-	/* Not an option */
-	if (*o != '-') {
+	/* Not an option. With GNU style, this includes '-' */
+	if (*o != '-' || (gnu && !o[1])) {
 	    if (extract) {
 		if (del)
 		    *cp++ = o;
@@ -1964,7 +1964,7 @@ bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
 	    } else
 		break;
 	}
-	/* '-' or '--', end parsing */
+	/* '--' or (with non-GNU style, see above) '-', end parsing */
 	if (!o[1] || (o[1] == '-' && !o[2])) {
 	    if (del && extract)
 		*cp++ = o;
diff --git a/Test/V12zparseopts.ztst b/Test/V12zparseopts.ztst
index e465d0e0c..e6139ea5e 100644
--- a/Test/V12zparseopts.ztst
+++ b/Test/V12zparseopts.ztst
@@ -341,3 +341,28 @@
 >ret: 1, gopt: -G, optv: , argv: -foobar 1 2 3
 >ret: 0, gopt: -G, optv: -foo=bar, argv: 1 2 3
 >ret: 0, gopt: -G, optv: -foo=, argv: bar 1 2 3
+
+  for term in - --; do
+    # With -D -E -G
+    () {
+      local -a optv
+      zparseopts -a optv -D -E -F -G - -foo -bar
+      print -r - ret: $?, term: $term, optv: $optv, argv: $argv
+    } --foo x --bar $term --baz
+    for gopt in '' -G; do
+      # With -D + with/without -G
+      () {
+        local -a optv
+        zparseopts -a optv -D -F $gopt - -foo -bar
+        print -r - ret: $?, term: $term, gopt: $gopt, optv: $optv, argv: $argv
+      } --foo $term --bar
+    done
+  done
+0:only -- acts as explicit parsing terminator with -G
+?(anon):zparseopts:2: bad option: --baz
+>ret: 1, term: -, optv: , argv: --foo x --bar - --baz
+>ret: 0, term: -, gopt: , optv: --foo, argv: --bar
+>ret: 0, term: -, gopt: -G, optv: --foo, argv: - --bar
+>ret: 0, term: --, optv: --foo --bar, argv: x -- --baz
+>ret: 0, term: --, gopt: , optv: --foo, argv: --bar
+>ret: 0, term: --, gopt: -G, optv: --foo, argv: --bar




Messages sorted by: Reverse Date, Date, Thread, Author