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}