diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-07-17 03:24:51 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-07-17 03:25:24 +0800 |
| commit | b9f208deed7b8e012fbcd84202e2fb1d5eb8eeb9 (patch) | |
| tree | 2e0f00651b0cff09a2f6bafd6ce35046532ffa81 /mingling_picker/src/parselib/single_matcher.rs | |
| parent | 8b2c209c2f111e0e208de5dde9df6c4bd3ea1052 (diff) | |
feat(picker2): complete Picker2 prototype
Picker2 replaces the original Picker1 with a two-phase (tag → pick) +
mask-bitmap architecture, decoupling argument matching from type
conversion via a composable matcher pipeline.
Architecture
- FlagMatcher — boolean flags (--verbose)
- ArgMatcher — single flag+value pairs (--name Alice)
- MultiArgMatcher — multi-value flag groups (--files a.txt b.txt)
- PositionalMatcher — positional arguments, respects `--`
- SingleMatcher — composite for Single-type Pickables
Types
- Flag (Active/Inactive) — semantic bool flag value
- String + 14 numeric types via SinglePickable trait
- Vec<T> — greedy multi-value (all SinglePickable types)
- VecUntil<T> — bounded multi-value via BoundaryCheck trait
- VecUntil<T>, pick_string, pick_numbers, pick_bool, pick_flag
Style system
- UNIX_STYLE (kebab), POWERSHELL_STYLE (Pascal), WINDOWS_STYLE (Pascal)
- naming_case auto-conversion via just_fmt integration
- Style-aware separator (= for Unix, : for PS/Windows)
Infrastructure
- internal_repeat! macro generates PickerPattern1..=32
- SinglePickable blanket impl → Pickable
- MultiPickableWithBoundary trait with greedy/bounded variants
- 151 integration tests
- Docs updated for parser feature
Diffstat (limited to 'mingling_picker/src/parselib/single_matcher.rs')
| -rw-r--r-- | mingling_picker/src/parselib/single_matcher.rs | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/mingling_picker/src/parselib/single_matcher.rs b/mingling_picker/src/parselib/single_matcher.rs new file mode 100644 index 0000000..25c4741 --- /dev/null +++ b/mingling_picker/src/parselib/single_matcher.rs @@ -0,0 +1,59 @@ +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`](crate::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, only complete pairs (flag + value) are kept. + /// Flag occurrences without a following value or inline separator + /// are dropped so they remain available for other matchers. + #[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()); + let sep = ParserStyle::global_style().value_separator; + + // Walk pairs: [flag, value, flag, value, ...] + // Drop any flag that has no following value and no inline separator. + let mut i = 0; + let mut result = Vec::with_capacity(positions.len()); + while i < positions.len() { + let flag_idx = positions[i]; + if let Some(raw) = args.get(flag_idx) + && raw.contains(sep) + { + // Eq mode: value is inline, keep just the flag. + result.push(flag_idx); + i += 1; + continue; + } + if i + 1 < positions.len() { + // Pair: flag + value. + result.push(flag_idx); + result.push(positions[i + 1]); + i += 2; + } else { + // Flag without value — drop it. + i += 1; + } + } + result + } + } +} |
