• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! This module contains traits that are usable with the `#[derive(...)].`
2 //! macros in [`clap_derive`].
3 
4 use crate::builder::PossibleValue;
5 use crate::{ArgMatches, Command, Error};
6 
7 use 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 ///
79 pub trait Parser: FromArgMatches + CommandFactory + Sized {
80     /// Parse from `std::env::args_os()`, exit on error
parse() -> Self81     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.
try_parse() -> Result<Self, 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
parse_from<I, T>(itr: I) -> Self where I: IntoIterator<Item = T>, T: Into<OsString> + Clone,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.
try_parse_from<I, T>(itr: I) -> Result<Self, Error> where I: IntoIterator<Item = T>, T: Into<OsString> + Clone,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
update_from<I, T>(&mut self, itr: I) where I: IntoIterator<Item = T>, T: Into<OsString> + Clone,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.
try_update_from<I, T>(&mut self, itr: I) -> Result<(), Error> where I: IntoIterator<Item = T>, T: Into<OsString> + Clone,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`].
162 pub trait CommandFactory: Sized {
163     /// Build a [`Command`] that can instantiate `Self`.
164     ///
165     /// See [`FromArgMatches::from_arg_matches_mut`] for instantiating `Self`.
command() -> Command166     fn command() -> Command;
167     /// Build a [`Command`] that can update `self`.
168     ///
169     /// See [`FromArgMatches::update_from_arg_matches_mut`] for updating `self`.
command_for_update() -> Command170     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`].
176 pub 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     /// ```
from_arg_matches(matches: &ArgMatches) -> Result<Self, Error>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     /// ```
from_arg_matches_mut(matches: &mut ArgMatches) -> Result<Self, Error>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`.
update_from_arg_matches(&mut self, matches: &ArgMatches) -> Result<(), Error>248     fn update_from_arg_matches(&mut self, matches: &ArgMatches) -> Result<(), Error>;
249 
250     /// Assign values from `ArgMatches` to `self`.
update_from_arg_matches_mut(&mut self, matches: &mut ArgMatches) -> Result<(), Error>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 /// ```
284 pub trait Args: FromArgMatches + Sized {
285     /// Report the [`ArgGroup::id`][crate::ArgGroup::id] for this set of arguments
group_id() -> Option<crate::Id>286     fn group_id() -> Option<crate::Id> {
287         None
288     }
289     /// Append to [`Command`] so it can instantiate `Self`.
290     ///
291     /// See also [`CommandFactory`].
augment_args(cmd: Command) -> Command292     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`].
augment_args_for_update(cmd: Command) -> Command298     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 /// ```
330 pub trait Subcommand: FromArgMatches + Sized {
331     /// Append to [`Command`] so it can instantiate `Self`.
332     ///
333     /// See also [`CommandFactory`].
augment_subcommands(cmd: Command) -> Command334     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`].
augment_subcommands_for_update(cmd: Command) -> Command340     fn augment_subcommands_for_update(cmd: Command) -> Command;
341     /// Test whether `Self` can parse a specific subcommand
has_subcommand(name: &str) -> bool342     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 /// ```
374 pub trait ValueEnum: Sized + Clone {
375     /// All possible argument values, in display order.
value_variants<'a>() -> &'a [Self]376     fn value_variants<'a>() -> &'a [Self];
377 
378     /// Parse an argument into `Self`.
from_str(input: &str, ignore_case: bool) -> Result<Self, String>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.
to_possible_value(&self) -> Option<PossibleValue>394     fn to_possible_value(&self) -> Option<PossibleValue>;
395 }
396 
397 impl<T: Parser> Parser for Box<T> {
parse() -> Self398     fn parse() -> Self {
399         Box::new(<T as Parser>::parse())
400     }
401 
try_parse() -> Result<Self, Error>402     fn try_parse() -> Result<Self, Error> {
403         <T as Parser>::try_parse().map(Box::new)
404     }
405 
parse_from<I, It>(itr: I) -> Self where I: IntoIterator<Item = It>, It: Into<OsString> + Clone,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 
try_parse_from<I, It>(itr: I) -> Result<Self, Error> where I: IntoIterator<Item = It>, It: Into<OsString> + Clone,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 
423 impl<T: CommandFactory> CommandFactory for Box<T> {
command<'help>() -> Command424     fn command<'help>() -> Command {
425         <T as CommandFactory>::command()
426     }
command_for_update<'help>() -> Command427     fn command_for_update<'help>() -> Command {
428         <T as CommandFactory>::command_for_update()
429     }
430 }
431 
432 impl<T: FromArgMatches> FromArgMatches for Box<T> {
from_arg_matches(matches: &ArgMatches) -> Result<Self, Error>433     fn from_arg_matches(matches: &ArgMatches) -> Result<Self, Error> {
434         <T as FromArgMatches>::from_arg_matches(matches).map(Box::new)
435     }
from_arg_matches_mut(matches: &mut ArgMatches) -> Result<Self, Error>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     }
update_from_arg_matches(&mut self, matches: &ArgMatches) -> Result<(), Error>439     fn update_from_arg_matches(&mut self, matches: &ArgMatches) -> Result<(), Error> {
440         <T as FromArgMatches>::update_from_arg_matches(self, matches)
441     }
update_from_arg_matches_mut(&mut self, matches: &mut ArgMatches) -> Result<(), Error>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 
447 impl<T: Args> Args for Box<T> {
augment_args(cmd: Command) -> Command448     fn augment_args(cmd: Command) -> Command {
449         <T as Args>::augment_args(cmd)
450     }
augment_args_for_update(cmd: Command) -> Command451     fn augment_args_for_update(cmd: Command) -> Command {
452         <T as Args>::augment_args_for_update(cmd)
453     }
454 }
455 
456 impl<T: Subcommand> Subcommand for Box<T> {
augment_subcommands(cmd: Command) -> Command457     fn augment_subcommands(cmd: Command) -> Command {
458         <T as Subcommand>::augment_subcommands(cmd)
459     }
augment_subcommands_for_update(cmd: Command) -> Command460     fn augment_subcommands_for_update(cmd: Command) -> Command {
461         <T as Subcommand>::augment_subcommands_for_update(cmd)
462     }
has_subcommand(name: &str) -> bool463     fn has_subcommand(name: &str) -> bool {
464         <T as Subcommand>::has_subcommand(name)
465     }
466 }
467 
format_error<I: CommandFactory>(err: crate::Error) -> crate::Error468 fn format_error<I: CommandFactory>(err: crate::Error) -> crate::Error {
469     let mut cmd = I::command();
470     err.format(&mut cmd)
471 }
472