aboutsummaryrefslogtreecommitdiff
path: root/mingling_picker
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-07-16 19:47:01 +0800
committer魏曹先生 <1992414357@qq.com>2026-07-16 19:47:01 +0800
commit4f4a61d493547660260a5aa1db1af8a6ec42bbb6 (patch)
tree68e228ce2ecaf232f5367beac677dc4126b7188e /mingling_picker
parent20253556eacdcb068210254b540f47a4522fc6f5 (diff)
refactor: extract `seek_end_of_options` into utils and add test helpers
Deduplicate the `seek_end_of_options` function by moving it from both `arg_matcher` and `flag_matcher` into a single shared implementation in utils. Add `make_masked` and `make_args` test helpers to the test crate
Diffstat (limited to 'mingling_picker')
-rw-r--r--mingling_picker/src/parselib/arg_matcher.rs32
-rw-r--r--mingling_picker/src/parselib/flag_matcher.rs18
-rw-r--r--mingling_picker/src/parselib/utils.rs10
-rw-r--r--mingling_picker/test/src/lib.rs15
-rw-r--r--mingling_picker/test/src/test/arg_matcher_test.rs31
-rw-r--r--mingling_picker/test/src/test/style_test.rs10
6 files changed, 37 insertions, 79 deletions
diff --git a/mingling_picker/src/parselib/arg_matcher.rs b/mingling_picker/src/parselib/arg_matcher.rs
index 931652a..808e4a2 100644
--- a/mingling_picker/src/parselib/arg_matcher.rs
+++ b/mingling_picker/src/parselib/arg_matcher.rs
@@ -1,4 +1,7 @@
-use crate::{matcher_needed::*, parselib::build_possible_flags};
+use crate::{
+ matcher_needed::*,
+ parselib::{build_possible_flags, seek_end_of_options},
+};
/// `ArgMatcher` is used for parameters that carry a single value.
///
@@ -53,7 +56,6 @@ impl Matcher for ArgMatcher {
arg_info: &PickerArgInfo,
) -> Option<usize> {
if arg_info.positional {
- // Positional: first available position.
return args.first().map(|a| a.raw_idx);
}
@@ -61,7 +63,6 @@ impl Matcher for ArgMatcher {
let end = seek_end_of_options(args, style);
for arg in args {
- // Stop at end-of-options marker.
if end.is_some_and(|e| arg.raw_idx >= e) {
break;
}
@@ -83,7 +84,6 @@ impl Matcher for ArgMatcher {
arg_info: &PickerArgInfo,
) -> Vec<usize> {
if arg_info.positional {
- // Positional: all available positions before `--`.
let end = seek_end_of_options(args, style);
return args
.iter()
@@ -98,7 +98,6 @@ impl Matcher for ArgMatcher {
let mut result = Vec::new();
let mut i = 0;
while i < args.len() {
- // Stop at end-of-options marker.
if end.is_some_and(|e| args[i].raw_idx >= e) {
break;
}
@@ -108,28 +107,22 @@ impl Matcher for ArgMatcher {
.any(|f| Self::matches(args[i].raw, f, style.case_sensitive));
if matched {
- // Find which flag matched to check eq mode.
let flag_str = possible_flags
.iter()
.find(|f| Self::matches(args[i].raw, f, style.case_sensitive))
.expect("already matched");
- result.push(args[i].raw_idx); // flag position
+ result.push(args[i].raw_idx);
if !Self::is_eq_mode(args[i].raw, flag_str) {
- // Non-eq mode: the next argument is the value.
- // Always tag it — even if it looks like a flag — so that
- // the mask reserves it. Validation is the Pickable's job.
if i + 1 < args.len() {
result.push(args[i + 1].raw_idx);
- i += 2; // skip flag + value
+ i += 2;
continue;
}
- // No value available: tag just the flag.
i += 1;
continue;
}
- // eq mode: value is inline, no extra slot.
i += 1;
continue;
}
@@ -139,16 +132,3 @@ impl Matcher for ArgMatcher {
result
}
}
-
-/// Locate the end-of-options marker (`--`) in the argument list.
-fn seek_end_of_options(args: &[MaskedArg], style: &ParserStyle) -> Option<usize> {
- args.iter()
- .find(|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)
-}
diff --git a/mingling_picker/src/parselib/flag_matcher.rs b/mingling_picker/src/parselib/flag_matcher.rs
index 782d0f8..e93d35a 100644
--- a/mingling_picker/src/parselib/flag_matcher.rs
+++ b/mingling_picker/src/parselib/flag_matcher.rs
@@ -1,6 +1,6 @@
use crate::{
matcher_needed::*,
- parselib::{build_possible_flags, get_seeked_first, multi_seek_eq},
+ parselib::{build_possible_flags, get_seeked_first, multi_seek_eq, seek_end_of_options},
};
/// `FlagMatcher` is used to match flags in command-line arguments.
@@ -80,19 +80,3 @@ fn single_pass_match_all(
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(),
- )
-}
diff --git a/mingling_picker/src/parselib/utils.rs b/mingling_picker/src/parselib/utils.rs
index 5219b02..ae3c203 100644
--- a/mingling_picker/src/parselib/utils.rs
+++ b/mingling_picker/src/parselib/utils.rs
@@ -34,7 +34,15 @@ pub fn build_possible_flags(style: &ParserStyle, arg_info: &PickerArgInfo) -> Ve
/// subsequent arguments should be treated as positional arguments, not flags.
#[must_use]
pub fn seek_end_of_options(args: &[MaskedArg], style: &ParserStyle) -> Option<usize> {
- get_seeked_first(seek_eq(args, style.end_of_options, style.case_sensitive))
+ args.iter()
+ .find(|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)
}
/// Seeks arguments in `args` that are exactly equal to the given `string`.
diff --git a/mingling_picker/test/src/lib.rs b/mingling_picker/test/src/lib.rs
index 9bc0560..eac6cad 100644
--- a/mingling_picker/test/src/lib.rs
+++ b/mingling_picker/test/src/lib.rs
@@ -6,3 +6,18 @@
#[cfg(test)]
mod test;
+
+use mingling_picker::parselib::MaskedArg;
+
+/// Create a single `MaskedArg` from a raw string and its original index.
+pub fn make_masked(raw: &str, idx: usize) -> MaskedArg<'_> {
+ MaskedArg { raw, raw_idx: idx }
+}
+
+/// Create a `Vec<MaskedArg>` from an array of `(raw, raw_idx)` pairs.
+pub fn make_args<'a>(pairs: &'a [(&'a str, usize)]) -> Vec<MaskedArg<'a>> {
+ pairs
+ .iter()
+ .map(|&(raw, idx)| MaskedArg { raw, raw_idx: idx })
+ .collect()
+}
diff --git a/mingling_picker/test/src/test/arg_matcher_test.rs b/mingling_picker/test/src/test/arg_matcher_test.rs
index 3249079..947e20f 100644
--- a/mingling_picker/test/src/test/arg_matcher_test.rs
+++ b/mingling_picker/test/src/test/arg_matcher_test.rs
@@ -1,16 +1,9 @@
use mingling_picker::PickerArgInfo;
-use mingling_picker::parselib::{ArgMatcher, MaskedArg, Matcher, POWERSHELL_STYLE, UNIX_STYLE};
+use mingling_picker::parselib::{ArgMatcher, Matcher, POWERSHELL_STYLE, UNIX_STYLE};
-fn make_args<'a>(pairs: &'a [(&'a str, usize)]) -> Vec<MaskedArg<'a>> {
- pairs
- .iter()
- .map(|&(raw, idx)| MaskedArg { raw, raw_idx: idx })
- .collect()
-}
+use crate::make_args;
-// ============================================================
// on_match_one — Named
-// ============================================================
#[test]
fn test_match_one_named_basic() {
@@ -59,9 +52,7 @@ fn test_match_one_named_after_end_of_options() {
assert_eq!(result, None);
}
-// ============================================================
// on_match_one — Positional
-// ============================================================
#[test]
fn test_match_one_positional_basic() {
@@ -81,9 +72,7 @@ fn test_match_one_positional_takes_first() {
assert_eq!(result, Some(0));
}
-// ============================================================
// on_match_all — Named, single occurrence
-// ============================================================
#[test]
fn test_match_all_named_flag_plus_value() {
@@ -125,9 +114,7 @@ fn test_match_all_named_value_looks_like_flag() {
assert_eq!(result, vec![0, 1]);
}
-// ============================================================
// on_match_all — Named, multiple occurrences (Single per flag)
-// ============================================================
#[test]
fn test_match_all_named_two_occurrences() {
@@ -149,9 +136,7 @@ fn test_match_all_named_skips_non_matching_args() {
assert_eq!(result, vec![0, 1, 3, 4]);
}
-// ============================================================
// on_match_all — Named, short flag
-// ============================================================
#[test]
fn test_match_all_named_short_flag() {
@@ -163,9 +148,7 @@ fn test_match_all_named_short_flag() {
assert_eq!(result, vec![0, 1]);
}
-// ============================================================
// on_match_all — Named, eq + non-eq mixed
-// ============================================================
#[test]
fn test_match_all_named_mixed_eq_and_regular() {
@@ -176,9 +159,7 @@ fn test_match_all_named_mixed_eq_and_regular() {
assert_eq!(result, vec![0, 1, 2]);
}
-// ============================================================
// on_match_all — Named, case insensitive (PowerShell)
-// ============================================================
#[test]
fn test_match_all_named_powershell_case_insensitive() {
@@ -189,9 +170,7 @@ fn test_match_all_named_powershell_case_insensitive() {
assert_eq!(result, vec![0, 1]);
}
-// ============================================================
// on_match_all — Positional
-// ============================================================
#[test]
fn test_match_all_positional_single() {
@@ -211,9 +190,7 @@ fn test_match_all_positional_multiple() {
assert_eq!(result, vec![0, 1]);
}
-// ============================================================
// End-of-options marker (`--`)
-// ============================================================
#[test]
fn test_match_all_named_stops_at_end_of_options() {
@@ -240,9 +217,7 @@ fn test_match_all_positional_stops_at_end_of_options() {
assert_eq!(result, vec![0]);
}
-// ============================================================
// Empty args
-// ============================================================
#[test]
fn test_match_one_empty() {
@@ -262,9 +237,7 @@ fn test_match_all_empty() {
assert!(result.is_empty());
}
-// ============================================================
// Verify that -- itself is never matched as a flag
-// ============================================================
#[test]
fn test_match_all_end_of_options_not_matched() {
diff --git a/mingling_picker/test/src/test/style_test.rs b/mingling_picker/test/src/test/style_test.rs
index efb2185..3c337b9 100644
--- a/mingling_picker/test/src/test/style_test.rs
+++ b/mingling_picker/test/src/test/style_test.rs
@@ -1,9 +1,11 @@
use mingling_picker::PickerArgInfo;
use mingling_picker::parselib::{
- FlagMatcher, MaskedArg, Matcher, POWERSHELL_STYLE, ParserStyle, ParserStyleNamingCase,
- UNIX_STYLE, WINDOWS_STYLE, build_possible_flags,
+ FlagMatcher, Matcher, POWERSHELL_STYLE, ParserStyle, ParserStyleNamingCase, UNIX_STYLE,
+ WINDOWS_STYLE, build_possible_flags,
};
+use crate::make_masked;
+
// Style: formatting utilities
#[test]
@@ -45,10 +47,6 @@ fn test_build_possible_flags_with_short_and_alias() {
// Style: matching with different styles via Matcher trait
-fn make_masked(raw: &str, idx: usize) -> MaskedArg<'_> {
- MaskedArg { raw, raw_idx: idx }
-}
-
#[test]
fn test_windows_style_match() {
// Windows style: /verbose (case insensitive)