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