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 <author1@example.com>:author2 lastname <author2@example.com>"`
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 <author1@example.com>,\nauthor2 lastname <author2@example.com>,\nauthor3 lastname <author3@example.com>"`
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