Repository: google/argh (language: rust)

Issue:
Support option delimiter in argh
Two dashes ('--') will indicate the end of argument options. All subsequent values are given to the tool as-is. For example, with "Usage: foo [-a] <file>", the command line "foo -- -a" may interpret -a as a file name rather than a switch. Further, "foo -a -- -a" enables the switch -a (the first -a, before the --) and passes the literal text -a (the second -a).

This option is supported in various tools. Would be useful to support here too.


Discussion / hints:

Fix patch:
diff --git a/argh_derive/src/lib.rs b/argh_derive/src/lib.rs
index 8d15871..27287a3 100644
--- a/argh_derive/src/lib.rs
+++ b/argh_derive/src/lib.rs
@@ -326,6 +326,7 @@ fn impl_from_args_struct(
                 let mut __help = false;
                 let mut __remaining_args = __args;
                 let mut __positional_index = 0;
+                let mut __options_ended = false;
                 'parse_args: while let Some(&__next_arg) = __remaining_args.get(0) {
                     __remaining_args = &__remaining_args[1..];
                     if __next_arg == "--help" || __next_arg == "help" {
@@ -333,7 +334,12 @@ fn impl_from_args_struct(
                         continue;
                     }
 
-                    if __next_arg.starts_with("-") {
+                    if __next_arg.starts_with("-") && !__options_ended {
+                        if __next_arg == "--" {
+                            __options_ended = true;
+                            continue;
+                        }
+
                         if __help {
                             return Err(
                                 "Trailing arguments are not allowed after `help`."


Test patch:
diff --git a/tests/lib.rs b/tests/lib.rs
index a19ed5a..428015c 100644
--- a/tests/lib.rs
+++ b/tests/lib.rs
@@ -317,13 +317,7 @@ Options:
 
     #[test]
     fn mixed_with_option() {
-        assert_output(
-            &["first", "--b", "foo"],
-            WithOption {
-                a: "first".into(),
-                b: "foo".into(),
-            },
-        );
+        assert_output(&["first", "--b", "foo"], WithOption { a: "first".into(), b: "foo".into() });
 
         assert_error::<WithOption>(
             &[],
@@ -513,7 +507,28 @@ mod fuchsia_commandline_tools_rubric {
     /// even when their syntax matches that of options. e.g. `foo -- -e` should be parsed
     /// as passing a single positional argument with the value `-e`.
     #[test]
-    fn double_dash_positional() {}
+    fn double_dash_positional() {
+        #[derive(FromArgs, Debug, PartialEq)]
+        /// Positional arguments list
+        struct StringList {
+            #[argh(positional)]
+            /// a list of strings
+            strs: Vec<String>,
+
+            #[argh(switch)]
+            /// some flag
+            flag: bool,
+        }
+
+        assert_output(
+            &["--", "a", "-b", "--flag"],
+            StringList { strs: vec!["a".into(), "-b".into(), "--flag".into()], flag: false },
+        );
+        assert_output(
+            &["--flag", "--", "-a", "b"],
+            StringList { strs: vec!["-a".into(), "b".into()], flag: true },
+        );
+    }
 
     /// Double-dash can be parsed into an optional field using a provided
     /// `fn(&[&str]) -> Result<T, EarlyExit>`.