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