From afd3230de38b28e89ac9ec48a951993fce379688 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Thu, 16 Jul 2026 23:11:48 +0800 Subject: fix(arg_matcher): prevent `--` from being consumed as flag value --- mingling_picker/src/parselib/arg_matcher.rs | 5 ++- mingling_picker/test/src/test/arg_matcher_test.rs | 39 +++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) 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()); +} -- cgit