aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-07-16 23:11:48 +0800
committer魏曹先生 <1992414357@qq.com>2026-07-16 23:11:48 +0800
commitafd3230de38b28e89ac9ec48a951993fce379688 (patch)
tree152588ad00759a617847dd7cd71b147e10323fb6
parent7bf5ba795361f6abe9d591a2912816ed41a9760b (diff)
fix(arg_matcher): prevent `--` from being consumed as flag value
-rw-r--r--mingling_picker/src/parselib/arg_matcher.rs5
-rw-r--r--mingling_picker/test/src/test/arg_matcher_test.rs39
2 files changed, 43 insertions, 1 deletions
diff --git a/mingling_picker/src/parselib/arg_matcher.rs b/mingling_picker/src/parselib/arg_matcher.rs
index d4b8793..38bb9cc 100644
--- a/mingling_picker/src/parselib/arg_matcher.rs
+++ b/mingling_picker/src/parselib/arg_matcher.rs
@@ -120,7 +120,10 @@ impl Matcher for ArgMatcher {
result.push(args[i].raw_idx);
if !Self::is_inline_value(args[i].raw, flag_str, sep) {
- if i + 1 < args.len() {
+ if i + 1 < args.len()
+ // Don't consume `--` (end-of-options marker) as a value.
+ && end.is_none_or(|e| args[i + 1].raw_idx < e)
+ {
result.push(args[i + 1].raw_idx);
i += 2;
continue;
diff --git a/mingling_picker/test/src/test/arg_matcher_test.rs b/mingling_picker/test/src/test/arg_matcher_test.rs
index 947e20f..7b37bc8 100644
--- a/mingling_picker/test/src/test/arg_matcher_test.rs
+++ b/mingling_picker/test/src/test/arg_matcher_test.rs
@@ -248,3 +248,42 @@ fn test_match_all_end_of_options_not_matched() {
let result = ArgMatcher::on_match_all(&args, &UNIX_STYLE, &info);
assert!(result.is_empty());
}
+
+// `--` should never be consumed as a value by a named flag.
+
+#[test]
+fn test_match_all_named_does_not_consume_end_marker() {
+ // `--flag` before `--`, but the next position IS `--`.
+ // Only tag the flag, don't consume the end-of-options marker.
+ let mut info = PickerArgInfo::new();
+ info.set_long("flag");
+ let args = make_args(&[("--flag", 0), ("--", 1), ("value", 2)]);
+ let result = ArgMatcher::on_match_all(&args, &UNIX_STYLE, &info);
+ assert_eq!(result, vec![0], "should NOT consume -- as a value");
+}
+
+#[test]
+fn test_match_all_named_does_not_consume_end_marker_flag_before_end() {
+ // Simulates: --flag -- you where -- is end-of-options.
+ // The flag should be tagged but -- should NOT be consumed as its value.
+ let mut info = PickerArgInfo::new();
+ info.set_long("flag");
+
+ let args = make_args(&[("--flag", 0), ("--", 1), ("you", 2)]);
+ let result = ArgMatcher::on_match_all(&args, &UNIX_STYLE, &info);
+ assert_eq!(
+ result,
+ vec![0],
+ "flag before --: only tag flag, leave -- for positional"
+ );
+}
+
+#[test]
+fn test_match_all_flag_after_end_has_value() {
+ // Flag after `--` should not match at all.
+ let mut info = PickerArgInfo::new();
+ info.set_long("flag");
+ let args = make_args(&[("--", 0), ("--flag", 1), ("value", 2)]);
+ let result = ArgMatcher::on_match_all(&args, &UNIX_STYLE, &info);
+ assert!(result.is_empty());
+}