aboutsummaryrefslogtreecommitdiff
path: root/arg_picker
diff options
context:
space:
mode:
Diffstat (limited to 'arg_picker')
-rw-r--r--arg_picker/Cargo.toml3
-rw-r--r--arg_picker/src/arg.rs57
-rw-r--r--arg_picker/src/builtin.rs1
-rw-r--r--arg_picker/src/builtin/pick_picker_args.rs21
-rw-r--r--arg_picker/src/constants.rs16
-rw-r--r--arg_picker/src/corebind/entry_picker.rs131
-rw-r--r--arg_picker/src/infos.rs75
-rw-r--r--arg_picker/src/lib.rs20
-rw-r--r--arg_picker/src/parselib.rs23
-rw-r--r--arg_picker/src/picker.rs108
-rw-r--r--arg_picker/src/picker/parse.rs8
-rw-r--r--arg_picker/src/picker/result.rs8
-rw-r--r--arg_picker/test/src/test/route_test.rs4
13 files changed, 292 insertions, 183 deletions
diff --git a/arg_picker/Cargo.toml b/arg_picker/Cargo.toml
index f7672c1..d87a844 100644
--- a/arg_picker/Cargo.toml
+++ b/arg_picker/Cargo.toml
@@ -9,9 +9,8 @@ readme = "README.md"
description = "A lightweight, type-safe CLI argument parser"
[features]
-mingling_support = ["dep:mingling_core", "arg-picker-macros/mingling_support"]
+mingling_support = ["arg-picker-macros/mingling_support"]
[dependencies]
-mingling_core = { workspace = true, optional = true }
arg-picker-macros.workspace = true
just_fmt.workspace = true
diff --git a/arg_picker/src/arg.rs b/arg_picker/src/arg.rs
index 78ad539..4fa21b5 100644
--- a/arg_picker/src/arg.rs
+++ b/arg_picker/src/arg.rs
@@ -1,4 +1,4 @@
-use crate::Pickable;
+use crate::{Pickable, PickerArgInfo};
use std::marker::PhantomData;
/// Represents a constraint definition for a parameter selection.
@@ -133,14 +133,61 @@ where
self.positional = positional;
self
}
+
+ /// Converts this `PickerArg` into a `PickerArgInfo` value.
+ ///
+ /// This is a convenience method equivalent to calling `PickerArgInfo::from(self)`.
+ pub fn into_info(self) -> PickerArgInfo<'a> {
+ let value = self;
+ let (long, alias) = match value.full.len() {
+ 0 => (None, None),
+ _ => {
+ let long = Some(value.full[0]);
+ let alias = if value.full.len() > 1 {
+ Some(value.full[1..].to_vec())
+ } else {
+ None
+ };
+ (long, alias)
+ }
+ };
+
+ PickerArgInfo {
+ short: value.short,
+ long,
+ alias,
+ positional: value.positional,
+ optional: false,
+ multi: false,
+ is_flag: false,
+ }
+ }
}
/// Describes the attribute (behavior) of a command-line parameter.
///
/// The ordering reflects parse priority (higher = parsed first):
-/// `PositionalMulti < Positional < Flag < Single < Multi`
+/// `Postprocess < Final < PositionalMulti < Positional < Flag < Single < Multi < Begin < Preprocess`
+///
+/// # Variants
+///
+/// - `Postprocess` — Reserved lowest priority, used only in special cases.
+/// - `Final` — Reserved post-processing priority, used only in special cases.
+/// - `PositionalMulti` — Positional argument that accepts multiple values (e.g., multiple input files).
+/// - `Positional` — Positional argument matched by its position (e.g., an input file).
+/// - `Flag` — Boolean flag with no associated value (e.g., `--verbose`).
+/// - `Single` — Accepts a single value (e.g., `--name Alice`).
+/// - `Multi` — Accepts multiple values (e.g., `--file a.txt --file b.txt`).
+/// - `Begin` — Reserved pre-processing priority, used only in special cases.
+/// - `Preprocess` — Reserved highest priority, used only in special cases.
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum PickerArgAttr {
+ /// Reserved lowest priority, used only in special cases.
+ Postprocess,
+
+ /// Reserved post-processing priority, used only in special cases.
+ Final,
+
/// Positional argument that accepts multiple values (e.g., multiple input files).
PositionalMulti,
@@ -156,6 +203,12 @@ pub enum PickerArgAttr {
/// Accepts multiple values (e.g., `--file a.txt --file b.txt`).
Multi,
+
+ /// Reserved pre-processing priority, used only in special cases.
+ Begin,
+
+ /// Reserved highest priority, used only in special cases.
+ Preprocess,
}
impl PickerArgAttr {
diff --git a/arg_picker/src/builtin.rs b/arg_picker/src/builtin.rs
index e855b08..1c698ba 100644
--- a/arg_picker/src/builtin.rs
+++ b/arg_picker/src/builtin.rs
@@ -1,4 +1,5 @@
mod pick_bool;
mod pick_flag;
mod pick_numbers;
+mod pick_picker_args;
mod pick_string;
diff --git a/arg_picker/src/builtin/pick_picker_args.rs b/arg_picker/src/builtin/pick_picker_args.rs
new file mode 100644
index 0000000..419cbc8
--- /dev/null
+++ b/arg_picker/src/builtin/pick_picker_args.rs
@@ -0,0 +1,21 @@
+use crate::{PickerArgResult::Parsed, PickerArgs, parselib::build_masked_args, pickable_needed::*};
+
+impl<'a> Pickable<'a> for PickerArgs<'a> {
+ fn get_attr(_flag: &'a PickerArg<'a, Self>) -> PickerArgAttr {
+ // Use the lowest priority attribute
+ PickerArgAttr::Postprocess
+ }
+
+ fn tag(ctx: TagPhaseContext) -> Vec<usize> {
+ // Collect all remaining raw index values
+ build_masked_args(ctx.args, ctx.mask)
+ .iter()
+ .map(|m| m.raw_idx)
+ .collect()
+ }
+
+ fn pick(raw_strs: &[&str]) -> PickerArgResult<Self> {
+ let remains: Vec<String> = raw_strs.iter().map(|s| s.to_string()).collect();
+ Parsed(PickerArgs::Owned(remains))
+ }
+}
diff --git a/arg_picker/src/constants.rs b/arg_picker/src/constants.rs
new file mode 100644
index 0000000..39250f8
--- /dev/null
+++ b/arg_picker/src/constants.rs
@@ -0,0 +1,16 @@
+use std::marker::PhantomData;
+
+use crate::{PickerArg, PickerArgs};
+
+/// Remaining positional arguments (anything not consumed as an option).
+/// - `full`: `[]` (empty — not triggered by any `--` prefix).
+/// - `short`: (none)
+/// - `positional`: `false` (this is a meta‑argument that collects everything left).
+/// This constant is used internally to access any leftover arguments after
+/// all defined flags/options have been processed.
+pub const REMAINS: PickerArg<PickerArgs> = PickerArg::<PickerArgs> {
+ full: &[],
+ short: None,
+ positional: false,
+ internal_type: PhantomData,
+};
diff --git a/arg_picker/src/corebind/entry_picker.rs b/arg_picker/src/corebind/entry_picker.rs
deleted file mode 100644
index d543f98..0000000
--- a/arg_picker/src/corebind/entry_picker.rs
+++ /dev/null
@@ -1,131 +0,0 @@
-use std::marker::PhantomData;
-
-use mingling_core::{ChainProcess, Groupped, ProgramCollect};
-
-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`.
-///
-/// This trait provides a bridge between entry definitions created with the `mingling` framework
-/// and the picker argument system used for CLI argument parsing and routing.
-///
-/// # Type Parameters
-///
-/// * `'a` — The lifetime of the picker and its references to argument definitions.
-/// * `This` — The program type used for dispatching runtime routes; must implement [`ProgramCollect`].
-/// * `Route` — The route type used for dispatching; must implement [`Groupped<This>`].
-pub trait EntryPicker<'a, This> {
- /// Converts `self` into a [`Picker`] for the given route type `Route`.
- fn to_picker(self) -> Picker<'a, ChainProcess<This>>;
-
- /// Starts building a picker pattern with the first argument.
- ///
- /// Returns a [`PickerPattern1`] that can be further chained with additional
- /// arguments, defaults, routes, and post-processing.
- ///
- /// # Type Parameters
- ///
- /// * `Next` — The nominal type of the first argument; must implement [`Pickable`].
- ///
- /// # Parameters
- ///
- /// * `arg` — The argument definition, typically obtained from [`crate::macros::arg`].
- fn pick<Next>(
- self,
- arg: impl Into<&'a PickerArg<'a, Next>>,
- ) -> PickerPattern1<'a, Next, ChainProcess<This>>
- where
- Self: Sized,
- Next: Pickable<'a> + Default + Sized,
- {
- let picker = Self::to_picker(self);
- 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::macros::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::macros::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::macros::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)
- }
-}
-
-impl<'a, This, Bind> EntryPicker<'a, This> for Bind
-where
- This: ProgramCollect<Enum = This>,
- Bind: Groupped<This> + Into<Vec<String>>,
-{
- fn to_picker(self) -> Picker<'a, ChainProcess<This>> {
- let args = self.into();
- Picker {
- route_phantom: PhantomData,
- args: PickerArgs::Owned(args),
- }
- }
-}
diff --git a/arg_picker/src/infos.rs b/arg_picker/src/infos.rs
index 074539a..c17b6a2 100644
--- a/arg_picker/src/infos.rs
+++ b/arg_picker/src/infos.rs
@@ -1,4 +1,4 @@
-use crate::{Pickable, PickerArg};
+use crate::{Pickable, PickerArg, parselib::ParserStyle};
/// Represents the result of parsing or looking up a value.
///
@@ -288,28 +288,7 @@ where
T: Pickable<'a>,
{
fn from(value: PickerArg<'a, T>) -> Self {
- let (long, alias) = match value.full.len() {
- 0 => (None, None),
- _ => {
- let long = Some(value.full[0]);
- let alias = if value.full.len() > 1 {
- Some(value.full[1..].to_vec())
- } else {
- None
- };
- (long, alias)
- }
- };
-
- Self {
- short: value.short,
- long,
- alias,
- positional: value.positional,
- optional: false,
- multi: false,
- is_flag: false,
- }
+ value.into_info()
}
}
@@ -437,6 +416,56 @@ impl<'a> PickerArgInfo<'a> {
self.is_flag = is_flag;
self
}
+
+ /// Returns the short flag string, e.g. `-n` for short `n`.
+ ///
+ /// Uses [`ParserStyle::global_style()`] to format the flag.
+ ///
+ /// # Returns
+ ///
+ /// - `Some(String)` if `self.short` is set.
+ /// - `None` if `self.short` is `None`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use arg_picker::PickerArgInfo;
+ ///
+ /// let info = PickerArgInfo::new().with_short('n');
+ /// assert_eq!(info.short_flag(), Some("-n".to_string()));
+ ///
+ /// let info = PickerArgInfo::new();
+ /// assert_eq!(info.short_flag(), None);
+ /// ```
+ pub fn short_flag(&self) -> Option<String> {
+ let short = self.short?;
+ Some(ParserStyle::global_style().flag_string(short))
+ }
+
+ /// Returns the long flag string, e.g. `--name` for long `"name"`.
+ ///
+ /// Uses [`ParserStyle::global_style()`] to format the flag.
+ ///
+ /// # Returns
+ ///
+ /// - `Some(String)` if `self.long` is set.
+ /// - `None` if `self.long` is `None`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use arg_picker::PickerArgInfo;
+ ///
+ /// let info = PickerArgInfo::new().with_long("name");
+ /// assert_eq!(info.long_flag(), Some("--name".to_string()));
+ ///
+ /// let info = PickerArgInfo::new();
+ /// assert_eq!(info.long_flag(), None);
+ /// ```
+ pub fn long_flag(&self) -> Option<String> {
+ let long = self.long?;
+ Some(ParserStyle::global_style().flag_string(long))
+ }
}
impl<'a> Default for PickerArgInfo<'a> {
diff --git a/arg_picker/src/lib.rs b/arg_picker/src/lib.rs
index 21a0d35..285cd16 100644
--- a/arg_picker/src/lib.rs
+++ b/arg_picker/src/lib.rs
@@ -29,13 +29,8 @@ pub mod value;
/// use arg_picker::prelude::*;
/// ```
pub mod prelude {
- pub use crate::macros::arg;
-
- #[cfg(not(feature = "mingling_support"))]
pub use crate::IntoPicker;
-
- #[cfg(feature = "mingling_support")]
- pub use crate::corebind::EntryPicker;
+ pub use crate::macros::arg;
}
/// Re-export of the `arg_picker_macros` crate
@@ -54,9 +49,12 @@ pub mod matcher_needed {
pub use crate::parselib::{MaskedArg, Matcher, ParserStyle};
}
-#[cfg(feature = "mingling_support")]
-mod corebind;
+mod constants;
-#[allow(unused_imports)]
-#[cfg(feature = "mingling_support")]
-pub use corebind::*;
+/// Re-export of constants used by `arg-picker`.
+///
+/// This module provides access to various constants defined internally, such as
+/// default values, configuration limits, and other static parameters.
+pub mod consts {
+ pub use crate::constants::*;
+}
diff --git a/arg_picker/src/parselib.rs b/arg_picker/src/parselib.rs
index 7fbd606..0fcd583 100644
--- a/arg_picker/src/parselib.rs
+++ b/arg_picker/src/parselib.rs
@@ -117,13 +117,32 @@ impl<'a> From<crate::TagPhaseContext<'a>> for MatcherContext<'a> {
}
}
+/// Checks whether the argument at index `idx` is already claimed (masked).
+///
+/// Returns `true` if `idx` is within the mask bounds and the mask value is non-zero,
+/// indicating the argument has been claimed by a previous matcher.
+///
+/// # Arguments
+///
+/// * `mask` - A byte slice where non-zero values indicate claimed arguments.
+/// * `idx` - The index to check in the mask.
#[inline(always)]
-fn is_masked(mask: &[u8], idx: usize) -> bool {
+pub fn is_masked(mask: &[u8], idx: usize) -> bool {
idx < mask.len() && mask[idx] != 0
}
+/// Builds a vector of [`MaskedArg`] from the given `PickerArgs` and mask.
+///
+/// Only arguments whose mask entry is `0` (i.e., available/not yet claimed) are included.
+/// Each resulting [`MaskedArg`] retains its original raw string and its index in the full
+/// argument list for later reference.
+///
+/// # Arguments
+///
+/// * `args` - The full set of parsed arguments.
+/// * `mask` - A byte slice where `0` means available and non-zero means already claimed.
#[inline(always)]
-fn build_masked_args<'a>(args: &'a PickerArgs, mask: &'a [u8]) -> Vec<MaskedArg<'a>> {
+pub fn build_masked_args<'a>(args: &'a PickerArgs, mask: &'a [u8]) -> Vec<MaskedArg<'a>> {
let mut cidx = 0;
args.iter()
.filter_map(|r| {
diff --git a/arg_picker/src/picker.rs b/arg_picker/src/picker.rs
index ecab648..f722fb5 100644
--- a/arg_picker/src/picker.rs
+++ b/arg_picker/src/picker.rs
@@ -73,6 +73,26 @@ pub enum PickerArgs<'a> {
Owned(Vec<String>),
}
+impl<'a> From<PickerArgs<'a>> for Vec<String> {
+ fn from(value: PickerArgs<'a>) -> Self {
+ match value {
+ PickerArgs::Slice(items) => items.iter().map(|s| s.to_string()).collect(),
+ PickerArgs::Vec(items) => items.into_iter().map(|s| s.to_string()).collect(),
+ PickerArgs::Owned(items) => items,
+ }
+ }
+}
+
+impl<'a> From<&'a PickerArgs<'a>> for Vec<&'a str> {
+ fn from(value: &'a PickerArgs<'a>) -> Self {
+ match value {
+ PickerArgs::Slice(items) => items.to_vec(),
+ PickerArgs::Vec(items) => items.clone(),
+ PickerArgs::Owned(items) => items.iter().map(|s| s.as_str()).collect(),
+ }
+ }
+}
+
impl<'a> Default for PickerArgs<'a> {
fn default() -> Self {
Self::Vec(vec![])
@@ -138,6 +158,15 @@ impl<'a> IntoIterator for &'a PickerArgs<'a> {
}
}
+impl<'a, Route> From<PickerArgs<'a>> for Picker<'a, Route> {
+ fn from(args: PickerArgs<'a>) -> Self {
+ Picker {
+ route_phantom: PhantomData,
+ args,
+ }
+ }
+}
+
impl<'a, Route> From<&'a [&'a str]> for Picker<'a, Route> {
fn from(value: &'a [&'a str]) -> Self {
Picker {
@@ -340,11 +369,83 @@ pub trait IntoPicker<'a> {
fn pick<N>(self, arg: impl Into<&'a PickerArg<'a, N>>) -> PickerPattern1<'a, N, ()>
where
Self: Sized,
- N: Pickable<'a> + Default + Sized,
+ N: Pickable<'a> + Sized,
{
Picker::build_pattern1(self.to_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::macros::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, ()>
+ where
+ Self: Sized,
+ Next: Pickable<'a> + 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::macros::arg`].
+ fn pick_or_default<Next>(
+ self,
+ arg: impl Into<&'a PickerArg<'a, Next>>,
+ ) -> PickerPattern1<'a, Next, ()>
+ 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::macros::arg`].
+ /// * `func` — A closure that produces a route value if the arg is not provided by the user.
+ fn pick_or_route<Next, F, Route>(
+ self,
+ arg: impl Into<&'a PickerArg<'a, Next>>,
+ func: F,
+ ) -> PickerPattern1<'a, Next, Route>
+ where
+ Self: Sized,
+ Next: Pickable<'a> + Sized,
+ F: FnMut() -> Route + 'static,
+ {
+ self.pick(arg).with_route::<Route>().or_route(func)
+ }
+
/// Converts the value into a `Picker` with a specified route type.
///
/// This method allows changing the route (phantom type parameter) of the picker.
@@ -408,10 +509,9 @@ 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>(
+ /// Build the PickerPattern via Arguments
+ pub fn build_pattern1<N>(
args: PickerArgs<'a>,
arg: &'a PickerArg<'a, N>,
error_route: Option<Route>,
diff --git a/arg_picker/src/picker/parse.rs b/arg_picker/src/picker/parse.rs
index 366028b..9db5bd9 100644
--- a/arg_picker/src/picker/parse.rs
+++ b/arg_picker/src/picker/parse.rs
@@ -21,14 +21,16 @@ internal_repeat!(1..=32 => {
internal_repeat!(1..=32 => {
impl<'a, (T$,+), Route> PickerPattern$<'a, (T$,+), Route>
where (T$: Pickable<'a>,+) {
- /// Unwraps the result, panicking if a route was selected.
+ /// Unwraps the result, panicking if a route was selected or a required
+ /// value is missing.
///
/// # Panics
///
- /// Panics if a route was selected.
+ /// Panics if a route was selected, or if a required argument was not
+ /// provided by the user.
pub fn unwrap(self) -> ((T$,+)) {
let p = self.parse();
- ((p.v$.unwrap(),+))
+ ((p.v$.expect(concat!("missing required argument at position ", $)),+))
}
/// Returns the individual option values without checking the route.
diff --git a/arg_picker/src/picker/result.rs b/arg_picker/src/picker/result.rs
index 83ca2cd..2099825 100644
--- a/arg_picker/src/picker/result.rs
+++ b/arg_picker/src/picker/result.rs
@@ -21,13 +21,15 @@ internal_repeat!(1..=32 => {
internal_repeat!(1..=32 => {
impl<(T$,+), Route> PickerResult$<(T$,+), Route> {
- /// Unwraps the result, panicking if a route was selected.
+ /// Unwraps the result, panicking if a route was selected or a required
+ /// value is missing.
///
/// # Panics
///
- /// Panics if `self.route` is `Some(...)`.
+ /// Panics if `self.route` is `Some(...)`, or if a required argument was
+ /// not provided by the user.
pub fn unwrap(self) -> ((T$,+)) {
- ((self.v$.unwrap(),+))
+ ((self.v$.expect(concat!("missing required argument at position ", $)),+))
}
/// Returns the individual option values without checking the route.
diff --git a/arg_picker/test/src/test/route_test.rs b/arg_picker/test/src/test/route_test.rs
index 7594c6e..c9cd5ab 100644
--- a/arg_picker/test/src/test/route_test.rs
+++ b/arg_picker/test/src/test/route_test.rs
@@ -1,4 +1,4 @@
-use arg_picker::{macros::arg, IntoPicker};
+use arg_picker::{IntoPicker, macros::arg};
// Route mechanism — or_route
@@ -53,7 +53,7 @@ fn test_or_route_to_option_returns_none() {
}
#[test]
-#[should_panic(expected = "called `Option::unwrap()` on a `None` value")]
+#[should_panic(expected = "missing required argument")]
fn test_or_route_unwrap_panics() {
let args: Vec<&str> = vec![];
args.with_route::<&'static str>()