//! This module contains traits that are usable with the `#[derive(...)]` //! macros in `clap_derive`. use crate::builder::PossibleValue; use crate::{ArgMatches, Command, Error}; use std::ffi::OsString; /// Parse command-line arguments into `Self`. /// /// The primary one-stop-shop trait used to create an instance of a `clap` /// [`Command`], conduct the parsing, and turn the resulting [`ArgMatches`] back /// into concrete instance of the user struct. /// /// This trait is primarily a convenience on top of [`FromArgMatches`] + /// [`CommandFactory`] which uses those two underlying traits to build the two /// fundamental functions `parse` which uses the `std::env::args_os` iterator, /// and `parse_from` which allows the consumer to supply the iterator (along /// with fallible options for each). /// /// See also [`Subcommand`] and [`Args`]. /// /// **NOTE:** Deriving requires the `derive` feature flag pub trait Parser: FromArgMatches + CommandFactory + Sized { /// Parse from `std::env::args_os()`, exit on error fn parse() -> Self { let mut matches = ::command().get_matches(); let res = ::from_arg_matches_mut(&mut matches) .map_err(format_error::); match res { Ok(s) => s, Err(e) => { // Since this is more of a development-time error, we aren't doing as fancy of a quit // as `get_matches` e.exit() } } } /// Parse from `std::env::args_os()`, return Err on error. fn try_parse() -> Result { let mut matches = ok!(::command().try_get_matches()); ::from_arg_matches_mut(&mut matches).map_err(format_error::) } /// Parse from iterator, exit on error fn parse_from(itr: I) -> Self where I: IntoIterator, T: Into + Clone, { let mut matches = ::command().get_matches_from(itr); let res = ::from_arg_matches_mut(&mut matches) .map_err(format_error::); match res { Ok(s) => s, Err(e) => { // Since this is more of a development-time error, we aren't doing as fancy of a quit // as `get_matches_from` e.exit() } } } /// Parse from iterator, return Err on error. fn try_parse_from(itr: I) -> Result where I: IntoIterator, T: Into + Clone, { let mut matches = ok!(::command().try_get_matches_from(itr)); ::from_arg_matches_mut(&mut matches).map_err(format_error::) } /// Update from iterator, exit on error fn update_from(&mut self, itr: I) where I: IntoIterator, T: Into + Clone, { let mut matches = ::command_for_update().get_matches_from(itr); let res = ::update_from_arg_matches_mut(self, &mut matches) .map_err(format_error::); if let Err(e) = res { // Since this is more of a development-time error, we aren't doing as fancy of a quit // as `get_matches_from` e.exit() } } /// Update from iterator, return Err on error. fn try_update_from(&mut self, itr: I) -> Result<(), Error> where I: IntoIterator, T: Into + Clone, { let mut matches = ok!(::command_for_update().try_get_matches_from(itr)); ::update_from_arg_matches_mut(self, &mut matches) .map_err(format_error::) } } /// Create a [`Command`] relevant for a user-defined container. /// /// Derived as part of [`Parser`]. pub trait CommandFactory: Sized { /// Build a [`Command`] that can instantiate `Self`. /// /// See [`FromArgMatches::from_arg_matches_mut`] for instantiating `Self`. fn command() -> Command; /// Build a [`Command`] that can update `self`. /// /// See [`FromArgMatches::update_from_arg_matches_mut`] for updating `self`. fn command_for_update() -> Command; } /// Converts an instance of [`ArgMatches`] to a user-defined container. /// /// Derived as part of [`Parser`], [`Args`], and [`Subcommand`]. pub trait FromArgMatches: Sized { /// Instantiate `Self` from [`ArgMatches`], parsing the arguments as needed. /// /// Motivation: If our application had two CLI options, `--name /// ` and the flag `--debug`, we may create a struct as follows: /// /// ```rust /// # #[cfg(feature = "derive")] { /// struct Context { /// name: String, /// debug: bool /// } /// # } /// ``` /// /// We then need to convert the `ArgMatches` that `clap` generated into our struct. /// `from_arg_matches` serves as the equivalent of: /// /// ```rust /// # #[cfg(feature = "derive")] { /// # use clap::ArgMatches; /// # struct Context { /// # name: String, /// # debug: bool /// # } /// impl From for Context { /// fn from(m: ArgMatches) -> Self { /// Context { /// name: m.get_one::("name").unwrap().clone(), /// debug: m.get_flag("debug"), /// } /// } /// } /// # } /// ``` fn from_arg_matches(matches: &ArgMatches) -> Result; /// Instantiate `Self` from [`ArgMatches`], parsing the arguments as needed. /// /// Motivation: If our application had two CLI options, `--name /// ` and the flag `--debug`, we may create a struct as follows: /// /// ```rust /// # #[cfg(feature = "derive")] { /// struct Context { /// name: String, /// debug: bool /// } /// # } /// ``` /// /// We then need to convert the `ArgMatches` that `clap` generated into our struct. /// `from_arg_matches_mut` serves as the equivalent of: /// /// ```rust /// # #[cfg(feature = "derive")] { /// # use clap::ArgMatches; /// # struct Context { /// # name: String, /// # debug: bool /// # } /// impl From for Context { /// fn from(m: ArgMatches) -> Self { /// Context { /// name: m.get_one::("name").unwrap().to_string(), /// debug: m.get_flag("debug"), /// } /// } /// } /// # } /// ``` fn from_arg_matches_mut(matches: &mut ArgMatches) -> Result { Self::from_arg_matches(matches) } /// Assign values from `ArgMatches` to `self`. fn update_from_arg_matches(&mut self, matches: &ArgMatches) -> Result<(), Error>; /// Assign values from `ArgMatches` to `self`. fn update_from_arg_matches_mut(&mut self, matches: &mut ArgMatches) -> Result<(), Error> { self.update_from_arg_matches(matches) } } /// Parse a set of arguments into a user-defined container. /// /// Implementing this trait lets a parent container delegate argument parsing behavior to `Self`. /// with: /// - `#[command(flatten)] args: ChildArgs`: Attribute can only be used with struct fields that impl /// `Args`. /// - `Variant(ChildArgs)`: No attribute is used with enum variants that impl `Args`. /// /// **NOTE:** Deriving requires the `derive` feature flag pub trait Args: FromArgMatches + Sized { /// Report the [`ArgGroup::id`][crate::ArgGroup::id] for this set of arguments fn group_id() -> Option { None } /// Append to [`Command`] so it can instantiate `Self`. /// /// See also [`CommandFactory`]. fn augment_args(cmd: Command) -> Command; /// Append to [`Command`] so it can update `self`. /// /// This is used to implement `#[command(flatten)]` /// /// See also [`CommandFactory`]. fn augment_args_for_update(cmd: Command) -> Command; } /// Parse a sub-command into a user-defined enum. /// /// Implementing this trait lets a parent container delegate subcommand behavior to `Self`. /// with: /// - `#[command(subcommand)] field: SubCmd`: Attribute can be used with either struct fields or enum /// variants that impl `Subcommand`. /// - `#[command(flatten)] Variant(SubCmd)`: Attribute can only be used with enum variants that impl /// `Subcommand`. /// /// **NOTE:** Deriving requires the `derive` feature flag pub trait Subcommand: FromArgMatches + Sized { /// Append to [`Command`] so it can instantiate `Self`. /// /// See also [`CommandFactory`]. fn augment_subcommands(cmd: Command) -> Command; /// Append to [`Command`] so it can update `self`. /// /// This is used to implement `#[command(flatten)]` /// /// See also [`CommandFactory`]. fn augment_subcommands_for_update(cmd: Command) -> Command; /// Test whether `Self` can parse a specific subcommand fn has_subcommand(name: &str) -> bool; } /// Parse arguments into enums. /// /// When deriving [`Parser`], a field whose type implements `ValueEnum` can have the attribute /// `#[arg(value_enum)]` which will /// - Call [`EnumValueParser`][crate::builder::EnumValueParser] /// - Allowing using the `#[arg(default_value_t)]` attribute without implementing `Display`. /// /// **NOTE:** Deriving requires the `derive` feature flag pub trait ValueEnum: Sized + Clone { /// All possible argument values, in display order. fn value_variants<'a>() -> &'a [Self]; /// Parse an argument into `Self`. fn from_str(input: &str, ignore_case: bool) -> Result { Self::value_variants() .iter() .find(|v| { v.to_possible_value() .expect("ValueEnum::value_variants contains only values with a corresponding ValueEnum::to_possible_value") .matches(input, ignore_case) }) .cloned() .ok_or_else(|| format!("invalid variant: {input}")) } /// The canonical argument value. /// /// The value is `None` for skipped variants. fn to_possible_value(&self) -> Option; } impl Parser for Box { fn parse() -> Self { Box::new(::parse()) } fn try_parse() -> Result { ::try_parse().map(Box::new) } fn parse_from(itr: I) -> Self where I: IntoIterator, It: Into + Clone, { Box::new(::parse_from(itr)) } fn try_parse_from(itr: I) -> Result where I: IntoIterator, It: Into + Clone, { ::try_parse_from(itr).map(Box::new) } } impl CommandFactory for Box { fn command<'help>() -> Command { ::command() } fn command_for_update<'help>() -> Command { ::command_for_update() } } impl FromArgMatches for Box { fn from_arg_matches(matches: &ArgMatches) -> Result { ::from_arg_matches(matches).map(Box::new) } fn from_arg_matches_mut(matches: &mut ArgMatches) -> Result { ::from_arg_matches_mut(matches).map(Box::new) } fn update_from_arg_matches(&mut self, matches: &ArgMatches) -> Result<(), Error> { ::update_from_arg_matches(self, matches) } fn update_from_arg_matches_mut(&mut self, matches: &mut ArgMatches) -> Result<(), Error> { ::update_from_arg_matches_mut(self, matches) } } impl Args for Box { fn augment_args(cmd: Command) -> Command { ::augment_args(cmd) } fn augment_args_for_update(cmd: Command) -> Command { ::augment_args_for_update(cmd) } } impl Subcommand for Box { fn augment_subcommands(cmd: Command) -> Command { ::augment_subcommands(cmd) } fn augment_subcommands_for_update(cmd: Command) -> Command { ::augment_subcommands_for_update(cmd) } fn has_subcommand(name: &str) -> bool { ::has_subcommand(name) } } fn format_error(err: crate::Error) -> crate::Error { let mut cmd = I::command(); err.format(&mut cmd) }