aboutsummaryrefslogtreecommitdiff
path: root/mingling_picker
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-07-17 09:03:32 +0800
committer魏曹先生 <1992414357@qq.com>2026-07-17 09:03:32 +0800
commited4b8dfc825b59012ad850d6c88067e7007962a2 (patch)
tree8f5f4cd9229fae5f088f9b23ca9607341a3b5468 /mingling_picker
parentd77e8926dff6466f0c46ee4529dd9f7b9772ae99 (diff)
feat: add shorthand methods for fallback picker patterns
Introduce `pick_or`, `pick_or_default`, and `pick_or_route` methods on both `Picker` and existing patterns to combine picking with a fallback in a single call. Extract shared `PickerPattern1` construction into `Picker::build_pattern1`.
Diffstat (limited to 'mingling_picker')
-rw-r--r--mingling_picker/src/corebind/entry_picker.rs84
-rw-r--r--mingling_picker/src/picker.rs86
-rw-r--r--mingling_picker/src/picker/patterns.rs81
3 files changed, 210 insertions, 41 deletions
diff --git a/mingling_picker/src/corebind/entry_picker.rs b/mingling_picker/src/corebind/entry_picker.rs
index f96ba66..69bc4d8 100644
--- a/mingling_picker/src/corebind/entry_picker.rs
+++ b/mingling_picker/src/corebind/entry_picker.rs
@@ -2,7 +2,7 @@ use std::marker::PhantomData;
use mingling_core::{ChainProcess, Groupped, ProgramCollect};
-use crate::{Pickable, Picker, PickerArg, PickerArgResult, PickerArgs, PickerPattern1};
+use crate::{Pickable, Picker, PickerArg, PickerArgs, PickerPattern1};
/// Trait for converting Mingling entry types (types that implement `Groupped<R>` and `Into<Vec<String>>`)
/// into [`Picker`] instances for a given route type `R`.
@@ -40,15 +40,79 @@ pub trait EntryPicker<'a, This> {
Next: Pickable<'a> + Default + Sized,
{
let picker = Self::to_picker(self);
- PickerPattern1 {
- args: picker.args,
- arg_1: arg.into(),
- result_1: PickerArgResult::Unparsed,
- default_1: None,
- route_1: None,
- post_1: None,
- error_route: None,
- }
+ Picker::build_pattern1(picker.args, arg.into(), None)
+ }
+
+ /// Starts building a picker pattern with the first argument, using a default value provider.
+ ///
+ /// This is a shorthand for calling `.pick(arg).or(func)`.
+ ///
+ /// # Type Parameters
+ ///
+ /// * `Next` — The nominal type of the first argument; must implement [`Pickable`].
+ ///
+ /// # Parameters
+ ///
+ /// * `arg` — The argument definition, typically obtained from [`crate::arg`].
+ /// * `func` — A closure that provides a default value if the arg is not provided by the user.
+ fn pick_or<Next, F>(
+ self,
+ arg: impl Into<&'a PickerArg<'a, Next>>,
+ func: F,
+ ) -> PickerPattern1<'a, Next, ChainProcess<This>>
+ where
+ Self: Sized,
+ Next: Pickable<'a> + Default + Sized,
+ F: FnMut() -> Next + 'static,
+ {
+ self.pick(arg).or(func)
+ }
+
+ /// Starts building a picker pattern with the first argument, using a default value.
+ ///
+ /// This is a shorthand for calling `.pick(arg).or_default()`.
+ ///
+ /// # Type Parameters
+ ///
+ /// * `Next` — The nominal type of the first argument; must implement [`Pickable`] and [`Default`].
+ ///
+ /// # Parameters
+ ///
+ /// * `arg` — The argument definition, typically obtained from [`crate::arg`].
+ fn pick_or_default<Next>(
+ self,
+ arg: impl Into<&'a PickerArg<'a, Next>>,
+ ) -> PickerPattern1<'a, Next, ChainProcess<This>>
+ where
+ Self: Sized,
+ Next: Pickable<'a> + Default + Sized,
+ {
+ self.pick(arg).or_default()
+ }
+
+ /// Starts building a picker pattern with the first argument, using a route if the arg is not provided.
+ ///
+ /// This is a shorthand for calling `.pick(arg).or_route(func)`.
+ ///
+ /// # Type Parameters
+ ///
+ /// * `Next` — The nominal type of the first argument; must implement [`Pickable`].
+ ///
+ /// # Parameters
+ ///
+ /// * `arg` — The argument definition, typically obtained from [`crate::arg`].
+ /// * `func` — A closure that produces a route value if the arg is not provided by the user.
+ fn pick_or_route<Next, F>(
+ self,
+ arg: impl Into<&'a PickerArg<'a, Next>>,
+ func: F,
+ ) -> PickerPattern1<'a, Next, ChainProcess<This>>
+ where
+ Self: Sized,
+ Next: Pickable<'a> + Default + Sized,
+ F: FnMut() -> ChainProcess<This> + 'static,
+ {
+ self.pick(arg).or_route(func)
}
}
diff --git a/mingling_picker/src/picker.rs b/mingling_picker/src/picker.rs
index 81fb10a..7cf1525 100644
--- a/mingling_picker/src/picker.rs
+++ b/mingling_picker/src/picker.rs
@@ -254,6 +254,59 @@ impl<'a> Iterator for PickerIter<'a> {
impl<'a> ExactSizeIterator for PickerIter<'a> {}
+impl<'a, Route> Picker<'a, Route> {
+ /// Creates a `PickerPattern1` from the given arg to start a picking chain.
+ ///
+ /// This method initiates a parameter picking chain with one arg.
+ /// The result is initially `Unparsed`.
+ pub fn pick<N>(self, arg: impl Into<&'a PickerArg<'a, N>>) -> PickerPattern1<'a, N, Route>
+ where
+ N: Pickable<'a>,
+ {
+ Self::build_pattern1(self.args, arg.into(), None::<Route>)
+ }
+
+ /// Creates a `PickerPattern1` from the given arg.
+ /// If parsing fails, attempts the fallback arg.
+ pub fn pick_or<N, F>(
+ self,
+ arg: impl Into<&'a PickerArg<'a, N>>,
+ or_arg: F,
+ ) -> PickerPattern1<'a, N, Route>
+ where
+ N: Pickable<'a>,
+ F: FnMut() -> N + 'static,
+ {
+ self.pick(arg).or(or_arg)
+ }
+
+ /// Creates a `PickerPattern1` from the given arg.
+ /// If parsing fails, uses the provided default value.
+ pub fn pick_or_default<N>(
+ self,
+ arg: impl Into<&'a PickerArg<'a, N>>,
+ ) -> PickerPattern1<'a, N, Route>
+ where
+ N: Pickable<'a> + Default,
+ {
+ self.pick(arg).or_default()
+ }
+
+ /// Creates a `PickerPattern1` from the given arg.
+ /// If parsing fails, switches to the given error route.
+ pub fn pick_or_route<N, F>(
+ self,
+ arg: impl Into<&'a PickerArg<'a, N>>,
+ error_route: F,
+ ) -> PickerPattern1<'a, N, Route>
+ where
+ N: Pickable<'a>,
+ F: FnMut() -> Route + 'static,
+ {
+ self.pick(arg).or_route(error_route)
+ }
+}
+
/// Trait for converting types into a `Picker`
///
/// Implemented for:
@@ -289,15 +342,7 @@ pub trait IntoPicker<'a> {
Self: Sized,
N: Pickable<'a> + Default + Sized,
{
- PickerPattern1 {
- args: self.to_picker().args,
- arg_1: arg.into(),
- result_1: PickerArgResult::Unparsed,
- default_1: None,
- route_1: None,
- post_1: None,
- error_route: None,
- }
+ Picker::build_pattern1(self.to_picker().args, arg.into(), None::<()>)
}
/// Converts the value into a `Picker` with a specified route type.
@@ -362,3 +407,26 @@ impl<'a> IntoPicker<'a> for Vec<String> {
}
}
}
+
+// Private helper: shared construction logic for `PickerPattern1`.
+// Both `Picker::pick` and `IntoPicker::pick` delegate to this.
+impl<'a, Route> Picker<'a, Route> {
+ pub(crate) fn build_pattern1<N>(
+ args: PickerArgs<'a>,
+ arg: &'a PickerArg<'a, N>,
+ error_route: Option<Route>,
+ ) -> PickerPattern1<'a, N, Route>
+ where
+ N: Pickable<'a>,
+ {
+ PickerPattern1 {
+ args,
+ error_route,
+ arg_1: arg,
+ result_1: PickerArgResult::Unparsed,
+ route_1: None,
+ default_1: None,
+ post_1: None,
+ }
+ }
+}
diff --git a/mingling_picker/src/picker/patterns.rs b/mingling_picker/src/picker/patterns.rs
index daaf43a..8bdddde 100644
--- a/mingling_picker/src/picker/patterns.rs
+++ b/mingling_picker/src/picker/patterns.rs
@@ -1,6 +1,6 @@
use mingling_picker_macros::internal_repeat;
-use crate::{Pickable, Picker, PickerArg, PickerArgResult, PickerArgs};
+use crate::{Pickable, PickerArg, PickerArgResult, PickerArgs};
internal_repeat!(1..=32 => {
#[doc(hidden)]
@@ -175,26 +175,63 @@ internal_repeat!(1..32 => {
+)
}
}
+
+ /// Picks a new arg with a default value provider in a single call.
+ ///
+ /// This is a shorthand for calling `.pick(arg).or(func)`.
+ ///
+ /// # Example
+ ///
+ /// ```ignore
+ /// let pattern = picker
+ /// .pick_or(&my_arg, || 42);
+ /// ```
+ #[allow(clippy::type_complexity)]
+ pub fn pick_or<N, F>(self, arg: impl Into<&'a PickerArg<'a, N>>, func: F) -> PickerPattern$+<'a, (T$,+), N, Route>
+ where
+ N: Pickable<'a>,
+ F: FnMut() -> N + 'static,
+ F: 'static,
+ {
+ self.pick(arg).or(func)
+ }
+
+ /// Picks a new arg with a default value in a single call.
+ ///
+ /// This is a shorthand for calling `.pick(arg).or_default()`.
+ ///
+ /// # Example
+ ///
+ /// ```ignore
+ /// let pattern = picker
+ /// .pick_or_default(&my_arg);
+ /// ```
+ #[allow(clippy::type_complexity)]
+ pub fn pick_or_default<N>(self, arg: impl Into<&'a PickerArg<'a, N>>) -> PickerPattern$+<'a, (T$,+), N, Route>
+ where
+ N: Pickable<'a> + Default,
+ {
+ self.pick(arg).or_default()
+ }
+
+ /// Picks a new arg with a route in a single call.
+ ///
+ /// This is a shorthand for calling `.pick(arg).or_route(func)`.
+ ///
+ /// # Example
+ ///
+ /// ```ignore
+ /// let pattern = picker
+ /// .pick_or_route(&my_arg, || Redirect::home());
+ /// ```
+ #[allow(clippy::type_complexity)]
+ pub fn pick_or_route<N, F>(self, arg: impl Into<&'a PickerArg<'a, N>>, func: F) -> PickerPattern$+<'a, (T$,+), N, Route>
+ where
+ N: Pickable<'a>,
+ F: FnMut() -> Route + 'static,
+ F: 'static,
+ {
+ self.pick(arg).or_route(func)
+ }
}
});
-
-impl<'a, Route> Picker<'a, Route> {
- /// Creates a `PickerPattern1` from the given arg to start a picking chain.
- ///
- /// This method initiates a parameter picking chain with one arg.
- /// The result is initially `Unparsed`.
- pub fn pick<N>(self, arg: impl Into<&'a PickerArg<'a, N>>) -> PickerPattern1<'a, N, Route>
- where
- N: Pickable<'a>,
- {
- PickerPattern1 {
- args: self.args,
- error_route: None::<Route>,
- arg_1: arg.into(),
- result_1: PickerArgResult::Unparsed,
- route_1: None,
- default_1: None,
- post_1: None,
- }
- }
-}