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