1 //! This module contains traits that are usable with the `#[derive(...)].`
2 //! macros in [`clap_derive`].
3
4 use crate::{ArgMatches, Command, Error, PossibleValue};
5
6 use std::ffi::OsString;
7
8 /// Parse command-line arguments into `Self`.
9 ///
10 /// The primary one-stop-shop trait used to create an instance of a `clap`
11 /// [`Command`], conduct the parsing, and turn the resulting [`ArgMatches`] back
12 /// into concrete instance of the user struct.
13 ///
14 /// This trait is primarily a convenience on top of [`FromArgMatches`] +
15 /// [`CommandFactory`] which uses those two underlying traits to build the two
16 /// fundamental functions `parse` which uses the `std::env::args_os` iterator,
17 /// and `parse_from` which allows the consumer to supply the iterator (along
18 /// with fallible options for each).
19 ///
20 /// See also [`Subcommand`] and [`Args`].
21 ///
22 /// See the [derive reference](crate::_derive) for attributes and best practices.
23 ///
24 /// **NOTE:** Deriving requires the [`derive` feature flag][crate::_features]
25 ///
26 /// # Examples
27 ///
28 /// The following example creates a `Context` struct that would be used
29 /// throughout the application representing the normalized values coming from
30 /// the CLI.
31 ///
32 #[cfg_attr(not(feature = "derive"), doc = " ```ignore")]
33 #[cfg_attr(feature = "derive", doc = " ```")]
34 /// /// My super CLI
35 /// #[derive(clap::Parser)]
36 /// #[clap(name = "demo")]
37 /// struct Context {
38 /// /// More verbose output
39 /// #[clap(long)]
40 /// verbose: bool,
41 /// /// An optional name
42 /// #[clap(short, long)]
43 /// name: Option<String>,
44 /// }
45 /// ```
46 ///
47 /// The equivalent [`Command`] struct + `From` implementation:
48 ///
49 /// ```rust
50 /// # use clap::{Command, Arg, ArgMatches, ArgAction};
51 /// Command::new("demo")
52 /// .about("My super CLI")
53 /// .arg(Arg::new("verbose")
54 /// .long("verbose")
55 /// .action(ArgAction::SetTrue)
56 /// .help("More verbose output"))
57 /// .arg(Arg::new("name")
58 /// .long("name")
59 /// .short('n')
60 /// .help("An optional name")
61 /// .takes_value(true));
62 ///
63 /// struct Context {
64 /// verbose: bool,
65 /// name: Option<String>,
66 /// }
67 ///
68 /// impl From<ArgMatches> for Context {
69 /// fn from(m: ArgMatches) -> Self {
70 /// Context {
71 /// verbose: *m.get_one::<bool>("verbose").expect("defaulted_by_clap"),
72 /// name: m.get_one::<String>("name").cloned(),
73 /// }
74 /// }
75 /// }
76 /// ```
77 ///
78 pub trait Parser: FromArgMatches + CommandFactory + Sized {
79 /// Parse from `std::env::args_os()`, exit on error
parse() -> Self80 fn parse() -> Self {
81 let mut matches = <Self as CommandFactory>::command().get_matches();
82 let res = <Self as FromArgMatches>::from_arg_matches_mut(&mut matches)
83 .map_err(format_error::<Self>);
84 match res {
85 Ok(s) => s,
86 Err(e) => {
87 // Since this is more of a development-time error, we aren't doing as fancy of a quit
88 // as `get_matches`
89 e.exit()
90 }
91 }
92 }
93
94 /// Parse from `std::env::args_os()`, return Err on error.
try_parse() -> Result<Self, Error>95 fn try_parse() -> Result<Self, Error> {
96 let mut matches = <Self as CommandFactory>::command().try_get_matches()?;
97 <Self as FromArgMatches>::from_arg_matches_mut(&mut matches).map_err(format_error::<Self>)
98 }
99
100 /// Parse from iterator, exit on error
parse_from<I, T>(itr: I) -> Self where I: IntoIterator<Item = T>, T: Into<OsString> + Clone,101 fn parse_from<I, T>(itr: I) -> Self
102 where
103 I: IntoIterator<Item = T>,
104 T: Into<OsString> + Clone,
105 {
106 let mut matches = <Self as CommandFactory>::command().get_matches_from(itr);
107 let res = <Self as FromArgMatches>::from_arg_matches_mut(&mut matches)
108 .map_err(format_error::<Self>);
109 match res {
110 Ok(s) => s,
111 Err(e) => {
112 // Since this is more of a development-time error, we aren't doing as fancy of a quit
113 // as `get_matches_from`
114 e.exit()
115 }
116 }
117 }
118
119 /// 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,120 fn try_parse_from<I, T>(itr: I) -> Result<Self, Error>
121 where
122 I: IntoIterator<Item = T>,
123 T: Into<OsString> + Clone,
124 {
125 let mut matches = <Self as CommandFactory>::command().try_get_matches_from(itr)?;
126 <Self as FromArgMatches>::from_arg_matches_mut(&mut matches).map_err(format_error::<Self>)
127 }
128
129 /// Update from iterator, exit on error
update_from<I, T>(&mut self, itr: I) where I: IntoIterator<Item = T>, T: Into<OsString> + Clone,130 fn update_from<I, T>(&mut self, itr: I)
131 where
132 I: IntoIterator<Item = T>,
133 T: Into<OsString> + Clone,
134 {
135 let mut matches = <Self as CommandFactory>::command_for_update().get_matches_from(itr);
136 let res = <Self as FromArgMatches>::update_from_arg_matches_mut(self, &mut matches)
137 .map_err(format_error::<Self>);
138 if let Err(e) = res {
139 // Since this is more of a development-time error, we aren't doing as fancy of a quit
140 // as `get_matches_from`
141 e.exit()
142 }
143 }
144
145 /// 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,146 fn try_update_from<I, T>(&mut self, itr: I) -> Result<(), Error>
147 where
148 I: IntoIterator<Item = T>,
149 T: Into<OsString> + Clone,
150 {
151 let mut matches =
152 <Self as CommandFactory>::command_for_update().try_get_matches_from(itr)?;
153 <Self as FromArgMatches>::update_from_arg_matches_mut(self, &mut matches)
154 .map_err(format_error::<Self>)
155 }
156
157 /// Deprecated, `StructOpt::clap` replaced with [`CommandFactory::command`] (derive as part of
158 /// [`Parser`])
159 #[cfg_attr(
160 feature = "deprecated",
161 deprecated(
162 since = "3.0.0",
163 note = "`StructOpt::clap` is replaced with `CommandFactory::command` (derived as part of `Parser`)"
164 )
165 )]
166 #[doc(hidden)]
clap<'help>() -> Command<'help>167 fn clap<'help>() -> Command<'help> {
168 <Self as CommandFactory>::command()
169 }
170
171 /// Deprecated, `StructOpt::from_clap` replaced with [`FromArgMatches::from_arg_matches_mut`] (derive as part of
172 /// [`Parser`])
173 #[cfg_attr(
174 feature = "deprecated",
175 deprecated(
176 since = "3.0.0",
177 note = "`StructOpt::from_clap` is replaced with `FromArgMatches::from_arg_matches_mut` (derived as part of `Parser`)"
178 )
179 )]
180 #[doc(hidden)]
from_clap(matches: &ArgMatches) -> Self181 fn from_clap(matches: &ArgMatches) -> Self {
182 <Self as FromArgMatches>::from_arg_matches(matches).unwrap()
183 }
184
185 /// Deprecated, `StructOpt::from_args` replaced with `Parser::parse` (note the change in derives)
186 #[cfg_attr(
187 feature = "deprecated",
188 deprecated(
189 since = "3.0.0",
190 note = "`StructOpt::from_args` is replaced with `Parser::parse` (note the change in derives)"
191 )
192 )]
193 #[doc(hidden)]
from_args() -> Self194 fn from_args() -> Self {
195 Self::parse()
196 }
197
198 /// Deprecated, `StructOpt::from_args_safe` replaced with `Parser::try_parse` (note the change in derives)
199 #[cfg_attr(
200 feature = "deprecated",
201 deprecated(
202 since = "3.0.0",
203 note = "`StructOpt::from_args_safe` is replaced with `Parser::try_parse` (note the change in derives)"
204 )
205 )]
206 #[doc(hidden)]
from_args_safe() -> Result<Self, Error>207 fn from_args_safe() -> Result<Self, Error> {
208 Self::try_parse()
209 }
210
211 /// Deprecated, `StructOpt::from_iter` replaced with `Parser::parse_from` (note the change in derives)
212 #[cfg_attr(
213 feature = "deprecated",
214 deprecated(
215 since = "3.0.0",
216 note = "`StructOpt::from_iter` is replaced with `Parser::parse_from` (note the change in derives)"
217 )
218 )]
219 #[doc(hidden)]
from_iter<I, T>(itr: I) -> Self where I: IntoIterator<Item = T>, T: Into<OsString> + Clone,220 fn from_iter<I, T>(itr: I) -> Self
221 where
222 I: IntoIterator<Item = T>,
223 T: Into<OsString> + Clone,
224 {
225 Self::parse_from(itr)
226 }
227
228 /// Deprecated, `StructOpt::from_iter_safe` replaced with `Parser::try_parse_from` (note the
229 /// change in derives)
230 #[cfg_attr(
231 feature = "deprecated",
232 deprecated(
233 since = "3.0.0",
234 note = "`StructOpt::from_iter_safe` is replaced with `Parser::try_parse_from` (note the change in derives)"
235 )
236 )]
237 #[doc(hidden)]
from_iter_safe<I, T>(itr: I) -> Result<Self, Error> where I: IntoIterator<Item = T>, T: Into<OsString> + Clone,238 fn from_iter_safe<I, T>(itr: I) -> Result<Self, Error>
239 where
240 I: IntoIterator<Item = T>,
241 T: Into<OsString> + Clone,
242 {
243 Self::try_parse_from(itr)
244 }
245 }
246
247 /// Create a [`Command`] relevant for a user-defined container.
248 ///
249 /// Derived as part of [`Parser`].
250 pub trait CommandFactory: Sized {
251 /// Build a [`Command`] that can instantiate `Self`.
252 ///
253 /// See [`FromArgMatches::from_arg_matches_mut`] for instantiating `Self`.
command<'help>() -> Command<'help>254 fn command<'help>() -> Command<'help> {
255 #[allow(deprecated)]
256 Self::into_app()
257 }
258 /// Deprecated, replaced with `CommandFactory::command`
259 #[cfg_attr(
260 feature = "deprecated",
261 deprecated(since = "3.1.0", note = "Replaced with `CommandFactory::command")
262 )]
into_app<'help>() -> Command<'help>263 fn into_app<'help>() -> Command<'help>;
264 /// Build a [`Command`] that can update `self`.
265 ///
266 /// See [`FromArgMatches::update_from_arg_matches_mut`] for updating `self`.
command_for_update<'help>() -> Command<'help>267 fn command_for_update<'help>() -> Command<'help> {
268 #[allow(deprecated)]
269 Self::into_app_for_update()
270 }
271 /// Deprecated, replaced with `CommandFactory::command_for_update`
272 #[cfg_attr(
273 feature = "deprecated",
274 deprecated(
275 since = "3.1.0",
276 note = "Replaced with `CommandFactory::command_for_update"
277 )
278 )]
into_app_for_update<'help>() -> Command<'help>279 fn into_app_for_update<'help>() -> Command<'help>;
280 }
281
282 /// Converts an instance of [`ArgMatches`] to a user-defined container.
283 ///
284 /// Derived as part of [`Parser`], [`Args`], and [`Subcommand`].
285 pub trait FromArgMatches: Sized {
286 /// Instantiate `Self` from [`ArgMatches`], parsing the arguments as needed.
287 ///
288 /// Motivation: If our application had two CLI options, `--name
289 /// <STRING>` and the flag `--debug`, we may create a struct as follows:
290 ///
291 #[cfg_attr(not(feature = "derive"), doc = " ```ignore")]
292 #[cfg_attr(feature = "derive", doc = " ```no_run")]
293 /// struct Context {
294 /// name: String,
295 /// debug: bool
296 /// }
297 /// ```
298 ///
299 /// We then need to convert the `ArgMatches` that `clap` generated into our struct.
300 /// `from_arg_matches` serves as the equivalent of:
301 ///
302 #[cfg_attr(not(feature = "derive"), doc = " ```ignore")]
303 #[cfg_attr(feature = "derive", doc = " ```no_run")]
304 /// # use clap::ArgMatches;
305 /// # struct Context {
306 /// # name: String,
307 /// # debug: bool
308 /// # }
309 /// impl From<ArgMatches> for Context {
310 /// fn from(m: ArgMatches) -> Self {
311 /// Context {
312 /// name: m.get_one::<String>("name").unwrap().clone(),
313 /// debug: *m.get_one::<bool>("debug").expect("defaulted by clap"),
314 /// }
315 /// }
316 /// }
317 /// ```
from_arg_matches(matches: &ArgMatches) -> Result<Self, Error>318 fn from_arg_matches(matches: &ArgMatches) -> Result<Self, Error>;
319
320 /// Instantiate `Self` from [`ArgMatches`], parsing the arguments as needed.
321 ///
322 /// Motivation: If our application had two CLI options, `--name
323 /// <STRING>` and the flag `--debug`, we may create a struct as follows:
324 ///
325 #[cfg_attr(not(feature = "derive"), doc = " ```ignore")]
326 #[cfg_attr(feature = "derive", doc = " ```no_run")]
327 /// struct Context {
328 /// name: String,
329 /// debug: bool
330 /// }
331 /// ```
332 ///
333 /// We then need to convert the `ArgMatches` that `clap` generated into our struct.
334 /// `from_arg_matches_mut` serves as the equivalent of:
335 ///
336 #[cfg_attr(not(feature = "derive"), doc = " ```ignore")]
337 #[cfg_attr(feature = "derive", doc = " ```no_run")]
338 /// # use clap::ArgMatches;
339 /// # struct Context {
340 /// # name: String,
341 /// # debug: bool
342 /// # }
343 /// impl From<ArgMatches> for Context {
344 /// fn from(m: ArgMatches) -> Self {
345 /// Context {
346 /// name: m.get_one::<String>("name").unwrap().to_string(),
347 /// debug: *m.get_one::<bool>("debug").expect("defaulted by clap"),
348 /// }
349 /// }
350 /// }
351 /// ```
from_arg_matches_mut(matches: &mut ArgMatches) -> Result<Self, Error>352 fn from_arg_matches_mut(matches: &mut ArgMatches) -> Result<Self, Error> {
353 Self::from_arg_matches(matches)
354 }
355
356 /// Assign values from `ArgMatches` to `self`.
update_from_arg_matches(&mut self, matches: &ArgMatches) -> Result<(), Error>357 fn update_from_arg_matches(&mut self, matches: &ArgMatches) -> Result<(), Error>;
358
359 /// Assign values from `ArgMatches` to `self`.
update_from_arg_matches_mut(&mut self, matches: &mut ArgMatches) -> Result<(), Error>360 fn update_from_arg_matches_mut(&mut self, matches: &mut ArgMatches) -> Result<(), Error> {
361 self.update_from_arg_matches(matches)
362 }
363 }
364
365 /// Parse a set of arguments into a user-defined container.
366 ///
367 /// Implementing this trait lets a parent container delegate argument parsing behavior to `Self`.
368 /// with:
369 /// - `#[clap(flatten)] args: ChildArgs`: Attribute can only be used with struct fields that impl
370 /// `Args`.
371 /// - `Variant(ChildArgs)`: No attribute is used with enum variants that impl `Args`.
372 ///
373 /// See the [derive reference](crate::_derive) for attributes and best practices.
374 ///
375 /// **NOTE:** Deriving requires the [`derive` feature flag][crate::_features]
376 ///
377 /// # Example
378 ///
379 #[cfg_attr(not(feature = "derive"), doc = " ```ignore")]
380 #[cfg_attr(feature = "derive", doc = " ```")]
381 /// #[derive(clap::Parser)]
382 /// struct Args {
383 /// #[clap(flatten)]
384 /// logging: LogArgs,
385 /// }
386 ///
387 /// #[derive(clap::Args)]
388 /// struct LogArgs {
389 /// #[clap(long, short = 'v', parse(from_occurrences))]
390 /// verbose: i8,
391 /// }
392 /// ```
393 pub trait Args: FromArgMatches + Sized {
394 /// Append to [`Command`] so it can instantiate `Self`.
395 ///
396 /// See also [`CommandFactory`].
augment_args(cmd: Command<'_>) -> Command<'_>397 fn augment_args(cmd: Command<'_>) -> Command<'_>;
398 /// Append to [`Command`] so it can update `self`.
399 ///
400 /// This is used to implement `#[clap(flatten)]`
401 ///
402 /// See also [`CommandFactory`].
augment_args_for_update(cmd: Command<'_>) -> Command<'_>403 fn augment_args_for_update(cmd: Command<'_>) -> Command<'_>;
404 }
405
406 /// Parse a sub-command into a user-defined enum.
407 ///
408 /// Implementing this trait lets a parent container delegate subcommand behavior to `Self`.
409 /// with:
410 /// - `#[clap(subcommand)] field: SubCmd`: Attribute can be used with either struct fields or enum
411 /// variants that impl `Subcommand`.
412 /// - `#[clap(flatten)] Variant(SubCmd)`: Attribute can only be used with enum variants that impl
413 /// `Subcommand`.
414 ///
415 /// See the [derive reference](crate::_derive) for attributes and best practices.
416 ///
417 /// **NOTE:** Deriving requires the [`derive` feature flag][crate::_features]
418 ///
419 /// # Example
420 ///
421 #[cfg_attr(not(feature = "derive"), doc = " ```ignore")]
422 #[cfg_attr(feature = "derive", doc = " ```")]
423 /// #[derive(clap::Parser)]
424 /// struct Args {
425 /// #[clap(subcommand)]
426 /// action: Action,
427 /// }
428 ///
429 /// #[derive(clap::Subcommand)]
430 /// enum Action {
431 /// Add,
432 /// Remove,
433 /// }
434 /// ```
435 pub trait Subcommand: FromArgMatches + Sized {
436 /// Append to [`Command`] so it can instantiate `Self`.
437 ///
438 /// See also [`CommandFactory`].
augment_subcommands(cmd: Command<'_>) -> Command<'_>439 fn augment_subcommands(cmd: Command<'_>) -> Command<'_>;
440 /// Append to [`Command`] so it can update `self`.
441 ///
442 /// This is used to implement `#[clap(flatten)]`
443 ///
444 /// See also [`CommandFactory`].
augment_subcommands_for_update(cmd: Command<'_>) -> Command<'_>445 fn augment_subcommands_for_update(cmd: Command<'_>) -> Command<'_>;
446 /// Test whether `Self` can parse a specific subcommand
has_subcommand(name: &str) -> bool447 fn has_subcommand(name: &str) -> bool;
448 }
449
450 /// Parse arguments into enums.
451 ///
452 /// When deriving [`Parser`], a field whose type implements `ValueEnum` can have the attribute
453 /// `#[clap(value_enum)]` which will
454 /// - Call [`Arg::possible_values`][crate::Arg::possible_values]
455 /// - Allowing using the `#[clap(default_value_t)]` attribute without implementing `Display`.
456 ///
457 /// See the [derive reference](crate::_derive) for attributes and best practices.
458 ///
459 /// **NOTE:** Deriving requires the [`derive` feature flag][crate::_features]
460 ///
461 /// # Example
462 ///
463 #[cfg_attr(not(feature = "derive"), doc = " ```ignore")]
464 #[cfg_attr(feature = "derive", doc = " ```")]
465 /// #[derive(clap::Parser)]
466 /// struct Args {
467 /// #[clap(value_enum)]
468 /// level: Level,
469 /// }
470 ///
471 /// #[derive(clap::ValueEnum, Clone)]
472 /// enum Level {
473 /// Debug,
474 /// Info,
475 /// Warning,
476 /// Error,
477 /// }
478 /// ```
479 pub trait ValueEnum: Sized + Clone {
480 /// All possible argument values, in display order.
value_variants<'a>() -> &'a [Self]481 fn value_variants<'a>() -> &'a [Self];
482
483 /// Parse an argument into `Self`.
from_str(input: &str, ignore_case: bool) -> Result<Self, String>484 fn from_str(input: &str, ignore_case: bool) -> Result<Self, String> {
485 Self::value_variants()
486 .iter()
487 .find(|v| {
488 v.to_possible_value()
489 .expect("ValueEnum::value_variants contains only values with a corresponding ValueEnum::to_possible_value")
490 .matches(input, ignore_case)
491 })
492 .cloned()
493 .ok_or_else(|| format!("Invalid variant: {}", input))
494 }
495
496 /// The canonical argument value.
497 ///
498 /// The value is `None` for skipped variants.
to_possible_value<'a>(&self) -> Option<PossibleValue<'a>>499 fn to_possible_value<'a>(&self) -> Option<PossibleValue<'a>>;
500 }
501
502 impl<T: Parser> Parser for Box<T> {
parse() -> Self503 fn parse() -> Self {
504 Box::new(<T as Parser>::parse())
505 }
506
try_parse() -> Result<Self, Error>507 fn try_parse() -> Result<Self, Error> {
508 <T as Parser>::try_parse().map(Box::new)
509 }
510
parse_from<I, It>(itr: I) -> Self where I: IntoIterator<Item = It>, It: Into<OsString> + Clone,511 fn parse_from<I, It>(itr: I) -> Self
512 where
513 I: IntoIterator<Item = It>,
514 It: Into<OsString> + Clone,
515 {
516 Box::new(<T as Parser>::parse_from(itr))
517 }
518
try_parse_from<I, It>(itr: I) -> Result<Self, Error> where I: IntoIterator<Item = It>, It: Into<OsString> + Clone,519 fn try_parse_from<I, It>(itr: I) -> Result<Self, Error>
520 where
521 I: IntoIterator<Item = It>,
522 It: Into<OsString> + Clone,
523 {
524 <T as Parser>::try_parse_from(itr).map(Box::new)
525 }
526 }
527
528 #[allow(deprecated)]
529 impl<T: CommandFactory> CommandFactory for Box<T> {
into_app<'help>() -> Command<'help>530 fn into_app<'help>() -> Command<'help> {
531 <T as CommandFactory>::into_app()
532 }
into_app_for_update<'help>() -> Command<'help>533 fn into_app_for_update<'help>() -> Command<'help> {
534 <T as CommandFactory>::into_app_for_update()
535 }
536 }
537
538 impl<T: FromArgMatches> FromArgMatches for Box<T> {
from_arg_matches(matches: &ArgMatches) -> Result<Self, Error>539 fn from_arg_matches(matches: &ArgMatches) -> Result<Self, Error> {
540 <T as FromArgMatches>::from_arg_matches(matches).map(Box::new)
541 }
from_arg_matches_mut(matches: &mut ArgMatches) -> Result<Self, Error>542 fn from_arg_matches_mut(matches: &mut ArgMatches) -> Result<Self, Error> {
543 <T as FromArgMatches>::from_arg_matches_mut(matches).map(Box::new)
544 }
update_from_arg_matches(&mut self, matches: &ArgMatches) -> Result<(), Error>545 fn update_from_arg_matches(&mut self, matches: &ArgMatches) -> Result<(), Error> {
546 <T as FromArgMatches>::update_from_arg_matches(self, matches)
547 }
update_from_arg_matches_mut(&mut self, matches: &mut ArgMatches) -> Result<(), Error>548 fn update_from_arg_matches_mut(&mut self, matches: &mut ArgMatches) -> Result<(), Error> {
549 <T as FromArgMatches>::update_from_arg_matches_mut(self, matches)
550 }
551 }
552
553 impl<T: Args> Args for Box<T> {
augment_args(cmd: Command<'_>) -> Command<'_>554 fn augment_args(cmd: Command<'_>) -> Command<'_> {
555 <T as Args>::augment_args(cmd)
556 }
augment_args_for_update(cmd: Command<'_>) -> Command<'_>557 fn augment_args_for_update(cmd: Command<'_>) -> Command<'_> {
558 <T as Args>::augment_args_for_update(cmd)
559 }
560 }
561
562 impl<T: Subcommand> Subcommand for Box<T> {
augment_subcommands(cmd: Command<'_>) -> Command<'_>563 fn augment_subcommands(cmd: Command<'_>) -> Command<'_> {
564 <T as Subcommand>::augment_subcommands(cmd)
565 }
augment_subcommands_for_update(cmd: Command<'_>) -> Command<'_>566 fn augment_subcommands_for_update(cmd: Command<'_>) -> Command<'_> {
567 <T as Subcommand>::augment_subcommands_for_update(cmd)
568 }
has_subcommand(name: &str) -> bool569 fn has_subcommand(name: &str) -> bool {
570 <T as Subcommand>::has_subcommand(name)
571 }
572 }
573
format_error<I: CommandFactory>(err: crate::Error) -> crate::Error574 fn format_error<I: CommandFactory>(err: crate::Error) -> crate::Error {
575 let mut cmd = I::command();
576 err.format(&mut cmd)
577 }
578