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