1//! This module contains traits that are usable with the `#[derive(...)].` 2//! macros in [`clap_derive`]. 3 4use crate::builder::PossibleValue; 5use crate::{ArgMatches, Command, Error}; 6 7use std::ffi::OsString; 8 9/// Parse command-line arguments into `Self`. 10/// 11/// The primary one-stop-shop trait used to create an instance of a `clap` 12/// [`Command`], conduct the parsing, and turn the resulting [`ArgMatches`] back 13/// into concrete instance of the user struct. 14/// 15/// This trait is primarily a convenience on top of [`FromArgMatches`] + 16/// [`CommandFactory`] which uses those two underlying traits to build the two 17/// fundamental functions `parse` which uses the `std::env::args_os` iterator, 18/// and `parse_from` which allows the consumer to supply the iterator (along 19/// with fallible options for each). 20/// 21/// See also [`Subcommand`] and [`Args`]. 22/// 23/// See the [derive reference](crate::_derive) for attributes and best practices. 24/// 25/// **NOTE:** Deriving requires the [`derive` feature flag][crate::_features] 26/// 27/// # Examples 28/// 29/// The following example creates a `Context` struct that would be used 30/// throughout the application representing the normalized values coming from 31/// the CLI. 32/// 33#[cfg_attr(not(feature = "derive"), doc = " ```ignore")] 34#[cfg_attr(feature = "derive", doc = " ```")] 35/// /// My super CLI 36/// #[derive(clap::Parser)] 37/// #[command(name = "demo")] 38/// struct Context { 39/// /// More verbose output 40/// #[arg(long)] 41/// verbose: bool, 42/// /// An optional name 43/// #[arg(short, long)] 44/// name: Option<String>, 45/// } 46/// ``` 47/// 48/// The equivalent [`Command`] struct + `From` implementation: 49/// 50/// ```rust 51/// # use clap::{Command, Arg, ArgMatches, ArgAction}; 52/// Command::new("demo") 53/// .about("My super CLI") 54/// .arg(Arg::new("verbose") 55/// .long("verbose") 56/// .action(ArgAction::SetTrue) 57/// .help("More verbose output")) 58/// .arg(Arg::new("name") 59/// .long("name") 60/// .short('n') 61/// .help("An optional name") 62/// .action(ArgAction::Set)); 63/// 64/// struct Context { 65/// verbose: bool, 66/// name: Option<String>, 67/// } 68/// 69/// impl From<ArgMatches> for Context { 70/// fn from(m: ArgMatches) -> Self { 71/// Context { 72/// verbose: m.get_flag("verbose"), 73/// name: m.get_one::<String>("name").cloned(), 74/// } 75/// } 76/// } 77/// ``` 78/// 79pub trait Parser: FromArgMatches + CommandFactory + Sized { 80 /// Parse from `std::env::args_os()`, exit on error 81 fn parse() -> Self { 82 let mut matches = <Self as CommandFactory>::command().get_matches(); 83 let res = <Self as FromArgMatches>::from_arg_matches_mut(&mut matches) 84 .map_err(format_error::<Self>); 85 match res { 86 Ok(s) => s, 87 Err(e) => { 88 // Since this is more of a development-time error, we aren't doing as fancy of a quit 89 // as `get_matches` 90 e.exit() 91 } 92 } 93 } 94 95 /// Parse from `std::env::args_os()`, return Err on error. 96 fn try_parse() -> Result<Self, Error> { 97 let mut matches = ok!(<Self as CommandFactory>::command().try_get_matches()); 98 <Self as FromArgMatches>::from_arg_matches_mut(&mut matches).map_err(format_error::<Self>) 99 } 100 101 /// Parse from iterator, exit on error 102 fn parse_from<I, T>(itr: I) -> Self 103 where 104 I: IntoIterator<Item = T>, 105 T: Into<OsString> + Clone, 106 { 107 let mut matches = <Self as CommandFactory>::command().get_matches_from(itr); 108 let res = <Self as FromArgMatches>::from_arg_matches_mut(&mut matches) 109 .map_err(format_error::<Self>); 110 match res { 111 Ok(s) => s, 112 Err(e) => { 113 // Since this is more of a development-time error, we aren't doing as fancy of a quit 114 // as `get_matches_from` 115 e.exit() 116 } 117 } 118 } 119 120 /// Parse from iterator, return Err on error. 121 fn try_parse_from<I, T>(itr: I) -> Result<Self, Error> 122 where 123 I: IntoIterator<Item = T>, 124 T: Into<OsString> + Clone, 125 { 126 let mut matches = ok!(<Self as CommandFactory>::command().try_get_matches_from(itr)); 127 <Self as FromArgMatches>::from_arg_matches_mut(&mut matches).map_err(format_error::<Self>) 128 } 129 130 /// Update from iterator, exit on error 131 fn update_from<I, T>(&mut self, itr: I) 132 where 133 I: IntoIterator<Item = T>, 134 T: Into<OsString> + Clone, 135 { 136 let mut matches = <Self as CommandFactory>::command_for_update().get_matches_from(itr); 137 let res = <Self as FromArgMatches>::update_from_arg_matches_mut(self, &mut matches) 138 .map_err(format_error::<Self>); 139 if let Err(e) = res { 140 // Since this is more of a development-time error, we aren't doing as fancy of a quit 141 // as `get_matches_from` 142 e.exit() 143 } 144 } 145 146 /// Update from iterator, return Err on error. 147 fn try_update_from<I, T>(&mut self, itr: I) -> Result<(), Error> 148 where 149 I: IntoIterator<Item = T>, 150 T: Into<OsString> + Clone, 151 { 152 let mut matches = 153 ok!(<Self as CommandFactory>::command_for_update().try_get_matches_from(itr)); 154 <Self as FromArgMatches>::update_from_arg_matches_mut(self, &mut matches) 155 .map_err(format_error::<Self>) 156 } 157} 158 159/// Create a [`Command`] relevant for a user-defined container. 160/// 161/// Derived as part of [`Parser`]. 162pub trait CommandFactory: Sized { 163 /// Build a [`Command`] that can instantiate `Self`. 164 /// 165 /// See [`FromArgMatches::from_arg_matches_mut`] for instantiating `Self`. 166 fn command() -> Command; 167 /// Build a [`Command`] that can update `self`. 168 /// 169 /// See [`FromArgMatches::update_from_arg_matches_mut`] for updating `self`. 170 fn command_for_update() -> Command; 171} 172 173/// Converts an instance of [`ArgMatches`] to a user-defined container. 174/// 175/// Derived as part of [`Parser`], [`Args`], and [`Subcommand`]. 176pub trait FromArgMatches: Sized { 177 /// Instantiate `Self` from [`ArgMatches`], parsing the arguments as needed. 178 /// 179 /// Motivation: If our application had two CLI options, `--name 180 /// <STRING>` and the flag `--debug`, we may create a struct as follows: 181 /// 182 #[cfg_attr(not(feature = "derive"), doc = " ```ignore")] 183 #[cfg_attr(feature = "derive", doc = " ```no_run")] 184 /// struct Context { 185 /// name: String, 186 /// debug: bool 187 /// } 188 /// ``` 189 /// 190 /// We then need to convert the `ArgMatches` that `clap` generated into our struct. 191 /// `from_arg_matches` serves as the equivalent of: 192 /// 193 #[cfg_attr(not(feature = "derive"), doc = " ```ignore")] 194 #[cfg_attr(feature = "derive", doc = " ```no_run")] 195 /// # use clap::ArgMatches; 196 /// # struct Context { 197 /// # name: String, 198 /// # debug: bool 199 /// # } 200 /// impl From<ArgMatches> for Context { 201 /// fn from(m: ArgMatches) -> Self { 202 /// Context { 203 /// name: m.get_one::<String>("name").unwrap().clone(), 204 /// debug: m.get_flag("debug"), 205 /// } 206 /// } 207 /// } 208 /// ``` 209 fn from_arg_matches(matches: &ArgMatches) -> Result<Self, Error>; 210 211 /// Instantiate `Self` from [`ArgMatches`], parsing the arguments as needed. 212 /// 213 /// Motivation: If our application had two CLI options, `--name 214 /// <STRING>` and the flag `--debug`, we may create a struct as follows: 215 /// 216 #[cfg_attr(not(feature = "derive"), doc = " ```ignore")] 217 #[cfg_attr(feature = "derive", doc = " ```no_run")] 218 /// struct Context { 219 /// name: String, 220 /// debug: bool 221 /// } 222 /// ``` 223 /// 224 /// We then need to convert the `ArgMatches` that `clap` generated into our struct. 225 /// `from_arg_matches_mut` serves as the equivalent of: 226 /// 227 #[cfg_attr(not(feature = "derive"), doc = " ```ignore")] 228 #[cfg_attr(feature = "derive", doc = " ```no_run")] 229 /// # use clap::ArgMatches; 230 /// # struct Context { 231 /// # name: String, 232 /// # debug: bool 233 /// # } 234 /// impl From<ArgMatches> for Context { 235 /// fn from(m: ArgMatches) -> Self { 236 /// Context { 237 /// name: m.get_one::<String>("name").unwrap().to_string(), 238 /// debug: m.get_flag("debug"), 239 /// } 240 /// } 241 /// } 242 /// ``` 243 fn from_arg_matches_mut(matches: &mut ArgMatches) -> Result<Self, Error> { 244 Self::from_arg_matches(matches) 245 } 246 247 /// Assign values from `ArgMatches` to `self`. 248 fn update_from_arg_matches(&mut self, matches: &ArgMatches) -> Result<(), Error>; 249 250 /// Assign values from `ArgMatches` to `self`. 251 fn update_from_arg_matches_mut(&mut self, matches: &mut ArgMatches) -> Result<(), Error> { 252 self.update_from_arg_matches(matches) 253 } 254} 255 256/// Parse a set of arguments into a user-defined container. 257/// 258/// Implementing this trait lets a parent container delegate argument parsing behavior to `Self`. 259/// with: 260/// - `#[command(flatten)] args: ChildArgs`: Attribute can only be used with struct fields that impl 261/// `Args`. 262/// - `Variant(ChildArgs)`: No attribute is used with enum variants that impl `Args`. 263/// 264/// See the [derive reference](crate::_derive) for attributes and best practices. 265/// 266/// **NOTE:** Deriving requires the [`derive` feature flag][crate::_features] 267/// 268/// # Example 269/// 270#[cfg_attr(not(feature = "derive"), doc = " ```ignore")] 271#[cfg_attr(feature = "derive", doc = " ```")] 272/// #[derive(clap::Parser)] 273/// struct Args { 274/// #[command(flatten)] 275/// logging: LogArgs, 276/// } 277/// 278/// #[derive(clap::Args)] 279/// struct LogArgs { 280/// #[arg(long, short = 'v', action = clap::ArgAction::Count)] 281/// verbose: u8, 282/// } 283/// ``` 284pub trait Args: FromArgMatches + Sized { 285 /// Report the [`ArgGroup::id`][crate::ArgGroup::id] for this set of arguments 286 fn group_id() -> Option<crate::Id> { 287 None 288 } 289 /// Append to [`Command`] so it can instantiate `Self`. 290 /// 291 /// See also [`CommandFactory`]. 292 fn augment_args(cmd: Command) -> Command; 293 /// Append to [`Command`] so it can update `self`. 294 /// 295 /// This is used to implement `#[command(flatten)]` 296 /// 297 /// See also [`CommandFactory`]. 298 fn augment_args_for_update(cmd: Command) -> Command; 299} 300 301/// Parse a sub-command into a user-defined enum. 302/// 303/// Implementing this trait lets a parent container delegate subcommand behavior to `Self`. 304/// with: 305/// - `#[command(subcommand)] field: SubCmd`: Attribute can be used with either struct fields or enum 306/// variants that impl `Subcommand`. 307/// - `#[command(flatten)] Variant(SubCmd)`: Attribute can only be used with enum variants that impl 308/// `Subcommand`. 309/// 310/// See the [derive reference](crate::_derive) for attributes and best practices. 311/// 312/// **NOTE:** Deriving requires the [`derive` feature flag][crate::_features] 313/// 314/// # Example 315/// 316#[cfg_attr(not(feature = "derive"), doc = " ```ignore")] 317#[cfg_attr(feature = "derive", doc = " ```")] 318/// #[derive(clap::Parser)] 319/// struct Args { 320/// #[command(subcommand)] 321/// action: Action, 322/// } 323/// 324/// #[derive(clap::Subcommand)] 325/// enum Action { 326/// Add, 327/// Remove, 328/// } 329/// ``` 330pub trait Subcommand: FromArgMatches + Sized { 331 /// Append to [`Command`] so it can instantiate `Self`. 332 /// 333 /// See also [`CommandFactory`]. 334 fn augment_subcommands(cmd: Command) -> Command; 335 /// Append to [`Command`] so it can update `self`. 336 /// 337 /// This is used to implement `#[command(flatten)]` 338 /// 339 /// See also [`CommandFactory`]. 340 fn augment_subcommands_for_update(cmd: Command) -> Command; 341 /// Test whether `Self` can parse a specific subcommand 342 fn has_subcommand(name: &str) -> bool; 343} 344 345/// Parse arguments into enums. 346/// 347/// When deriving [`Parser`], a field whose type implements `ValueEnum` can have the attribute 348/// `#[arg(value_enum)]` which will 349/// - Call [`EnumValueParser`][crate::builder::EnumValueParser] 350/// - Allowing using the `#[arg(default_value_t)]` attribute without implementing `Display`. 351/// 352/// See the [derive reference](crate::_derive) for attributes and best practices. 353/// 354/// **NOTE:** Deriving requires the [`derive` feature flag][crate::_features] 355/// 356/// # Example 357/// 358#[cfg_attr(not(feature = "derive"), doc = " ```ignore")] 359#[cfg_attr(feature = "derive", doc = " ```")] 360/// #[derive(clap::Parser)] 361/// struct Args { 362/// #[arg(value_enum)] 363/// level: Level, 364/// } 365/// 366/// #[derive(clap::ValueEnum, Clone)] 367/// enum Level { 368/// Debug, 369/// Info, 370/// Warning, 371/// Error, 372/// } 373/// ``` 374pub trait ValueEnum: Sized + Clone { 375 /// All possible argument values, in display order. 376 fn value_variants<'a>() -> &'a [Self]; 377 378 /// Parse an argument into `Self`. 379 fn from_str(input: &str, ignore_case: bool) -> Result<Self, String> { 380 Self::value_variants() 381 .iter() 382 .find(|v| { 383 v.to_possible_value() 384 .expect("ValueEnum::value_variants contains only values with a corresponding ValueEnum::to_possible_value") 385 .matches(input, ignore_case) 386 }) 387 .cloned() 388 .ok_or_else(|| format!("invalid variant: {input}")) 389 } 390 391 /// The canonical argument value. 392 /// 393 /// The value is `None` for skipped variants. 394 fn to_possible_value(&self) -> Option<PossibleValue>; 395} 396 397impl<T: Parser> Parser for Box<T> { 398 fn parse() -> Self { 399 Box::new(<T as Parser>::parse()) 400 } 401 402 fn try_parse() -> Result<Self, Error> { 403 <T as Parser>::try_parse().map(Box::new) 404 } 405 406 fn parse_from<I, It>(itr: I) -> Self 407 where 408 I: IntoIterator<Item = It>, 409 It: Into<OsString> + Clone, 410 { 411 Box::new(<T as Parser>::parse_from(itr)) 412 } 413 414 fn try_parse_from<I, It>(itr: I) -> Result<Self, Error> 415 where 416 I: IntoIterator<Item = It>, 417 It: Into<OsString> + Clone, 418 { 419 <T as Parser>::try_parse_from(itr).map(Box::new) 420 } 421} 422 423impl<T: CommandFactory> CommandFactory for Box<T> { 424 fn command<'help>() -> Command { 425 <T as CommandFactory>::command() 426 } 427 fn command_for_update<'help>() -> Command { 428 <T as CommandFactory>::command_for_update() 429 } 430} 431 432impl<T: FromArgMatches> FromArgMatches for Box<T> { 433 fn from_arg_matches(matches: &ArgMatches) -> Result<Self, Error> { 434 <T as FromArgMatches>::from_arg_matches(matches).map(Box::new) 435 } 436 fn from_arg_matches_mut(matches: &mut ArgMatches) -> Result<Self, Error> { 437 <T as FromArgMatches>::from_arg_matches_mut(matches).map(Box::new) 438 } 439 fn update_from_arg_matches(&mut self, matches: &ArgMatches) -> Result<(), Error> { 440 <T as FromArgMatches>::update_from_arg_matches(self, matches) 441 } 442 fn update_from_arg_matches_mut(&mut self, matches: &mut ArgMatches) -> Result<(), Error> { 443 <T as FromArgMatches>::update_from_arg_matches_mut(self, matches) 444 } 445} 446 447impl<T: Args> Args for Box<T> { 448 fn augment_args(cmd: Command) -> Command { 449 <T as Args>::augment_args(cmd) 450 } 451 fn augment_args_for_update(cmd: Command) -> Command { 452 <T as Args>::augment_args_for_update(cmd) 453 } 454} 455 456impl<T: Subcommand> Subcommand for Box<T> { 457 fn augment_subcommands(cmd: Command) -> Command { 458 <T as Subcommand>::augment_subcommands(cmd) 459 } 460 fn augment_subcommands_for_update(cmd: Command) -> Command { 461 <T as Subcommand>::augment_subcommands_for_update(cmd) 462 } 463 fn has_subcommand(name: &str) -> bool { 464 <T as Subcommand>::has_subcommand(name) 465 } 466} 467 468fn format_error<I: CommandFactory>(err: crate::Error) -> crate::Error { 469 let mut cmd = I::command(); 470 err.format(&mut cmd) 471} 472