aboutsummaryrefslogtreecommitdiff
path: root/mingling_picker
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-07-16 19:29:51 +0800
committer魏曹先生 <1992414357@qq.com>2026-07-16 19:29:51 +0800
commit2287f5db3c12049afd274496a49b223365fb1e89 (patch)
treed805dd51594b1ece2369eee5b18b34acb28f56bc /mingling_picker
parent41fe0580212b3a681fd767d331fd8875ee59b019 (diff)
refactor(flag_matcher): replace `vec_string_slice!` with single-pass
iteration
Diffstat (limited to 'mingling_picker')
-rw-r--r--mingling_picker/src/parselib/flag_matcher.rs79
1 files changed, 62 insertions, 17 deletions
diff --git a/mingling_picker/src/parselib/flag_matcher.rs b/mingling_picker/src/parselib/flag_matcher.rs
index af890b9..782d0f8 100644
--- a/mingling_picker/src/parselib/flag_matcher.rs
+++ b/mingling_picker/src/parselib/flag_matcher.rs
@@ -1,7 +1,6 @@
use crate::{
matcher_needed::*,
- parselib::{build_possible_flags, get_seeked_first, multi_seek_eq, seek_end_of_options},
- vec_string_slice,
+ parselib::{build_possible_flags, get_seeked_first, multi_seek_eq},
};
/// `FlagMatcher` is used to match flags in command-line arguments.
@@ -19,12 +18,10 @@ impl Matcher for FlagMatcher {
arg_info: &PickerArgInfo,
) -> Option<usize> {
let possible_flags = build_possible_flags(style, arg_info);
+ let flag_refs: Vec<&str> = possible_flags.iter().map(|s| s.as_str()).collect();
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,
- ));
+
+ let result = get_seeked_first(multi_seek_eq(args, &flag_refs, style.case_sensitive));
match (end_of_options, result) {
(Some(end), Some(current)) if current > end => None,
@@ -38,16 +35,64 @@ impl Matcher for FlagMatcher {
arg_info: &PickerArgInfo,
) -> Vec<usize> {
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,
+ single_pass_match_all(args, style, &possible_flags)
+ }
+}
+
+/// Single-pass match: finds the `--` marker and matching flags in one iteration.
+fn single_pass_match_all(
+ args: &[MaskedArg],
+ style: &ParserStyle,
+ possible_flags: &[String],
+) -> Vec<usize> {
+ let flag_refs: Vec<&str> = possible_flags.iter().map(|s| s.as_str()).collect();
+ let eoo = style.end_of_options;
+ let case_sensitive = style.case_sensitive;
+
+ let mut end_pos: Option<usize> = None;
+ let mut matches: Vec<usize> = Vec::new();
+
+ for arg in args {
+ if end_pos.is_none() {
+ let is_eoo = if case_sensitive {
+ arg.raw == eoo
+ } else {
+ arg.raw.eq_ignore_ascii_case(eoo)
+ };
+ if is_eoo {
+ end_pos = Some(arg.raw_idx);
+ continue;
+ }
+ }
+
+ // Only match flags before the end-of-options marker.
+ if end_pos.is_none() {
+ let matched = if case_sensitive {
+ flag_refs.contains(&arg.raw)
+ } else {
+ flag_refs.iter().any(|s| arg.raw.eq_ignore_ascii_case(s))
+ };
+ if matched {
+ matches.push(arg.raw_idx);
+ }
}
}
+
+ matches
+}
+
+/// Locate the end-of-options marker (`--`) in the argument list.
+fn seek_end_of_options(args: &[MaskedArg], style: &ParserStyle) -> Option<usize> {
+ get_seeked_first(
+ args.iter()
+ .filter(|arg| {
+ if style.case_sensitive {
+ arg.raw == style.end_of_options
+ } else {
+ arg.raw.eq_ignore_ascii_case(style.end_of_options)
+ }
+ })
+ .map(|arg| arg.raw_idx)
+ .collect(),
+ )
}