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