diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-07-16 23:46:40 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-07-16 23:46:40 +0800 |
| commit | 19e89549789b1af9a98b9c9401043e680a2d6eac (patch) | |
| tree | ddc7f08d2bb2c9e11f5c711e5004c0618ed59430 | |
| parent | 06d31f314ef9f1546ef70e9f1d082c4f1fd49cdf (diff) | |
refactor(picker): extract single-value tag logic into SingleMatcher
| -rw-r--r-- | mingling_picker/src/builtin/pick_string.rs | 29 | ||||
| -rw-r--r-- | mingling_picker/src/parselib.rs | 3 | ||||
| -rw-r--r-- | mingling_picker/src/parselib/single_matcher.rs | 39 |
3 files changed, 45 insertions, 26 deletions
diff --git a/mingling_picker/src/builtin/pick_string.rs b/mingling_picker/src/builtin/pick_string.rs index 873b4bd..6c11ef3 100644 --- a/mingling_picker/src/builtin/pick_string.rs +++ b/mingling_picker/src/builtin/pick_string.rs @@ -1,4 +1,4 @@ -use crate::parselib::{ArgMatcher, Matcher, ParserStyle, PositionalMatcher}; +use crate::parselib::{ParserStyle, SingleMatcher}; use crate::pickable_needed::*; impl<'a> Pickable<'a> for String { @@ -7,24 +7,7 @@ impl<'a> Pickable<'a> for String { } fn tag(ctx: TagPhaseContext) -> Vec<usize> { - if ctx.arg_info.positional { - PositionalMatcher::match_one(ctx.into()) - .map(|i| vec![i]) - .unwrap_or_default() - } else { - // Check for flag-without-value before consuming ctx. - let args = ctx.args; - let positions = ArgMatcher::match_all(ctx.into()); - if positions.len() == 1 { - let sep = ParserStyle::global_style().value_separator; - if let Some(raw) = args.get(positions[0]) - && !raw.contains(sep) - { - return vec![]; - } - } - positions - } + SingleMatcher::tag(ctx) } fn pick(raw_strs: &[&str]) -> PickerArgResult<Self> { @@ -32,19 +15,13 @@ impl<'a> Pickable<'a> for String { 0 => PickerArgResult::NotFound, 1 => { let s = raw_strs[0]; - // Inline value via style separator (e.g., --name=Alice, -Name:Alice). let sep = ParserStyle::global_style().value_separator; if let Some(pos) = s.rfind(sep) { return PickerArgResult::Parsed(s[pos + 1..].to_string()); } - // Positional value or single raw token — return as-is. - // (Named flags without a value are already filtered out by tag.) PickerArgResult::Parsed(s.to_string()) } - _ => { - // flag + value as separate args: take the second element. - PickerArgResult::Parsed(raw_strs[1].to_string()) - } + _ => PickerArgResult::Parsed(raw_strs[1].to_string()), } } } diff --git a/mingling_picker/src/parselib.rs b/mingling_picker/src/parselib.rs index 4e9f329..456a34d 100644 --- a/mingling_picker/src/parselib.rs +++ b/mingling_picker/src/parselib.rs @@ -7,6 +7,9 @@ pub use arg_matcher::*; mod pos_matcher; pub use pos_matcher::*; +mod single_matcher; +pub use single_matcher::*; + mod style; pub use style::*; diff --git a/mingling_picker/src/parselib/single_matcher.rs b/mingling_picker/src/parselib/single_matcher.rs new file mode 100644 index 0000000..3606d3a --- /dev/null +++ b/mingling_picker/src/parselib/single_matcher.rs @@ -0,0 +1,39 @@ +use crate::TagPhaseContext; +use crate::parselib::{ArgMatcher, Matcher, ParserStyle, PositionalMatcher}; + +/// `SingleMatcher` is a composite matcher for single-value parameters. +/// +/// It delegates to [`PositionalMatcher`] for positional args and +/// [`ArgMatcher`] for named args, adding a guard: if a named flag +/// captures only itself with no inline value (eq mode), the result +/// is cleared so that [`Pickable::pick`] receives `[]` → `NotFound`. +/// +/// This is the standard tag implementation for all `Single`-type +/// `Pickable` implementations (e.g., `String`, `i32`, `u64`). +pub struct SingleMatcher; + +impl SingleMatcher { + /// Match a single positional value or a named flag+value pair. + /// + /// For named args, returns `[]` when the flag has no following + /// value and no inline separator — indicating a missing value. + #[inline(always)] + pub fn tag(ctx: TagPhaseContext) -> Vec<usize> { + if ctx.arg_info.positional { + PositionalMatcher::match_one(ctx.into()) + .map(|i| vec![i]) + .unwrap_or_default() + } else { + let args = ctx.args; + let positions = ArgMatcher::match_all(ctx.into()); + if positions.len() == 1 { + let sep = ParserStyle::global_style().value_separator; + if let Some(raw) = args.get(positions[0]) + && !raw.contains(sep) { + return vec![]; + } + } + positions + } + } +} |
