aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mingling_picker/src/builtin/pick_string.rs29
-rw-r--r--mingling_picker/src/parselib.rs3
-rw-r--r--mingling_picker/src/parselib/single_matcher.rs39
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
+ }
+ }
+}