diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-07-17 09:03:32 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-07-17 09:03:32 +0800 |
| commit | ed4b8dfc825b59012ad850d6c88067e7007962a2 (patch) | |
| tree | 8f5f4cd9229fae5f088f9b23ca9607341a3b5468 /mingling_picker/src | |
| parent | d77e8926dff6466f0c46ee4529dd9f7b9772ae99 (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/src')
| -rw-r--r-- | mingling_picker/src/corebind/entry_picker.rs | 84 | ||||
| -rw-r--r-- | mingling_picker/src/picker.rs | 86 | ||||
| -rw-r--r-- | mingling_picker/src/picker/patterns.rs | 81 |
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, - } - } -} |
