aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-07-15 12:34:07 +0800
committer魏曹先生 <1992414357@qq.com>2026-07-15 12:34:07 +0800
commit98d21cc18d2859493bfbfc2ee428861e5351e5a1 (patch)
tree81f7b69b8f18e652e484b41975a8fa3051212578
parent559ff1a4d5d164c2fdbc29a9957e3db38651705f (diff)
feat(flag): add PositionalMulti variant and convenience methods
-rw-r--r--mingling_picker/src/flag.rs79
-rw-r--r--mingling_picker/src/pickable/implements.rs4
2 files changed, 77 insertions, 6 deletions
diff --git a/mingling_picker/src/flag.rs b/mingling_picker/src/flag.rs
index aebbc81..6c63c53 100644
--- a/mingling_picker/src/flag.rs
+++ b/mingling_picker/src/flag.rs
@@ -124,13 +124,16 @@ where
/// Describes the attribute (behavior) of a command-line parameter.
///
/// The ordering reflects parse priority (higher = parsed first):
-/// `Positional < Flag < Single < Multi`
+/// `Positional < PositionalMulti < Flag < Single < Multi`
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum PickerFlagAttr {
/// Positional argument matched by its position (e.g., an input file).
#[default]
Positional,
+ /// Positional argument that accepts multiple values (e.g., multiple input files).
+ PositionalMulti,
+
/// Boolean flag with no associated value (e.g., `--verbose`).
Flag,
@@ -153,6 +156,7 @@ impl PickerFlagAttr {
/// - `flag`: A reference to the [`PickerFlag`] to evaluate.
/// - `other`: A closure that returns a [`PickerFlagAttr`] when the flag is
/// **not** positional.
+ #[inline(always)]
pub fn positional_or_else<'a, T>(
flag: &PickerFlag<'a, T>,
other: fn() -> PickerFlagAttr,
@@ -166,6 +170,61 @@ impl PickerFlagAttr {
other()
}
}
+
+ /// Determines if the given `PickerFlag` represents a positional parameter and returns
+ /// `PickerFlagAttr::Positional` if so. Otherwise, returns the provided `default` attribute.
+ ///
+ /// # Parameters
+ ///
+ /// - `flag`: A reference to the [`PickerFlag`] to evaluate.
+ /// - `default`: The [`PickerFlagAttr`] to return if the flag is not positional.
+ #[inline(always)]
+ pub fn positional_or<'a, T>(flag: &PickerFlag<'a, T>, default: PickerFlagAttr) -> PickerFlagAttr
+ where
+ T: Pickable<'a> + Default,
+ {
+ if flag.is_positional() {
+ PickerFlagAttr::Positional
+ } else {
+ default
+ }
+ }
+
+ /// Determines if the given `PickerFlag` represents a positional parameter and returns
+ /// `PickerFlagAttr::Positional` if so. Otherwise, returns `PickerFlagAttr::Single`.
+ ///
+ /// # Parameters
+ ///
+ /// - `flag`: A reference to the [`PickerFlag`] to evaluate.
+ #[inline(always)]
+ pub fn positional_or_single<'a, T>(flag: &PickerFlag<'a, T>) -> PickerFlagAttr
+ where
+ T: Pickable<'a> + Default,
+ {
+ if flag.is_positional() {
+ PickerFlagAttr::Positional
+ } else {
+ PickerFlagAttr::Single
+ }
+ }
+
+ /// Determines if the given `PickerFlag` represents a positional parameter and returns
+ /// `PickerFlagAttr::PositionalMulti` if so. Otherwise, returns `PickerFlagAttr::Multi`.
+ ///
+ /// # Parameters
+ ///
+ /// - `flag`: A reference to the [`PickerFlag`] to evaluate.
+ #[inline(always)]
+ pub fn positional_or_multi<'a, T>(flag: &PickerFlag<'a, T>) -> PickerFlagAttr
+ where
+ T: Pickable<'a> + Default,
+ {
+ if flag.is_positional() {
+ PickerFlagAttr::PositionalMulti
+ } else {
+ PickerFlagAttr::Multi
+ }
+ }
}
#[cfg(test)]
@@ -174,37 +233,49 @@ mod tests {
#[test]
fn test_picker_flag_attr_ordering() {
- // Multi > Single > Flag > Positional
+ // Multi > Single > Flag > PositionalMulti > Positional
assert!(PickerFlagAttr::Multi > PickerFlagAttr::Single);
assert!(PickerFlagAttr::Multi > PickerFlagAttr::Flag);
+ assert!(PickerFlagAttr::Multi > PickerFlagAttr::PositionalMulti);
assert!(PickerFlagAttr::Multi > PickerFlagAttr::Positional);
assert!(PickerFlagAttr::Single > PickerFlagAttr::Flag);
+ assert!(PickerFlagAttr::Single > PickerFlagAttr::PositionalMulti);
assert!(PickerFlagAttr::Single > PickerFlagAttr::Positional);
+ assert!(PickerFlagAttr::Flag > PickerFlagAttr::PositionalMulti);
assert!(PickerFlagAttr::Flag > PickerFlagAttr::Positional);
+ assert!(PickerFlagAttr::PositionalMulti > PickerFlagAttr::Positional);
+
// PartialOrd
assert!(PickerFlagAttr::Multi >= PickerFlagAttr::Single);
assert!(PickerFlagAttr::Single >= PickerFlagAttr::Flag);
- assert!(PickerFlagAttr::Flag >= PickerFlagAttr::Positional);
+ assert!(PickerFlagAttr::Flag >= PickerFlagAttr::PositionalMulti);
+ assert!(PickerFlagAttr::PositionalMulti >= PickerFlagAttr::Positional);
- assert!(PickerFlagAttr::Positional < PickerFlagAttr::Flag);
+ assert!(PickerFlagAttr::Positional < PickerFlagAttr::PositionalMulti);
+ assert!(PickerFlagAttr::PositionalMulti < PickerFlagAttr::Flag);
assert!(PickerFlagAttr::Flag < PickerFlagAttr::Single);
assert!(PickerFlagAttr::Single < PickerFlagAttr::Multi);
+ }
+ #[test]
+ fn test_picker_flag_attr_sorting() {
// Sort
let mut values = vec![
PickerFlagAttr::Flag,
PickerFlagAttr::Single,
PickerFlagAttr::Positional,
PickerFlagAttr::Multi,
+ PickerFlagAttr::PositionalMulti,
];
values.sort();
assert_eq!(
values,
vec![
PickerFlagAttr::Positional,
+ PickerFlagAttr::PositionalMulti,
PickerFlagAttr::Flag,
PickerFlagAttr::Single,
PickerFlagAttr::Multi,
diff --git a/mingling_picker/src/pickable/implements.rs b/mingling_picker/src/pickable/implements.rs
index eb46334..cbf22c8 100644
--- a/mingling_picker/src/pickable/implements.rs
+++ b/mingling_picker/src/pickable/implements.rs
@@ -2,7 +2,7 @@ use crate::{Pickable, PickerFlagAttr};
impl<'a> Pickable<'a> for String {
fn get_attr(flag: &'a crate::PickerFlag<'a, Self>) -> PickerFlagAttr {
- PickerFlagAttr::positional_or_else(flag, || PickerFlagAttr::Single)
+ PickerFlagAttr::positional_or_single(flag)
}
fn tag(_ctx: super::TagPhaseContext) -> Vec<usize> {
@@ -16,7 +16,7 @@ impl<'a> Pickable<'a> for String {
impl<'a> Pickable<'a> for Vec<String> {
fn get_attr(flag: &'a crate::PickerFlag<'a, Self>) -> PickerFlagAttr {
- PickerFlagAttr::positional_or_else(flag, || PickerFlagAttr::Multi)
+ PickerFlagAttr::positional_or_multi(flag)
}
fn tag(_ctx: super::TagPhaseContext) -> Vec<usize> {