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