1 //! This module contains traits that are usable with the `#[derive(...)]`
2 //! macros in `clap_derive`.
4 use crate::builder
::PossibleValue
;
5 use crate::{ArgMatches, Command, Error}
;
7 use std
::ffi
::OsString
;
9 /// Parse command-line arguments into `Self`.
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.
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).
21 /// See also [`Subcommand`] and [`Args`].
23 /// **NOTE:** Deriving requires the `derive` feature flag
24 pub trait Parser
: FromArgMatches
+ CommandFactory
+ Sized
{
25 /// Parse from `std::env::args_os()`, exit on error
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>);
33 // Since this is more of a development-time error, we aren't doing as fancy of a quit
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>)
46 /// Parse from iterator, exit on error
47 fn parse_from
<I
, T
>(itr
: I
) -> Self
49 I
: IntoIterator
<Item
= T
>,
50 T
: Into
<OsString
> + Clone
,
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>);
58 // Since this is more of a development-time error, we aren't doing as fancy of a quit
59 // as `get_matches_from`
65 /// Parse from iterator, return Err on error.
66 fn try_parse_from
<I
, T
>(itr
: I
) -> Result
<Self, Error
>
68 I
: IntoIterator
<Item
= T
>,
69 T
: Into
<OsString
> + Clone
,
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>)
75 /// Update from iterator, exit on error
76 fn update_from
<I
, T
>(&mut self, itr
: I
)
78 I
: IntoIterator
<Item
= T
>,
79 T
: Into
<OsString
> + Clone
,
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>);
85 // Since this is more of a development-time error, we aren't doing as fancy of a quit
86 // as `get_matches_from`
91 /// Update from iterator, return Err on error.
92 fn try_update_from
<I
, T
>(&mut self, itr
: I
) -> Result
<(), Error
>
94 I
: IntoIterator
<Item
= T
>,
95 T
: Into
<OsString
> + Clone
,
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>)
104 /// Create a [`Command`] relevant for a user-defined container.
106 /// Derived as part of [`Parser`].
107 pub trait CommandFactory
: Sized
{
108 /// Build a [`Command`] that can instantiate `Self`.
110 /// See [`FromArgMatches::from_arg_matches_mut`] for instantiating `Self`.
111 fn command() -> Command
;
112 /// Build a [`Command`] that can update `self`.
114 /// See [`FromArgMatches::update_from_arg_matches_mut`] for updating `self`.
115 fn command_for_update() -> Command
;
118 /// Converts an instance of [`ArgMatches`] to a user-defined container.
120 /// Derived as part of [`Parser`], [`Args`], and [`Subcommand`].
121 pub trait FromArgMatches
: Sized
{
122 /// Instantiate `Self` from [`ArgMatches`], parsing the arguments as needed.
124 /// Motivation: If our application had two CLI options, `--name
125 /// <STRING>` and the flag `--debug`, we may create a struct as follows:
128 /// # #[cfg(feature = "derive")] {
136 /// We then need to convert the `ArgMatches` that `clap` generated into our struct.
137 /// `from_arg_matches` serves as the equivalent of:
140 /// # #[cfg(feature = "derive")] {
141 /// # use clap::ArgMatches;
142 /// # struct Context {
146 /// impl From<ArgMatches> for Context {
147 /// fn from(m: ArgMatches) -> Self {
149 /// name: m.get_one::<String>("name").unwrap().clone(),
150 /// debug: m.get_flag("debug"),
156 fn from_arg_matches(matches
: &ArgMatches
) -> Result
<Self, Error
>;
158 /// Instantiate `Self` from [`ArgMatches`], parsing the arguments as needed.
160 /// Motivation: If our application had two CLI options, `--name
161 /// <STRING>` and the flag `--debug`, we may create a struct as follows:
164 /// # #[cfg(feature = "derive")] {
172 /// We then need to convert the `ArgMatches` that `clap` generated into our struct.
173 /// `from_arg_matches_mut` serves as the equivalent of:
176 /// # #[cfg(feature = "derive")] {
177 /// # use clap::ArgMatches;
178 /// # struct Context {
182 /// impl From<ArgMatches> for Context {
183 /// fn from(m: ArgMatches) -> Self {
185 /// name: m.get_one::<String>("name").unwrap().to_string(),
186 /// debug: m.get_flag("debug"),
192 fn from_arg_matches_mut(matches
: &mut ArgMatches
) -> Result
<Self, Error
> {
193 Self::from_arg_matches(matches
)
196 /// Assign values from `ArgMatches` to `self`.
197 fn update_from_arg_matches(&mut self, matches
: &ArgMatches
) -> Result
<(), Error
>;
199 /// Assign values from `ArgMatches` to `self`.
200 fn update_from_arg_matches_mut(&mut self, matches
: &mut ArgMatches
) -> Result
<(), Error
> {
201 self.update_from_arg_matches(matches
)
205 /// Parse a set of arguments into a user-defined container.
207 /// Implementing this trait lets a parent container delegate argument parsing behavior to `Self`.
209 /// - `#[command(flatten)] args: ChildArgs`: Attribute can only be used with struct fields that impl
211 /// - `Variant(ChildArgs)`: No attribute is used with enum variants that impl `Args`.
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
216 fn group_id() -> Option
<crate::Id
> {
219 /// Append to [`Command`] so it can instantiate `Self`.
221 /// See also [`CommandFactory`].
222 fn augment_args(cmd
: Command
) -> Command
;
223 /// Append to [`Command`] so it can update `self`.
225 /// This is used to implement `#[command(flatten)]`
227 /// See also [`CommandFactory`].
228 fn augment_args_for_update(cmd
: Command
) -> Command
;
231 /// Parse a sub-command into a user-defined enum.
233 /// Implementing this trait lets a parent container delegate subcommand behavior to `Self`.
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
240 /// **NOTE:** Deriving requires the `derive` feature flag
241 pub trait Subcommand
: FromArgMatches
+ Sized
{
242 /// Append to [`Command`] so it can instantiate `Self`.
244 /// See also [`CommandFactory`].
245 fn augment_subcommands(cmd
: Command
) -> Command
;
246 /// Append to [`Command`] so it can update `self`.
248 /// This is used to implement `#[command(flatten)]`
250 /// See also [`CommandFactory`].
251 fn augment_subcommands_for_update(cmd
: Command
) -> Command
;
252 /// Test whether `Self` can parse a specific subcommand
253 fn has_subcommand(name
: &str) -> bool
;
256 /// Parse arguments into enums.
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`.
263 /// **NOTE:** Deriving requires the `derive` feature flag
264 pub trait ValueEnum
: Sized
+ Clone
{
265 /// All possible argument values, in display order.
266 fn value_variants
<'a
>() -> &'a
[Self];
268 /// Parse an argument into `Self`.
269 fn from_str(input
: &str, ignore_case
: bool
) -> Result
<Self, String
> {
270 Self::value_variants()
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
)
278 .ok_or_else(|| format
!("invalid variant: {input}"))
281 /// The canonical argument value.
283 /// The value is `None` for skipped variants.
284 fn to_possible_value(&self) -> Option
<PossibleValue
>;
287 impl<T
: Parser
> Parser
for Box
<T
> {
289 Box
::new(<T
as Parser
>::parse())
292 fn try_parse() -> Result
<Self, Error
> {
293 <T
as Parser
>::try_parse().map(Box
::new
)
296 fn parse_from
<I
, It
>(itr
: I
) -> Self
298 I
: IntoIterator
<Item
= It
>,
299 It
: Into
<OsString
> + Clone
,
301 Box
::new(<T
as Parser
>::parse_from(itr
))
304 fn try_parse_from
<I
, It
>(itr
: I
) -> Result
<Self, Error
>
306 I
: IntoIterator
<Item
= It
>,
307 It
: Into
<OsString
> + Clone
,
309 <T
as Parser
>::try_parse_from(itr
).map(Box
::new
)
313 impl<T
: CommandFactory
> CommandFactory
for Box
<T
> {
314 fn command
<'help
>() -> Command
{
315 <T
as CommandFactory
>::command()
317 fn command_for_update
<'help
>() -> Command
{
318 <T
as CommandFactory
>::command_for_update()
322 impl<T
: FromArgMatches
> FromArgMatches
for Box
<T
> {
323 fn from_arg_matches(matches
: &ArgMatches
) -> Result
<Self, Error
> {
324 <T
as FromArgMatches
>::from_arg_matches(matches
).map(Box
::new
)
326 fn from_arg_matches_mut(matches
: &mut ArgMatches
) -> Result
<Self, Error
> {
327 <T
as FromArgMatches
>::from_arg_matches_mut(matches
).map(Box
::new
)
329 fn update_from_arg_matches(&mut self, matches
: &ArgMatches
) -> Result
<(), Error
> {
330 <T
as FromArgMatches
>::update_from_arg_matches(self, matches
)
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
)
337 impl<T
: Args
> Args
for Box
<T
> {
338 fn augment_args(cmd
: Command
) -> Command
{
339 <T
as Args
>::augment_args(cmd
)
341 fn augment_args_for_update(cmd
: Command
) -> Command
{
342 <T
as Args
>::augment_args_for_update(cmd
)
346 impl<T
: Subcommand
> Subcommand
for Box
<T
> {
347 fn augment_subcommands(cmd
: Command
) -> Command
{
348 <T
as Subcommand
>::augment_subcommands(cmd
)
350 fn augment_subcommands_for_update(cmd
: Command
) -> Command
{
351 <T
as Subcommand
>::augment_subcommands_for_update(cmd
)
353 fn has_subcommand(name
: &str) -> bool
{
354 <T
as Subcommand
>::has_subcommand(name
)
358 fn format_error
<I
: CommandFactory
>(err
: crate::Error
) -> crate::Error
{
359 let mut cmd
= I
::command();