From 5c5b828fcb75aef5708ff95ea1f7994f86bef5b4 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Thu, 30 Apr 2026 22:28:07 +0800 Subject: Add `AsPicker` trait for types convertible to `Vec` --- CHANGELOG.md | 10 +++++++ README.md | 2 +- mingling/src/parser/picker.rs | 66 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eb30d4b..f66dbd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -104,6 +104,16 @@ this::().modify_res(|r: &mut Global| { }); ``` +11. **\[picker\]** For any type that can `Into>`, `.pick()`, `.pick_or()`, and `.pick_or_route()` functions are now supported + +```rust +// Before +let name: String = Picker::new(prev.inner).pick("--name").unpack(); + +// Now +let name: String = prev.pick("--name").unpack(); +``` + #### **BREAKING CHANGES**: 1. **\[macros\]** Removed macro `dispatcher_render!` from `mingling_macros` diff --git a/README.md b/README.md index a8dfda9..5e5809f 100644 --- a/README.md +++ b/README.md @@ -161,7 +161,7 @@ fn comp_greet_command(ctx: &ShellContext) -> Suggest { // Define chain, parsing `GreetEntry` into `StateGreeting` #[chain] fn parse_name_to_greet(prev: GreetEntry) -> NextProcess { - let state_greeting: StateGreeting = Picker::<()>::new(prev.inner) + let state_greeting: StateGreeting = Picker::new(prev.inner) .pick_or::((), "World") .unpack_directly() .into(); diff --git a/mingling/src/parser/picker.rs b/mingling/src/parser/picker.rs index 4641a49..915bc35 100644 --- a/mingling/src/parser/picker.rs +++ b/mingling/src/parser/picker.rs @@ -719,3 +719,69 @@ where T::build_enum(name) } } + +pub trait AsPicker +where + Self: Into>, +{ + /// Converts the value into a `Picker` by first converting it into a `Vec`. + fn as_picker(self) -> Picker + where + Self: Sized, + Vec: From, + { + let vec: Vec = self.into(); + Picker { args: vec.into() } + } + + /// Extracts a value for the given flag and returns a `Pick1` builder (no route). + /// + /// The extracted type `TNext` must implement `Pickable` and `Default`. + /// If the flag is not present, the default value for `TNext` is used. + fn pick(self, val: impl Into) -> Pick1 + where + Self: Sized, + TNext: Pickable + Default, + { + let vec: Vec = self.into(); + let picker: Picker = vec.into(); + picker.pick(val) + } + + /// Extracts a value for the given flag, returning the provided default value if not present, + /// and returns a `Pick1` builder (no route). + /// + /// The extracted type `TNext` must implement `Pickable`. + /// If the flag is not present, the provided `or` value is used. + fn pick_or(self, val: impl Into, or: impl Into) -> Pick1 + where + TNext: Pickable, + { + let vec: Vec = self.into(); + let picker: Picker = vec.into(); + picker.pick_or(val, or) + } + + /// Extracts a value for the given flag, storing the provided route if the flag is not present, + /// and returns a `PickWithRoute1` builder (with route). + /// + /// The extracted type `TNext` must implement `Pickable` and `Default`. + /// If the flag is not present, the default value for `TNext` is used and the provided `route` + /// is stored in the returned builder for later error handling. + fn pick_or_route(self, val: impl Into, route: R) -> PickWithRoute1 + where + TNext: Pickable + Default, + { + let vec: Vec = self.into(); + let picker: Picker = vec.into(); + picker.pick_or_route(val, route) + } +} + +// Implement AsPicker for any type that can be converted into a Vec +impl AsPicker for T +where + T: Sized, + Vec: From, +{ +} -- cgit