Repository: pacak/bpaf
Pull request #85 (2022-09-30 11:42:53)

parse_option should retain Missing if it manages to consume something
Fixes https://github.com/pacak/bpaf/issues/80


Patch:
diff --git a/docs/src/adjacent_0/cases.txt b/docs/src/adjacent_0/cases.txt
index 928af0c..9535a38 100644
--- a/docs/src/adjacent_0/cases.txt
+++ b/docs/src/adjacent_0/cases.txt
@@ -9,7 +9,7 @@ Options { multi: [Multi { m: (), val_1: 10, val_2: 20, val_3: 3.1415 }], switch:
 OK
 Options { multi: [Multi { m: (), val_1: 10, val_2: 20, val_3: 3.1415 }, Multi { m: (), val_1: 1, val_2: 2, val_3: 0.0 }], switch: true }
 
-? `-s` can't go in the middle
+? `-s` can't go in the middle as the parser expects the second item
 > -m 10 20 -s 3.1415
 Stderr
--m is not expected in this context
+Expected <V3>, pass --help for usage information
diff --git a/docs/src/adjacent_1/cases.txt b/docs/src/adjacent_1/cases.txt
index c260861..0e93126 100644
--- a/docs/src/adjacent_1/cases.txt
+++ b/docs/src/adjacent_1/cases.txt
@@ -11,4 +11,4 @@ Options { switch: true, multi: [Rect { item: (), width: 10, height: 10, painted:
 ? But with `adjacent` they cannot interleave
 > --rect --rect --width 10 --painted --height 10 --height 10 --width 10
 Stderr
---rect is not expected in this context
+Expected --width PX, pass --help for usage information
diff --git a/src/docs/adjacent_0.md b/src/docs/adjacent_0.md
index daf990d..ef8c710 100644
--- a/src/docs/adjacent_0.md
+++ b/src/docs/adjacent_0.md
@@ -88,10 +88,10 @@ parser accepts multiple groups of `-m` - they must not interleave
 Options { multi: [Multi { m: (), val_1: 10, val_2: 20, val_3: 3.1415 }, Multi { m: (), val_1: 1, val_2: 2, val_3: 0.0 }], switch: true }
 ```
 
-`-s` can't go in the middle
+`-s` can't go in the middle as the parser expects the second item
 ```console
 % app -m 10 20 -s 3.1415
--m is not expected in this context
+Expected <V3>, pass --help for usage information
 ```
 
 </details>
diff --git a/src/docs/adjacent_1.md b/src/docs/adjacent_1.md
index 1c8aba1..f3eb00a 100644
--- a/src/docs/adjacent_1.md
+++ b/src/docs/adjacent_1.md
@@ -60,7 +60,7 @@ Options { switch: true, multi: [Rect { item: (), width: 10, height: 10, painted:
 But with `adjacent` they cannot interleave
 ```console
 % app --rect --rect --width 10 --painted --height 10 --height 10 --width 10
---rect is not expected in this context
+Expected --width PX, pass --help for usage information
 ```
 
 </details>
diff --git a/src/structs.rs b/src/structs.rs
index 16a16f5..b7b5338 100644
--- a/src/structs.rs
+++ b/src/structs.rs
@@ -439,7 +439,13 @@ where
             match err {
                 Error::Stderr(_) if catch => Ok(None),
                 Error::Stderr(_) | Error::Stdout(_) => Err(err),
-                Error::Missing(_) => Ok(None),
+                Error::Missing(_) => {
+                    if args.len() == orig_args.len() {
+                        Ok(None)
+                    } else {
+                        Err(err)
+                    }
+                }
             }
         }
     }


Test patch:
diff --git a/tests/adjacent.rs b/tests/adjacent.rs
index 0a8dc65..1e0faf1 100644
--- a/tests/adjacent.rs
+++ b/tests/adjacent.rs
@@ -1,7 +1,7 @@
+use bpaf::*;
+
 #[test]
 fn test_adjacent() {
-    use bpaf::*;
-
     let a = short('a').req_flag(());
     let b = short('b').switch();
     let c = short('c').switch();
@@ -18,7 +18,6 @@ fn test_adjacent() {
 
 #[test]
 fn test_adjacent_prefix() {
-    use bpaf::*;
     let a = short('a').req_flag(());
     let b = positional::<usize>("X");
     let ab = construct!(a, b).adjacent().optional();
@@ -37,3 +36,67 @@ fn test_adjacent_prefix() {
     let r = parser.run_inner(Args::from(&["-a", "1", "-c"])).unwrap();
     assert_eq!(r, (Some(((), 1)), true));
 }
+
+#[test]
+fn adjacent_error_message_pos_single() {
+    let a = short('a').req_flag(());
+    let b = positional::<usize>("B");
+    let c = positional::<usize>("C");
+    let d = short('d').switch();
+    let adj = construct!(a, b, c).adjacent();
+    let parser = construct!(adj, d).to_options();
+
+    let r = parser
+        .run_inner(Args::from(&["-a", "10"]))
+        .unwrap_err()
+        .unwrap_stderr();
+    assert_eq!(r, "Expected <C>, pass --help for usage information");
+}
+
+#[test]
+fn adjacent_error_message_arg_single() {
+    let a = short('a').req_flag(());
+    let b = short('b').argument::<usize>("B");
+    let c = short('c').argument::<usize>("C");
+    let d = short('d').switch();
+    let adj = construct!(a, b, c).adjacent();
+    let parser = construct!(adj, d).to_options();
+
+    let r = parser
+        .run_inner(Args::from(&["-a", "10"]))
+        .unwrap_err()
+        .unwrap_stderr();
+    assert_eq!(r, "Expected -b B, pass --help for usage information");
+}
+
+#[test]
+fn adjacent_error_message_pos_many() {
+    let a = short('a').req_flag(());
+    let b = positional::<usize>("B");
+    let c = positional::<usize>("C");
+    let d = short('d').switch();
+    let adj = construct!(a, b, c).adjacent().many();
+    let parser = construct!(adj, d).to_options();
+
+    let r = parser
+        .run_inner(Args::from(&["-a", "10"]))
+        .unwrap_err()
+        .unwrap_stderr();
+    assert_eq!(r, "Expected <C>, pass --help for usage information");
+}
+
+#[test]
+fn adjacent_error_message_arg_many() {
+    let a = short('a').req_flag(());
+    let b = short('b').argument::<usize>("B");
+    let c = short('c').argument::<usize>("C");
+    let d = short('d').switch();
+    let adj = construct!(a, b, c).adjacent().many();
+    let parser = construct!(adj, d).to_options();
+
+    let r = parser
+        .run_inner(Args::from(&["-a", "10"]))
+        .unwrap_err()
+        .unwrap_stderr();
+    assert_eq!(r, "Expected -b B, pass --help for usage information");
+}