From ea6dda762aa147ebcbc29b269e65b78dd046f4dd Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Thu, 16 Jul 2026 04:08:09 +0800 Subject: feat(mingling_picker): replace bool Matcher with FlagMatcher Rename `bool_matcher` module to `flag_matcher` and introduce a dedicated `FlagMatcher` struct, moving matching logic away from the `bool` type itself --- mingling_picker/src/builtin/pick_bool.rs | 5 +-- mingling_picker/src/parselib.rs | 3 +- mingling_picker/src/parselib/bool_matcher.rs | 45 ----------------------- mingling_picker/src/parselib/flag_matcher.rs | 53 ++++++++++++++++++++++++++++ mingling_picker/test/src/test/style_test.rs | 28 +++++++-------- 5 files changed, 72 insertions(+), 62 deletions(-) delete mode 100644 mingling_picker/src/parselib/bool_matcher.rs create mode 100644 mingling_picker/src/parselib/flag_matcher.rs diff --git a/mingling_picker/src/builtin/pick_bool.rs b/mingling_picker/src/builtin/pick_bool.rs index 65efe47..673f2a3 100644 --- a/mingling_picker/src/builtin/pick_bool.rs +++ b/mingling_picker/src/builtin/pick_bool.rs @@ -1,4 +1,5 @@ -use crate::{parselib::Matcher, pickable_needed::*}; +use crate::parselib::{FlagMatcher, Matcher}; +use crate::pickable_needed::*; impl<'a> Pickable<'a> for bool { fn get_attr(_: &'a PickerFlag<'a, Self>) -> PickerFlagAttr { @@ -6,7 +7,7 @@ impl<'a> Pickable<'a> for bool { } fn tag(ctx: TagPhaseContext) -> Vec { - ::match_all(ctx.into()) + FlagMatcher::match_all(ctx.into()) } fn pick(raw_strs: &[&str]) -> PickerArgResult { diff --git a/mingling_picker/src/parselib.rs b/mingling_picker/src/parselib.rs index 5950c9d..cf550b7 100644 --- a/mingling_picker/src/parselib.rs +++ b/mingling_picker/src/parselib.rs @@ -1,4 +1,5 @@ -mod bool_matcher; +mod flag_matcher; +pub use flag_matcher::*; mod style; pub use style::*; diff --git a/mingling_picker/src/parselib/bool_matcher.rs b/mingling_picker/src/parselib/bool_matcher.rs deleted file mode 100644 index cbcb111..0000000 --- a/mingling_picker/src/parselib/bool_matcher.rs +++ /dev/null @@ -1,45 +0,0 @@ -use crate::{ - matcher_needed::*, - parselib::{build_possible_flags, get_seeked_first, multi_seek_eq, seek_end_of_options}, - vec_string_slice, -}; - -impl Matcher for bool { - fn on_match_one( - args: &[MaskedArg], - style: &ParserStyle, - arg_info: &PickerArgInfo, - ) -> Option { - let possible_flags = build_possible_flags(style, arg_info); - let end_of_options = seek_end_of_options(args, style); - let result = get_seeked_first(multi_seek_eq( - args, - vec_string_slice!(possible_flags), - style.case_sensitive, - )); - - match (end_of_options, result) { - (Some(end), Some(current)) if current > end => None, - _ => result, - } - } - - fn on_match_all( - args: &[MaskedArg], - style: &ParserStyle, - arg_info: &PickerArgInfo, - ) -> Vec { - let possible_flags = build_possible_flags(style, arg_info); - let end_of_options = seek_end_of_options(args, style); - let result = multi_seek_eq( - args, - vec_string_slice!(possible_flags), - style.case_sensitive, - ); - - match end_of_options { - Some(end) => result.into_iter().filter(|&idx| idx <= end).collect(), - None => result, - } - } -} diff --git a/mingling_picker/src/parselib/flag_matcher.rs b/mingling_picker/src/parselib/flag_matcher.rs new file mode 100644 index 0000000..af890b9 --- /dev/null +++ b/mingling_picker/src/parselib/flag_matcher.rs @@ -0,0 +1,53 @@ +use crate::{ + matcher_needed::*, + parselib::{build_possible_flags, get_seeked_first, multi_seek_eq, seek_end_of_options}, + vec_string_slice, +}; + +/// `FlagMatcher` is used to match flags in command-line arguments. +/// +/// Flags typically start with `-` or `--` (e.g., `-h`, `--help`), +/// and do not carry additional values. This matcher is responsible for finding +/// these flags in the argument list, taking into account that flags after `--` +/// (end-of-options marker) should not be matched. +pub struct FlagMatcher; + +impl Matcher for FlagMatcher { + fn on_match_one( + args: &[MaskedArg], + style: &ParserStyle, + arg_info: &PickerArgInfo, + ) -> Option { + let possible_flags = build_possible_flags(style, arg_info); + let end_of_options = seek_end_of_options(args, style); + let result = get_seeked_first(multi_seek_eq( + args, + vec_string_slice!(possible_flags), + style.case_sensitive, + )); + + match (end_of_options, result) { + (Some(end), Some(current)) if current > end => None, + _ => result, + } + } + + fn on_match_all( + args: &[MaskedArg], + style: &ParserStyle, + arg_info: &PickerArgInfo, + ) -> Vec { + let possible_flags = build_possible_flags(style, arg_info); + let end_of_options = seek_end_of_options(args, style); + let result = multi_seek_eq( + args, + vec_string_slice!(possible_flags), + style.case_sensitive, + ); + + match end_of_options { + Some(end) => result.into_iter().filter(|&idx| idx <= end).collect(), + None => result, + } + } +} diff --git a/mingling_picker/test/src/test/style_test.rs b/mingling_picker/test/src/test/style_test.rs index 795c4ab..dbe34b5 100644 --- a/mingling_picker/test/src/test/style_test.rs +++ b/mingling_picker/test/src/test/style_test.rs @@ -1,7 +1,7 @@ use mingling_picker::PickerArgInfo; use mingling_picker::parselib::{ - MaskedArg, Matcher, POWERSHELL_STYLE, ParserStyle, ParserStyleNamingCase, UNIX_STYLE, - WINDOWS_STYLE, build_possible_flags, + FlagMatcher, MaskedArg, Matcher, POWERSHELL_STYLE, ParserStyle, ParserStyleNamingCase, + UNIX_STYLE, WINDOWS_STYLE, build_possible_flags, }; // Style: formatting utilities @@ -56,7 +56,7 @@ fn test_windows_style_match() { info.set_long("verbose"); let args = vec![make_masked("/verbose", 0)]; - let result = ::on_match_one(&args, &WINDOWS_STYLE, &info); + let result = FlagMatcher::on_match_one(&args, &WINDOWS_STYLE, &info); assert_eq!(result, Some(0)); } @@ -67,7 +67,7 @@ fn test_windows_style_match_case_insensitive() { info.set_long("verbose"); let args = vec![make_masked("/VERBOSE", 0)]; - let result = ::on_match_one(&args, &WINDOWS_STYLE, &info); + let result = FlagMatcher::on_match_one(&args, &WINDOWS_STYLE, &info); assert_eq!(result, Some(0)); } @@ -78,7 +78,7 @@ fn test_windows_style_no_match_on_unrelated_flag() { info.set_long("verbose"); let args = vec![make_masked("/output", 0)]; - let result = ::on_match_one(&args, &WINDOWS_STYLE, &info); + let result = FlagMatcher::on_match_one(&args, &WINDOWS_STYLE, &info); assert_eq!(result, None); } @@ -89,7 +89,7 @@ fn test_powershell_style_match() { info.set_long("Verbose"); let args = vec![make_masked("-Verbose", 0)]; - let result = ::on_match_one(&args, &POWERSHELL_STYLE, &info); + let result = FlagMatcher::on_match_one(&args, &POWERSHELL_STYLE, &info); assert_eq!(result, Some(0)); } @@ -99,7 +99,7 @@ fn test_powershell_style_match_case_insensitive() { info.set_long("Verbose"); let args = vec![make_masked("-VERBOSE", 0)]; - let result = ::on_match_one(&args, &POWERSHELL_STYLE, &info); + let result = FlagMatcher::on_match_one(&args, &POWERSHELL_STYLE, &info); assert_eq!(result, Some(0)); } @@ -110,7 +110,7 @@ fn test_unix_style_case_sensitive_no_match() { info.set_long("verbose"); let args = vec![make_masked("--VERBOSE", 0)]; - let result = ::on_match_one(&args, &UNIX_STYLE, &info); + let result = FlagMatcher::on_match_one(&args, &UNIX_STYLE, &info); assert_eq!(result, None); } @@ -126,7 +126,7 @@ fn test_windows_style_match_all() { make_masked("/output", 1), make_masked("/VERBOSE", 2), ]; - let result = ::on_match_all(&args, &WINDOWS_STYLE, &info); + let result = FlagMatcher::on_match_all(&args, &WINDOWS_STYLE, &info); assert_eq!(result, vec![0, 2]); } @@ -142,7 +142,7 @@ fn test_windows_style_match_after_end_of_options() { make_masked("--", 1), make_masked("/verbose", 2), ]; - let result = ::on_match_all(&args, &WINDOWS_STYLE, &info); + let result = FlagMatcher::on_match_all(&args, &WINDOWS_STYLE, &info); // end_of_options is always "--" regardless of style assert_eq!(result, vec![0]); } @@ -162,7 +162,7 @@ fn test_kebab_case_naming_for_multiword_flag() { info.set_long("flag_a"); let args = vec![make_masked("--flag-a", 0)]; - let result = ::on_match_one(&args, &KEBAB_STYLE, &info); + let result = FlagMatcher::on_match_one(&args, &KEBAB_STYLE, &info); assert_eq!( result, Some(0), @@ -177,7 +177,7 @@ fn test_snake_case_should_not_match_as_long_flag() { info.set_long("flag_a"); let args = vec![make_masked("--flag_a", 0)]; - let result = ::on_match_one(&args, &KEBAB_STYLE, &info); + let result = FlagMatcher::on_match_one(&args, &KEBAB_STYLE, &info); assert_eq!( result, None, "--flag_a should NOT match in kebab-style context" @@ -191,7 +191,7 @@ fn test_snake_case_naming_for_unix_style() { info.set_long("flag_a"); let args = vec![make_masked("--flag_a", 0)]; - let result = ::on_match_one(&args, &UNIX_STYLE, &info); + let result = FlagMatcher::on_match_one(&args, &UNIX_STYLE, &info); assert_eq!( result, Some(0), @@ -206,7 +206,7 @@ fn test_powershell_pascal_case_naming() { info.set_long("verbose"); let args = vec![make_masked("-Verbose", 0)]; - let result = ::on_match_one(&args, &POWERSHELL_STYLE, &info); + let result = FlagMatcher::on_match_one(&args, &POWERSHELL_STYLE, &info); assert_eq!( result, Some(0), -- cgit