clap_builder/
derive.rs

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