1 /// Allows you to pull the version from your Cargo.toml at compile time as
2 /// `MAJOR.MINOR.PATCH_PKGVERSION_PRE`
3 ///
4 /// # Examples
5 ///
6 /// ```no_run
7 /// # use clap_builder as clap;
8 /// # use clap::crate_version;
9 /// # use clap::Command;
10 /// let m = Command::new("cmd")
11 ///             .version(crate_version!())
12 ///             .get_matches();
13 /// ```
14 #[cfg(feature = "cargo")]
15 #[macro_export]
16 macro_rules! crate_version {
17     () => {
18         env!("CARGO_PKG_VERSION")
19     };
20 }
21 
22 /// Allows you to pull the authors for the command from your Cargo.toml at
23 /// compile time in the form:
24 /// `"author1 lastname <[email protected]>:author2 lastname <[email protected]>"`
25 ///
26 /// You can replace the colons with a custom separator by supplying a
27 /// replacement string, so, for example,
28 /// `crate_authors!(",\n")` would become
29 /// `"author1 lastname <[email protected]>,\nauthor2 lastname <[email protected]>,\nauthor3 lastname <[email protected]>"`
30 ///
31 /// # Examples
32 ///
33 /// ```no_run
34 /// # use clap_builder as clap;
35 /// # use clap::crate_authors;
36 /// # use clap::Command;
37 /// let m = Command::new("cmd")
38 ///             .author(crate_authors!("\n"))
39 ///             .get_matches();
40 /// ```
41 #[cfg(feature = "cargo")]
42 #[macro_export]
43 macro_rules! crate_authors {
44     ($sep:expr) => {{
45         static authors: &str = env!("CARGO_PKG_AUTHORS");
46         if authors.contains(':') {
47             static CACHED: std::sync::OnceLock<String> = std::sync::OnceLock::new();
48             let s = CACHED.get_or_init(|| authors.replace(':', $sep));
49             let s: &'static str = &*s;
50             s
51         } else {
52             authors
53         }
54     }};
55     () => {
56         env!("CARGO_PKG_AUTHORS")
57     };
58 }
59 
60 /// Allows you to pull the description from your Cargo.toml at compile time.
61 ///
62 /// # Examples
63 ///
64 /// ```no_run
65 /// # use clap_builder as clap;
66 /// # use clap::crate_description;
67 /// # use clap::Command;
68 /// let m = Command::new("cmd")
69 ///             .about(crate_description!())
70 ///             .get_matches();
71 /// ```
72 #[cfg(feature = "cargo")]
73 #[macro_export]
74 macro_rules! crate_description {
75     () => {
76         env!("CARGO_PKG_DESCRIPTION")
77     };
78 }
79 
80 /// Allows you to pull the name from your Cargo.toml at compile time.
81 ///
82 /// **NOTE:** This macro extracts the name from an environment variable `CARGO_PKG_NAME`.
83 /// When the crate name is set to something different from the package name,
84 /// use environment variables `CARGO_CRATE_NAME` or `CARGO_BIN_NAME`.
85 /// See [the Cargo Book](https://doc.rust-lang.org/cargo/reference/environment-variables.html)
86 /// for more information.
87 ///
88 /// # Examples
89 ///
90 /// ```no_run
91 /// # use clap_builder as clap;
92 /// # use clap::crate_name;
93 /// # use clap::Command;
94 /// let m = Command::new(crate_name!())
95 ///             .get_matches();
96 /// ```
97 #[cfg(feature = "cargo")]
98 #[macro_export]
99 macro_rules! crate_name {
100     () => {
101         env!("CARGO_PKG_NAME")
102     };
103 }
104 
105 /// Allows you to build the `Command` instance from your Cargo.toml at compile time.
106 ///
107 /// **NOTE:** Changing the values in your `Cargo.toml` does not trigger a re-build automatically,
108 /// and therefore won't change the generated output until you recompile.
109 ///
110 /// In some cases you can "trick" the compiler into triggering a rebuild when your
111 /// `Cargo.toml` is changed by including this in your `src/main.rs` file
112 /// `include_str!("../Cargo.toml");`
113 ///
114 /// # Examples
115 ///
116 /// ```no_run
117 /// # use clap_builder as clap;
118 /// # use clap::command;
119 /// let m = command!().get_matches();
120 /// ```
121 #[cfg(feature = "cargo")]
122 #[macro_export]
123 macro_rules! command {
124     () => {{
125         $crate::command!($crate::crate_name!())
126     }};
127     ($name:expr) => {{
128         let mut cmd = $crate::Command::new($name).version($crate::crate_version!());
129 
130         let author = $crate::crate_authors!();
131         if !author.is_empty() {
132             cmd = cmd.author(author)
133         }
134 
135         let about = $crate::crate_description!();
136         if !about.is_empty() {
137             cmd = cmd.about(about)
138         }
139 
140         cmd
141     }};
142 }
143 
144 /// Requires `cargo` feature flag to be enabled.
145 #[cfg(not(feature = "cargo"))]
146 #[macro_export]
147 macro_rules! command {
148     () => {{
149         compile_error!("`cargo` feature flag is required");
150     }};
151     ($name:expr) => {{
152         compile_error!("`cargo` feature flag is required");
153     }};
154 }
155 
156 #[doc(hidden)]
157 #[macro_export]
158 macro_rules! arg_impl {
159     ( @string $val:ident ) => {
160         stringify!($val)
161     };
162     ( @string $val:literal ) => {{
163         let ident_or_string_literal: &str = $val;
164         ident_or_string_literal
165     }};
166     ( @string $val:tt ) => {
167         ::std::compile_error!("Only identifiers or string literals supported");
168     };
169     ( @string ) => {
170         None
171     };
172 
173     ( @char $val:ident ) => {{
174         let ident_or_char_literal = stringify!($val);
175         debug_assert_eq!(
176             ident_or_char_literal.len(),
177             1,
178             "Single-letter identifier expected, got {ident_or_char_literal}",
179         );
180         ident_or_char_literal.chars().next().unwrap()
181     }};
182     ( @char $val:literal ) => {{
183         let ident_or_char_literal: char = $val;
184         ident_or_char_literal
185     }};
186     ( @char ) => {{
187         None
188     }};
189 
190     (
191         @arg
192         ($arg:expr)
193         --$long:ident
194         $($tail:tt)*
195     ) => {{
196         debug_assert_eq!($arg.get_value_names(), None, "Flags should precede values");
197         debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
198 
199         let mut arg = $arg;
200         let long = $crate::arg_impl! { @string $long };
201         if arg.get_id() == "" {
202             arg = arg.id(long);
203         }
204         let action = $crate::ArgAction::SetTrue;
205         let arg = arg
206             .long(long)
207             .action(action);
208         let arg = $crate::arg_impl! {
209             @arg (arg) $($tail)*
210         };
211         arg
212     }};
213     (
214         @arg
215         ($arg:expr)
216         --$long:literal
217         $($tail:tt)*
218     ) => {{
219         debug_assert_eq!($arg.get_value_names(), None, "Flags should precede values");
220         debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
221 
222         let mut arg = $arg;
223         let long = $crate::arg_impl! { @string $long };
224         if arg.get_id() == "" {
225             arg = arg.id(long);
226         }
227         let action = $crate::ArgAction::SetTrue;
228         let arg = arg
229             .long(long)
230             .action(action);
231         let arg = $crate::arg_impl! {
232             @arg (arg) $($tail)*
233         };
234         arg
235     }};
236     (
237         @arg
238         ($arg:expr)
239         -$short:ident
240         $($tail:tt)*
241     ) => {{
242         debug_assert_eq!($arg.get_long(), None, "Short flags should precede long flags");
243         debug_assert_eq!($arg.get_value_names(), None, "Flags should precede values");
244         debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
245 
246         let action = $crate::ArgAction::SetTrue;
247         let arg = $arg
248             .short($crate::arg_impl! { @char $short })
249             .action(action);
250         let arg = $crate::arg_impl! {
251             @arg (arg) $($tail)*
252         };
253         arg
254     }};
255     (
256         @arg
257         ($arg:expr)
258         -$short:literal
259         $($tail:tt)*
260     ) => {{
261         debug_assert_eq!($arg.get_long(), None, "Short flags should precede long flags");
262         debug_assert_eq!($arg.get_value_names(), None, "Flags should precede values");
263         debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
264 
265         let action = $crate::ArgAction::SetTrue;
266         let arg = $arg
267             .short($crate::arg_impl! { @char $short })
268             .action(action);
269         let arg = $crate::arg_impl! {
270             @arg (arg) $($tail)*
271         };
272         arg
273     }};
274     (
275         @arg
276         ($arg:expr)
277         <$value_name:ident>
278         $($tail:tt)*
279     ) => {{
280         debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
281         debug_assert_eq!($arg.get_value_names(), None, "Multiple values not yet supported");
282 
283         let mut arg = $arg;
284 
285         if arg.get_long().is_none() && arg.get_short().is_none() {
286             arg = arg.required(true);
287         }
288 
289         let value_name = $crate::arg_impl! { @string $value_name };
290         if arg.get_id() == "" {
291             arg = arg.id(value_name);
292         }
293         let arg = arg
294             .value_name(value_name)
295             .action($crate::ArgAction::Set);
296         let arg = $crate::arg_impl! {
297             @arg (arg) $($tail)*
298         };
299         arg
300     }};
301     (
302         @arg
303         ($arg:expr)
304         <$value_name:literal>
305         $($tail:tt)*
306     ) => {{
307         debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
308         debug_assert_eq!($arg.get_value_names(), None, "Multiple values not yet supported");
309 
310         let mut arg = $arg;
311 
312         if arg.get_long().is_none() && arg.get_short().is_none() {
313             arg = arg.required(true);
314         }
315 
316         let value_name = $crate::arg_impl! { @string $value_name };
317         if arg.get_id() == "" {
318             arg = arg.id(value_name);
319         }
320         let arg = arg
321             .value_name(value_name)
322             .action($crate::ArgAction::Set);
323         let arg = $crate::arg_impl! {
324             @arg (arg) $($tail)*
325         };
326         arg
327     }};
328     (
329         @arg
330         ($arg:expr)
331         [$value_name:ident]
332         $($tail:tt)*
333     ) => {{
334         debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
335         debug_assert_eq!($arg.get_value_names(), None, "Multiple values not yet supported");
336 
337         let mut arg = $arg;
338 
339         if arg.get_long().is_none() && arg.get_short().is_none() {
340             arg = arg.required(false);
341         } else {
342             arg = arg.num_args(0..=1);
343         }
344 
345         let value_name = $crate::arg_impl! { @string $value_name };
346         if arg.get_id() == "" {
347             arg = arg.id(value_name);
348         }
349         let arg = arg
350             .value_name(value_name)
351             .action($crate::ArgAction::Set);
352         let arg = $crate::arg_impl! {
353             @arg (arg) $($tail)*
354         };
355         arg
356     }};
357     (
358         @arg
359         ($arg:expr)
360         [$value_name:literal]
361         $($tail:tt)*
362     ) => {{
363         debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
364         debug_assert_eq!($arg.get_value_names(), None, "Multiple values not yet supported");
365 
366         let mut arg = $arg;
367 
368         if arg.get_long().is_none() && arg.get_short().is_none() {
369             arg = arg.required(false);
370         } else {
371             arg = arg.num_args(0..=1);
372         }
373 
374         let value_name = $crate::arg_impl! { @string $value_name };
375         if arg.get_id() == "" {
376             arg = arg.id(value_name);
377         }
378         let arg = arg
379             .value_name(value_name)
380             .action($crate::ArgAction::Set);
381         let arg = $crate::arg_impl! {
382             @arg (arg) $($tail)*
383         };
384         arg
385     }};
386     (
387         @arg
388         ($arg:expr)
389         ...
390         $($tail:tt)*
391     ) => {{
392         let arg = match $arg.get_action() {
393             $crate::ArgAction::Set => {
394                 if $arg.get_long().is_none() && $arg.get_short().is_none() {
395                     $arg.num_args(1..)
396                         // Allow collecting arguments interleaved with flags
397                         .action($crate::ArgAction::Append)
398                 } else {
399                     $arg.action($crate::ArgAction::Append)
400                 }
401             },
402             $crate::ArgAction::SetTrue | $crate::ArgAction::Help | $crate::ArgAction::Version => {
403                 $arg.action($crate::ArgAction::Count)
404             }
405             action => {
406                 panic!("Unexpected action {action:?}")
407             }
408         };
409         let arg = $crate::arg_impl! {
410             @arg (arg) $($tail)*
411         };
412         arg
413     }};
414     (
415         @arg
416         ($arg:expr)
417         $help:literal
418     ) => {{
419         $arg.help($help)
420     }};
421     (
422         @arg
423         ($arg:expr)
424     ) => {{
425         $arg
426     }};
427 }
428 
429 /// Create an [`Arg`] from a usage string.
430 ///
431 /// Allows creation of basic settings for the [`Arg`].
432 ///
433 /// **NOTE**: Not all settings may be set using the usage string method. Some properties are
434 /// only available via the builder pattern.
435 ///
436 /// # Syntax
437 ///
438 /// Usage strings typically following the form:
439 ///
440 /// ```notrust
441 /// [explicit name] [short] [long] [value names] [...] [help string]
442 /// ```
443 ///
444 /// ### Explicit Name
445 ///
446 /// The name may be either a bare-word or a string, followed by a `:`, like `name:` or
447 /// `"name":`.
448 ///
449 /// *Note:* This is an optional field, if it's omitted the argument will use one of the additional
450 /// fields as the name using the following priority order:
451 ///
452 ///  1. Explicit Name
453 ///  2. Long
454 ///  3. Value Name
455 ///
456 /// See [`Arg::id`][crate::Arg::id].
457 ///
458 /// ### Short
459 ///
460 /// A short flag is a `-` followed by either a bare-character or quoted character, like `-f` or
461 /// `-'f'`.
462 ///
463 /// See [`Arg::short`][crate::Arg::short].
464 ///
465 /// ### Long
466 ///
467 /// A long flag is a `--` followed by either a bare-word or a string, like `--foo` or
468 /// `--"foo"`.
469 ///
470 /// **NOTE:** Dashes in the long name (e.g. `--foo-bar`) is not supported and quoting is required
471 /// (e.g. `--"foo-bar"`).
472 ///
473 /// See [`Arg::long`][crate::Arg::long].
474 ///
475 /// ### Values (Value Notation)
476 ///
477 /// This is set by placing bare-word between:
478 /// - `[]` like `[FOO]`
479 ///   - Positional argument: optional
480 ///   - Named argument: optional value
481 /// - `<>` like `<FOO>`: required
482 ///
483 /// See [`Arg::value_name`][crate::Arg::value_name].
484 ///
485 /// ### `...`
486 ///
487 /// `...` (three consecutive dots/periods) specifies that this argument may occur multiple
488 /// times (not to be confused with multiple values per occurrence).
489 ///
490 /// See [`ArgAction::Count`][crate::ArgAction::Count] and [`ArgAction::Append`][crate::ArgAction::Append].
491 ///
492 /// ### Help String
493 ///
494 /// The help string is denoted between a pair of double quotes `""` and may contain any
495 /// characters.
496 ///
497 /// # Examples
498 ///
499 /// ```rust
500 /// # use clap_builder as clap;
501 /// # use clap::{Command, Arg, arg};
502 /// let cmd = Command::new("prog")
503 ///     .args(&[
504 ///         arg!(--config <FILE> "a required file for the configuration and no short"),
505 ///         arg!(-d --debug ... "turns on debugging information and allows multiples"),
506 ///         arg!([input] "an optional input file to use")
507 ///     ]);
508 ///
509 /// let m = cmd.try_get_matches_from(["prog", "--config", "file.toml"]).unwrap();
510 /// assert_eq!(m.get_one::<String>("config").unwrap(), "file.toml");
511 /// assert_eq!(*m.get_one::<u8>("debug").unwrap(), 0);
512 /// assert_eq!(m.get_one::<String>("input"), None);
513 /// ```
514 /// [`Arg`]: crate::Arg
515 #[macro_export]
516 macro_rules! arg {
517     ( $name:ident: $($tail:tt)+ ) => {{
518         let arg = $crate::Arg::new($crate::arg_impl! { @string $name });
519         let arg = $crate::arg_impl! {
520             @arg (arg) $($tail)+
521         };
522         arg
523     }};
524     ( $($tail:tt)+ ) => {{
525         let arg = $crate::Arg::default();
526         let arg = $crate::arg_impl! {
527             @arg (arg) $($tail)+
528         };
529         debug_assert_ne!(arg.get_id(), "", "Without a value or long flag, the `name:` prefix is required");
530         arg
531     }};
532 }
533 
534 #[cfg(feature = "debug")]
535 macro_rules! debug {
536     ($($arg:tt)*) => ({
537         use std::fmt::Write as _;
538         let hint = anstyle::Style::new().dimmed();
539 
540         let module_path = module_path!();
541         let body = format!($($arg)*);
542         let mut styled = $crate::builder::StyledStr::new();
543         let _ = write!(styled, "{}[{module_path:>28}]{body}{}\n", hint.render(), hint.render_reset());
544         let color = $crate::output::fmt::Colorizer::new($crate::output::fmt::Stream::Stderr, $crate::ColorChoice::Auto).with_content(styled);
545         let _ = color.print();
546     })
547 }
548 
549 #[cfg(not(feature = "debug"))]
550 macro_rules! debug {
551     ($($arg:tt)*) => {};
552 }
553 
554 macro_rules! ok {
555     ($expr:expr) => {
556         match $expr {
557             Ok(val) => val,
558             Err(err) => {
559                 return Err(err);
560             }
561         }
562     };
563 }
564 
565 macro_rules! some {
566     ($expr:expr) => {
567         match $expr {
568             Some(val) => val,
569             None => {
570                 return None;
571             }
572         }
573     };
574 }
575