1 /// A convenience macro for loading the YAML file at compile time (relative to the current file, 2 /// like modules work). That YAML object can then be passed to this function. 3 /// 4 /// # Panics 5 /// 6 /// The YAML file must be properly formatted or this function will panic!(). A good way to 7 /// ensure this doesn't happen is to run your program with the `--help` switch. If this passes 8 /// without error, you needn't worry because the YAML is properly formatted. 9 /// 10 /// # Examples 11 /// 12 /// The following example shows how to load a properly formatted YAML file to build an instance 13 /// of an `App` struct. 14 /// 15 /// ```ignore 16 /// # #[macro_use] 17 /// # extern crate clap; 18 /// # use clap::App; 19 /// # fn main() { 20 /// let yml = load_yaml!("app.yml"); 21 /// let app = App::from_yaml(yml); 22 /// 23 /// // continued logic goes here, such as `app.get_matches()` etc. 24 /// # } 25 /// ``` 26 #[cfg(feature = "yaml")] 27 #[macro_export] 28 macro_rules! load_yaml { 29 ($yml:expr) => { 30 &::clap::YamlLoader::load_from_str(include_str!($yml)).expect("failed to load YAML file")[0] 31 }; 32 } 33 34 /// Convenience macro getting a typed value `T` where `T` implements [`std::str::FromStr`] from an 35 /// argument value. This macro returns a `Result<T,String>` which allows you as the developer to 36 /// decide what you'd like to do on a failed parse. There are two types of errors, parse failures 37 /// and those where the argument wasn't present (such as a non-required argument). You can use 38 /// it to get a single value, or a iterator as with the [`ArgMatches::values_of`] 39 /// 40 /// # Examples 41 /// 42 /// ```no_run 43 /// # #[macro_use] 44 /// # extern crate clap; 45 /// # use clap::App; 46 /// # fn main() { 47 /// let matches = App::new("myapp") 48 /// .arg_from_usage("[length] 'Set the length to use as a pos whole num, i.e. 20'") 49 /// .get_matches(); 50 /// 51 /// let len = value_t!(matches.value_of("length"), u32).unwrap_or_else(|e| e.exit()); 52 /// let also_len = value_t!(matches, "length", u32).unwrap_or_else(|e| e.exit()); 53 /// 54 /// println!("{} + 2: {}", len, len + 2); 55 /// # } 56 /// ``` 57 /// [`std::str::FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html 58 /// [`ArgMatches::values_of`]: ./struct.ArgMatches.html#method.values_of 59 /// [`Result<T,String>`]: https://doc.rust-lang.org/std/result/enum.Result.html 60 #[macro_export] 61 macro_rules! value_t { 62 ($m:ident, $v:expr, $t:ty) => { 63 value_t!($m.value_of($v), $t) 64 }; 65 ($m:ident.value_of($v:expr), $t:ty) => { 66 if let Some(v) = $m.value_of($v) { 67 match v.parse::<$t>() { 68 Ok(val) => Ok(val), 69 Err(_) => Err(::clap::Error::value_validation_auto(format!( 70 "The argument '{}' isn't a valid value", 71 v 72 ))), 73 } 74 } else { 75 Err(::clap::Error::argument_not_found_auto($v)) 76 } 77 }; 78 } 79 80 /// Convenience macro getting a typed value `T` where `T` implements [`std::str::FromStr`] or 81 /// exiting upon error, instead of returning a [`Result`] type. 82 /// 83 /// **NOTE:** This macro is for backwards compatibility sake. Prefer 84 /// [`value_t!(/* ... */).unwrap_or_else(|e| e.exit())`] 85 /// 86 /// # Examples 87 /// 88 /// ```no_run 89 /// # #[macro_use] 90 /// # extern crate clap; 91 /// # use clap::App; 92 /// # fn main() { 93 /// let matches = App::new("myapp") 94 /// .arg_from_usage("[length] 'Set the length to use as a pos whole num, i.e. 20'") 95 /// .get_matches(); 96 /// 97 /// let len = value_t_or_exit!(matches.value_of("length"), u32); 98 /// let also_len = value_t_or_exit!(matches, "length", u32); 99 /// 100 /// println!("{} + 2: {}", len, len + 2); 101 /// # } 102 /// ``` 103 /// [`std::str::FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html 104 /// [`Result`]: https://doc.rust-lang.org/std/result/enum.Result.html 105 /// [`value_t!(/* ... */).unwrap_or_else(|e| e.exit())`]: ./macro.value_t!.html 106 #[macro_export] 107 macro_rules! value_t_or_exit { 108 ($m:ident, $v:expr, $t:ty) => { 109 value_t_or_exit!($m.value_of($v), $t) 110 }; 111 ($m:ident.value_of($v:expr), $t:ty) => { 112 if let Some(v) = $m.value_of($v) { 113 match v.parse::<$t>() { 114 Ok(val) => val, 115 Err(_) => ::clap::Error::value_validation_auto(format!( 116 "The argument '{}' isn't a valid value", 117 v 118 )) 119 .exit(), 120 } 121 } else { 122 ::clap::Error::argument_not_found_auto($v).exit() 123 } 124 }; 125 } 126 127 /// Convenience macro getting a typed value [`Vec<T>`] where `T` implements [`std::str::FromStr`] 128 /// This macro returns a [`clap::Result<Vec<T>>`] which allows you as the developer to decide 129 /// what you'd like to do on a failed parse. 130 /// 131 /// # Examples 132 /// 133 /// ```no_run 134 /// # #[macro_use] 135 /// # extern crate clap; 136 /// # use clap::App; 137 /// # fn main() { 138 /// let matches = App::new("myapp") 139 /// .arg_from_usage("[seq]... 'A sequence of pos whole nums, i.e. 20 45'") 140 /// .get_matches(); 141 /// 142 /// let vals = values_t!(matches.values_of("seq"), u32).unwrap_or_else(|e| e.exit()); 143 /// for v in &vals { 144 /// println!("{} + 2: {}", v, v + 2); 145 /// } 146 /// 147 /// let vals = values_t!(matches, "seq", u32).unwrap_or_else(|e| e.exit()); 148 /// for v in &vals { 149 /// println!("{} + 2: {}", v, v + 2); 150 /// } 151 /// # } 152 /// ``` 153 /// [`std::str::FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html 154 /// [`Vec<T>`]: https://doc.rust-lang.org/std/vec/struct.Vec.html 155 /// [`clap::Result<Vec<T>>`]: ./type.Result.html 156 #[macro_export] 157 macro_rules! values_t { 158 ($m:ident, $v:expr, $t:ty) => { 159 values_t!($m.values_of($v), $t) 160 }; 161 ($m:ident.values_of($v:expr), $t:ty) => { 162 if let Some(vals) = $m.values_of($v) { 163 let mut tmp = vec![]; 164 let mut err = None; 165 for pv in vals { 166 match pv.parse::<$t>() { 167 Ok(rv) => tmp.push(rv), 168 Err(..) => { 169 err = Some(::clap::Error::value_validation_auto(format!( 170 "The argument '{}' isn't a valid value", 171 pv 172 ))); 173 break; 174 } 175 } 176 } 177 match err { 178 Some(e) => Err(e), 179 None => Ok(tmp), 180 } 181 } else { 182 Err(::clap::Error::argument_not_found_auto($v)) 183 } 184 }; 185 } 186 187 /// Convenience macro getting a typed value [`Vec<T>`] where `T` implements [`std::str::FromStr`] 188 /// or exiting upon error. 189 /// 190 /// **NOTE:** This macro is for backwards compatibility sake. Prefer 191 /// [`values_t!(/* ... */).unwrap_or_else(|e| e.exit())`] 192 /// 193 /// # Examples 194 /// 195 /// ```no_run 196 /// # #[macro_use] 197 /// # extern crate clap; 198 /// # use clap::App; 199 /// # fn main() { 200 /// let matches = App::new("myapp") 201 /// .arg_from_usage("[seq]... 'A sequence of pos whole nums, i.e. 20 45'") 202 /// .get_matches(); 203 /// 204 /// let vals = values_t_or_exit!(matches.values_of("seq"), u32); 205 /// for v in &vals { 206 /// println!("{} + 2: {}", v, v + 2); 207 /// } 208 /// 209 /// // type for example only 210 /// let vals: Vec<u32> = values_t_or_exit!(matches, "seq", u32); 211 /// for v in &vals { 212 /// println!("{} + 2: {}", v, v + 2); 213 /// } 214 /// # } 215 /// ``` 216 /// [`values_t!(/* ... */).unwrap_or_else(|e| e.exit())`]: ./macro.values_t!.html 217 /// [`std::str::FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html 218 /// [`Vec<T>`]: https://doc.rust-lang.org/std/vec/struct.Vec.html 219 #[macro_export] 220 macro_rules! values_t_or_exit { 221 ($m:ident, $v:expr, $t:ty) => { 222 values_t_or_exit!($m.values_of($v), $t) 223 }; 224 ($m:ident.values_of($v:expr), $t:ty) => { 225 if let Some(vals) = $m.values_of($v) { 226 vals.map(|v| { 227 v.parse::<$t>().unwrap_or_else(|_| { 228 ::clap::Error::value_validation_auto(format!( 229 "One or more arguments aren't valid values" 230 )) 231 .exit() 232 }) 233 }) 234 .collect::<Vec<$t>>() 235 } else { 236 ::clap::Error::argument_not_found_auto($v).exit() 237 } 238 }; 239 } 240 241 // _clap_count_exprs! is derived from https://github.com/DanielKeep/rust-grabbag 242 // commit: 82a35ca5d9a04c3b920622d542104e3310ee5b07 243 // License: MIT 244 // Copyright ⓒ 2015 grabbag contributors. 245 // Licensed under the MIT license (see LICENSE or <http://opensource.org 246 // /licenses/MIT>) or the Apache License, Version 2.0 (see LICENSE of 247 // <http://www.apache.org/licenses/LICENSE-2.0>), at your option. All 248 // files in the project carrying such notice may not be copied, modified, 249 // or distributed except according to those terms. 250 // 251 /// Counts the number of comma-delimited expressions passed to it. The result is a compile-time 252 /// evaluable expression, suitable for use as a static array size, or the value of a `const`. 253 /// 254 /// # Examples 255 /// 256 /// ``` 257 /// # #[macro_use] extern crate clap; 258 /// # fn main() { 259 /// const COUNT: usize = _clap_count_exprs!(a, 5+1, "hi there!".into_string()); 260 /// assert_eq!(COUNT, 3); 261 /// # } 262 /// ``` 263 #[macro_export] 264 macro_rules! _clap_count_exprs { 265 () => { 0 }; 266 ($e:expr) => { 1 }; 267 ($e:expr, $($es:expr),+) => { 1 + $crate::_clap_count_exprs!($($es),*) }; 268 } 269 270 /// Convenience macro to generate more complete enums with variants to be used as a type when 271 /// parsing arguments. This enum also provides a `variants()` function which can be used to 272 /// retrieve a `Vec<&'static str>` of the variant names, as well as implementing [`FromStr`] and 273 /// [`Display`] automatically. 274 /// 275 /// **NOTE:** Case insensitivity is supported for ASCII characters only. It's highly recommended to 276 /// use [`Arg::case_insensitive(true)`] for args that will be used with these enums 277 /// 278 /// **NOTE:** This macro automatically implements [`std::str::FromStr`] and [`std::fmt::Display`] 279 /// 280 /// **NOTE:** These enums support pub (or not) and uses of the `#[derive()]` traits 281 /// 282 /// # Examples 283 /// 284 /// ```rust 285 /// # #[macro_use] 286 /// # extern crate clap; 287 /// # use clap::{App, Arg}; 288 /// arg_enum!{ 289 /// #[derive(PartialEq, Debug)] 290 /// pub enum Foo { 291 /// Bar, 292 /// Baz, 293 /// Qux 294 /// } 295 /// } 296 /// // Foo enum can now be used via Foo::Bar, or Foo::Baz, etc 297 /// // and implements std::str::FromStr to use with the value_t! macros 298 /// fn main() { 299 /// let m = App::new("app") 300 /// .arg(Arg::from_usage("<foo> 'the foo'") 301 /// .possible_values(&Foo::variants()) 302 /// .case_insensitive(true)) 303 /// .get_matches_from(vec![ 304 /// "app", "baz" 305 /// ]); 306 /// let f = value_t!(m, "foo", Foo).unwrap_or_else(|e| e.exit()); 307 /// 308 /// assert_eq!(f, Foo::Baz); 309 /// } 310 /// ``` 311 /// [`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html 312 /// [`std::str::FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html 313 /// [`Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html 314 /// [`std::fmt::Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html 315 /// [`Arg::case_insensitive(true)`]: ./struct.Arg.html#method.case_insensitive 316 #[macro_export] 317 macro_rules! arg_enum { 318 (@as_item $($i:item)*) => ($($i)*); 319 (@impls ( $($tts:tt)* ) -> ($e:ident, $($v:ident),+)) => { 320 arg_enum!(@as_item 321 $($tts)* 322 323 impl ::std::str::FromStr for $e { 324 type Err = String; 325 326 fn from_str(s: &str) -> ::std::result::Result<Self,Self::Err> { 327 #[allow(deprecated, unused_imports)] 328 use ::std::ascii::AsciiExt; 329 match s { 330 $(stringify!($v) | 331 _ if s.eq_ignore_ascii_case(stringify!($v)) => Ok($e::$v)),+, 332 _ => Err({ 333 let v = vec![ 334 $(stringify!($v),)+ 335 ]; 336 format!("valid values: {}", 337 v.join(", ")) 338 }), 339 } 340 } 341 } 342 impl ::std::fmt::Display for $e { 343 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { 344 match *self { 345 $($e::$v => write!(f, stringify!($v)),)+ 346 } 347 } 348 } 349 impl $e { 350 #[allow(dead_code)] 351 pub fn variants() -> [&'static str; $crate::_clap_count_exprs!($(stringify!($v)),+)] { 352 [ 353 $(stringify!($v),)+ 354 ] 355 } 356 }); 357 }; 358 ($(#[$($m:meta),+])+ pub enum $e:ident { $($v:ident $(=$val:expr)*,)+ } ) => { 359 arg_enum!(@impls 360 ($(#[$($m),+])+ 361 pub enum $e { 362 $($v$(=$val)*),+ 363 }) -> ($e, $($v),+) 364 ); 365 }; 366 ($(#[$($m:meta),+])+ pub enum $e:ident { $($v:ident $(=$val:expr)*),+ } ) => { 367 arg_enum!(@impls 368 ($(#[$($m),+])+ 369 pub enum $e { 370 $($v$(=$val)*),+ 371 }) -> ($e, $($v),+) 372 ); 373 }; 374 ($(#[$($m:meta),+])+ enum $e:ident { $($v:ident $(=$val:expr)*,)+ } ) => { 375 arg_enum!(@impls 376 ($(#[$($m),+])+ 377 enum $e { 378 $($v$(=$val)*),+ 379 }) -> ($e, $($v),+) 380 ); 381 }; 382 ($(#[$($m:meta),+])+ enum $e:ident { $($v:ident $(=$val:expr)*),+ } ) => { 383 arg_enum!(@impls 384 ($(#[$($m),+])+ 385 enum $e { 386 $($v$(=$val)*),+ 387 }) -> ($e, $($v),+) 388 ); 389 }; 390 (pub enum $e:ident { $($v:ident $(=$val:expr)*,)+ } ) => { 391 arg_enum!(@impls 392 (pub enum $e { 393 $($v$(=$val)*),+ 394 }) -> ($e, $($v),+) 395 ); 396 }; 397 (pub enum $e:ident { $($v:ident $(=$val:expr)*),+ } ) => { 398 arg_enum!(@impls 399 (pub enum $e { 400 $($v$(=$val)*),+ 401 }) -> ($e, $($v),+) 402 ); 403 }; 404 (enum $e:ident { $($v:ident $(=$val:expr)*,)+ } ) => { 405 arg_enum!(@impls 406 (enum $e { 407 $($v$(=$val)*),+ 408 }) -> ($e, $($v),+) 409 ); 410 }; 411 (enum $e:ident { $($v:ident $(=$val:expr)*),+ } ) => { 412 arg_enum!(@impls 413 (enum $e { 414 $($v$(=$val)*),+ 415 }) -> ($e, $($v),+) 416 ); 417 }; 418 } 419 420 /// Allows you to pull the version from your Cargo.toml at compile time as 421 /// `MAJOR.MINOR.PATCH_PKGVERSION_PRE` 422 /// 423 /// # Examples 424 /// 425 /// ```no_run 426 /// # #[macro_use] 427 /// # extern crate clap; 428 /// # use clap::App; 429 /// # fn main() { 430 /// let m = App::new("app") 431 /// .version(crate_version!()) 432 /// .get_matches(); 433 /// # } 434 /// ``` 435 #[cfg(not(feature = "no_cargo"))] 436 #[macro_export] 437 macro_rules! crate_version { 438 () => { 439 "2.33.3" 440 }; 441 } 442 443 /// Allows you to pull the authors for the app from your Cargo.toml at 444 /// compile time in the form: 445 /// `"author1 lastname <author1@example.com>:author2 lastname <author2@example.com>"` 446 /// 447 /// You can replace the colons with a custom separator by supplying a 448 /// replacement string, so, for example, 449 /// `crate_authors!(",\n")` would become 450 /// `"author1 lastname <author1@example.com>,\nauthor2 lastname <author2@example.com>,\nauthor3 lastname <author3@example.com>"` 451 /// 452 /// # Examples 453 /// 454 /// ```no_run 455 /// # #[macro_use] 456 /// # extern crate clap; 457 /// # use clap::App; 458 /// # fn main() { 459 /// let m = App::new("app") 460 /// .author(crate_authors!("\n")) 461 /// .get_matches(); 462 /// # } 463 /// ``` 464 #[cfg(not(feature = "no_cargo"))] 465 #[macro_export] 466 macro_rules! crate_authors { 467 ($sep:expr) => {{ 468 use std::ops::Deref; 469 #[allow(deprecated)] 470 use std::sync::{Once, ONCE_INIT}; 471 472 #[allow(missing_copy_implementations)] 473 #[allow(dead_code)] 474 struct CargoAuthors { 475 __private_field: (), 476 }; 477 478 impl Deref for CargoAuthors { 479 type Target = str; 480 481 #[allow(unsafe_code)] 482 fn deref(&self) -> &'static str { 483 #[allow(deprecated)] 484 static ONCE: Once = ONCE_INIT; 485 static mut VALUE: *const String = 0 as *const String; 486 487 unsafe { 488 ONCE.call_once(|| { 489 let s = ["Kevin K. <kbknapp@gmail.com>"].join(":").replace(':', $sep); 490 VALUE = Box::into_raw(Box::new(s)); 491 }); 492 493 &(*VALUE)[..] 494 } 495 } 496 } 497 498 &*CargoAuthors { 499 __private_field: (), 500 } 501 }}; 502 () => { 503 ["Kevin K. <kbknapp@gmail.com>"].join(":") 504 }; 505 } 506 507 /// Allows you to pull the description from your Cargo.toml at compile time. 508 /// 509 /// # Examples 510 /// 511 /// ```no_run 512 /// # #[macro_use] 513 /// # extern crate clap; 514 /// # use clap::App; 515 /// # fn main() { 516 /// let m = App::new("app") 517 /// .about(crate_description!()) 518 /// .get_matches(); 519 /// # } 520 /// ``` 521 #[cfg(not(feature = "no_cargo"))] 522 #[macro_export] 523 macro_rules! crate_description { 524 () => { 525 "A simple to use, efficient, and full-featured Command Line Argument Parser\n" 526 }; 527 } 528 529 /// Allows you to pull the name from your Cargo.toml at compile time. 530 /// 531 /// # Examples 532 /// 533 /// ```no_run 534 /// # #[macro_use] 535 /// # extern crate clap; 536 /// # use clap::App; 537 /// # fn main() { 538 /// let m = App::new(crate_name!()) 539 /// .get_matches(); 540 /// # } 541 /// ``` 542 #[cfg(not(feature = "no_cargo"))] 543 #[macro_export] 544 macro_rules! crate_name { 545 () => { 546 "clap" 547 }; 548 } 549 550 /// Allows you to build the `App` instance from your Cargo.toml at compile time. 551 /// 552 /// Equivalent to using the `crate_*!` macros with their respective fields. 553 /// 554 /// Provided separator is for the [`crate_authors!`](macro.crate_authors.html) macro, 555 /// refer to the documentation therefor. 556 /// 557 /// **NOTE:** Changing the values in your `Cargo.toml` does not trigger a re-build automatically, 558 /// and therefore won't change the generated output until you recompile. 559 /// 560 /// **Pro Tip:** In some cases you can "trick" the compiler into triggering a rebuild when your 561 /// `Cargo.toml` is changed by including this in your `src/main.rs` file 562 /// `include_str!("../Cargo.toml");` 563 /// 564 /// # Examples 565 /// 566 /// ```no_run 567 /// # #[macro_use] 568 /// # extern crate clap; 569 /// # fn main() { 570 /// let m = app_from_crate!().get_matches(); 571 /// # } 572 /// ``` 573 #[cfg(not(feature = "no_cargo"))] 574 #[macro_export] 575 macro_rules! app_from_crate { 576 () => { 577 $crate::App::new(crate_name!()) 578 .version(crate_version!()) 579 .author(crate_authors!()) 580 .about(crate_description!()) 581 }; 582 ($sep:expr) => { 583 $crate::App::new(crate_name!()) 584 .version(crate_version!()) 585 .author(crate_authors!($sep)) 586 .about(crate_description!()) 587 }; 588 } 589 590 /// Build `App`, `Arg`s, `SubCommand`s and `Group`s with Usage-string like input 591 /// but without the associated parsing runtime cost. 592 /// 593 /// `clap_app!` also supports several shorthand syntaxes. 594 /// 595 /// # Examples 596 /// 597 /// ```no_run 598 /// # #[macro_use] 599 /// # extern crate clap; 600 /// # fn main() { 601 /// let matches = clap_app!(myapp => 602 /// (version: "1.0") 603 /// (author: "Kevin K. <kbknapp@gmail.com>") 604 /// (about: "Does awesome things") 605 /// (@arg CONFIG: -c --config +takes_value "Sets a custom config file") 606 /// (@arg INPUT: +required "Sets the input file to use") 607 /// (@arg debug: -d ... "Sets the level of debugging information") 608 /// (@group difficulty => 609 /// (@arg hard: -h --hard "Sets hard mode") 610 /// (@arg normal: -n --normal "Sets normal mode") 611 /// (@arg easy: -e --easy "Sets easy mode") 612 /// ) 613 /// (@subcommand test => 614 /// (about: "controls testing features") 615 /// (version: "1.3") 616 /// (author: "Someone E. <someone_else@other.com>") 617 /// (@arg verbose: -v --verbose "Print test information verbosely") 618 /// ) 619 /// ) 620 /// .get_matches(); 621 /// # } 622 /// ``` 623 /// # Shorthand Syntax for Args 624 /// 625 /// * A single hyphen followed by a character (such as `-c`) sets the [`Arg::short`] 626 /// * A double hyphen followed by a character or word (such as `--config`) sets [`Arg::long`] 627 /// * If one wishes to use a [`Arg::long`] with a hyphen inside (i.e. `--config-file`), you 628 /// must use `--("config-file")` due to limitations of the Rust macro system. 629 /// * Three dots (`...`) sets [`Arg::multiple(true)`] 630 /// * Angled brackets after either a short or long will set [`Arg::value_name`] and 631 /// `Arg::required(true)` such as `--config <FILE>` = `Arg::value_name("FILE")` and 632 /// `Arg::required(true)` 633 /// * Square brackets after either a short or long will set [`Arg::value_name`] and 634 /// `Arg::required(false)` such as `--config [FILE]` = `Arg::value_name("FILE")` and 635 /// `Arg::required(false)` 636 /// * There are short hand syntaxes for Arg methods that accept booleans 637 /// * A plus sign will set that method to `true` such as `+required` = `Arg::required(true)` 638 /// * An exclamation will set that method to `false` such as `!required` = `Arg::required(false)` 639 /// * A `#{min, max}` will set [`Arg::min_values(min)`] and [`Arg::max_values(max)`] 640 /// * An asterisk (`*`) will set `Arg::required(true)` 641 /// * Curly brackets around a `fn` will set [`Arg::validator`] as in `{fn}` = `Arg::validator(fn)` 642 /// * An Arg method that accepts a string followed by square brackets will set that method such as 643 /// `conflicts_with[FOO]` will set `Arg::conflicts_with("FOO")` (note the lack of quotes around 644 /// `FOO` in the macro) 645 /// * An Arg method that takes a string and can be set multiple times (such as 646 /// [`Arg::conflicts_with`]) followed by square brackets and a list of values separated by spaces 647 /// will set that method such as `conflicts_with[FOO BAR BAZ]` will set 648 /// `Arg::conflicts_with("FOO")`, `Arg::conflicts_with("BAR")`, and `Arg::conflicts_with("BAZ")` 649 /// (note the lack of quotes around the values in the macro) 650 /// 651 /// # Shorthand Syntax for Groups 652 /// 653 /// * There are short hand syntaxes for `ArgGroup` methods that accept booleans 654 /// * A plus sign will set that method to `true` such as `+required` = `ArgGroup::required(true)` 655 /// * An exclamation will set that method to `false` such as `!required` = `ArgGroup::required(false)` 656 /// 657 /// [`Arg::short`]: ./struct.Arg.html#method.short 658 /// [`Arg::long`]: ./struct.Arg.html#method.long 659 /// [`Arg::multiple(true)`]: ./struct.Arg.html#method.multiple 660 /// [`Arg::value_name`]: ./struct.Arg.html#method.value_name 661 /// [`Arg::min_values(min)`]: ./struct.Arg.html#method.min_values 662 /// [`Arg::max_values(max)`]: ./struct.Arg.html#method.max_values 663 /// [`Arg::validator`]: ./struct.Arg.html#method.validator 664 /// [`Arg::conflicts_with`]: ./struct.Arg.html#method.conflicts_with 665 #[macro_export] 666 macro_rules! clap_app { 667 (@app ($builder:expr)) => { $builder }; 668 (@app ($builder:expr) (@arg ($name:expr): $($tail:tt)*) $($tt:tt)*) => { 669 clap_app!{ @app 670 ($builder.arg( 671 clap_app!{ @arg ($crate::Arg::with_name($name)) (-) $($tail)* })) 672 $($tt)* 673 } 674 }; 675 (@app ($builder:expr) (@arg $name:ident: $($tail:tt)*) $($tt:tt)*) => { 676 clap_app!{ @app 677 ($builder.arg( 678 clap_app!{ @arg ($crate::Arg::with_name(stringify!($name))) (-) $($tail)* })) 679 $($tt)* 680 } 681 }; 682 (@app ($builder:expr) (@setting $setting:ident) $($tt:tt)*) => { 683 clap_app!{ @app 684 ($builder.setting($crate::AppSettings::$setting)) 685 $($tt)* 686 } 687 }; 688 // Treat the application builder as an argument to set its attributes 689 (@app ($builder:expr) (@attributes $($attr:tt)*) $($tt:tt)*) => { 690 clap_app!{ @app (clap_app!{ @arg ($builder) $($attr)* }) $($tt)* } 691 }; 692 (@app ($builder:expr) (@group $name:ident => $($tail:tt)*) $($tt:tt)*) => { 693 clap_app!{ @app 694 (clap_app!{ @group ($builder, $crate::ArgGroup::with_name(stringify!($name))) $($tail)* }) 695 $($tt)* 696 } 697 }; 698 (@app ($builder:expr) (@group $name:ident !$ident:ident => $($tail:tt)*) $($tt:tt)*) => { 699 clap_app!{ @app 700 (clap_app!{ @group ($builder, $crate::ArgGroup::with_name(stringify!($name)).$ident(false)) $($tail)* }) 701 $($tt)* 702 } 703 }; 704 (@app ($builder:expr) (@group $name:ident +$ident:ident => $($tail:tt)*) $($tt:tt)*) => { 705 clap_app!{ @app 706 (clap_app!{ @group ($builder, $crate::ArgGroup::with_name(stringify!($name)).$ident(true)) $($tail)* }) 707 $($tt)* 708 } 709 }; 710 // Handle subcommand creation 711 (@app ($builder:expr) (@subcommand $name:ident => $($tail:tt)*) $($tt:tt)*) => { 712 clap_app!{ @app 713 ($builder.subcommand( 714 clap_app!{ @app ($crate::SubCommand::with_name(stringify!($name))) $($tail)* } 715 )) 716 $($tt)* 717 } 718 }; 719 // Yaml like function calls - used for setting various meta directly against the app 720 (@app ($builder:expr) ($ident:ident: $($v:expr),*) $($tt:tt)*) => { 721 // clap_app!{ @app ($builder.$ident($($v),*)) $($tt)* } 722 clap_app!{ @app 723 ($builder.$ident($($v),*)) 724 $($tt)* 725 } 726 }; 727 728 // Add members to group and continue argument handling with the parent builder 729 (@group ($builder:expr, $group:expr)) => { $builder.group($group) }; 730 // Treat the group builder as an argument to set its attributes 731 (@group ($builder:expr, $group:expr) (@attributes $($attr:tt)*) $($tt:tt)*) => { 732 clap_app!{ @group ($builder, clap_app!{ @arg ($group) (-) $($attr)* }) $($tt)* } 733 }; 734 (@group ($builder:expr, $group:expr) (@arg $name:ident: $($tail:tt)*) $($tt:tt)*) => { 735 clap_app!{ @group 736 (clap_app!{ @app ($builder) (@arg $name: $($tail)*) }, 737 $group.arg(stringify!($name))) 738 $($tt)* 739 } 740 }; 741 742 // No more tokens to munch 743 (@arg ($arg:expr) $modes:tt) => { $arg }; 744 // Shorthand tokens influenced by the usage_string 745 (@arg ($arg:expr) $modes:tt --($long:expr) $($tail:tt)*) => { 746 clap_app!{ @arg ($arg.long($long)) $modes $($tail)* } 747 }; 748 (@arg ($arg:expr) $modes:tt --$long:ident $($tail:tt)*) => { 749 clap_app!{ @arg ($arg.long(stringify!($long))) $modes $($tail)* } 750 }; 751 (@arg ($arg:expr) $modes:tt -$short:ident $($tail:tt)*) => { 752 clap_app!{ @arg ($arg.short(stringify!($short))) $modes $($tail)* } 753 }; 754 (@arg ($arg:expr) (-) <$var:ident> $($tail:tt)*) => { 755 clap_app!{ @arg ($arg.value_name(stringify!($var))) (+) +takes_value +required $($tail)* } 756 }; 757 (@arg ($arg:expr) (+) <$var:ident> $($tail:tt)*) => { 758 clap_app!{ @arg ($arg.value_name(stringify!($var))) (+) $($tail)* } 759 }; 760 (@arg ($arg:expr) (-) [$var:ident] $($tail:tt)*) => { 761 clap_app!{ @arg ($arg.value_name(stringify!($var))) (+) +takes_value $($tail)* } 762 }; 763 (@arg ($arg:expr) (+) [$var:ident] $($tail:tt)*) => { 764 clap_app!{ @arg ($arg.value_name(stringify!($var))) (+) $($tail)* } 765 }; 766 (@arg ($arg:expr) $modes:tt ... $($tail:tt)*) => { 767 clap_app!{ @arg ($arg) $modes +multiple $($tail)* } 768 }; 769 // Shorthand magic 770 (@arg ($arg:expr) $modes:tt #{$n:expr, $m:expr} $($tail:tt)*) => { 771 clap_app!{ @arg ($arg) $modes min_values($n) max_values($m) $($tail)* } 772 }; 773 (@arg ($arg:expr) $modes:tt * $($tail:tt)*) => { 774 clap_app!{ @arg ($arg) $modes +required $($tail)* } 775 }; 776 // !foo -> .foo(false) 777 (@arg ($arg:expr) $modes:tt !$ident:ident $($tail:tt)*) => { 778 clap_app!{ @arg ($arg.$ident(false)) $modes $($tail)* } 779 }; 780 // +foo -> .foo(true) 781 (@arg ($arg:expr) $modes:tt +$ident:ident $($tail:tt)*) => { 782 clap_app!{ @arg ($arg.$ident(true)) $modes $($tail)* } 783 }; 784 // Validator 785 (@arg ($arg:expr) $modes:tt {$fn_:expr} $($tail:tt)*) => { 786 clap_app!{ @arg ($arg.validator($fn_)) $modes $($tail)* } 787 }; 788 (@as_expr $expr:expr) => { $expr }; 789 // Help 790 (@arg ($arg:expr) $modes:tt $desc:tt) => { $arg.help(clap_app!{ @as_expr $desc }) }; 791 // Handle functions that need to be called multiple times for each argument 792 (@arg ($arg:expr) $modes:tt $ident:ident[$($target:ident)*] $($tail:tt)*) => { 793 clap_app!{ @arg ($arg $( .$ident(stringify!($target)) )*) $modes $($tail)* } 794 }; 795 // Inherit builder's functions, e.g. `index(2)`, `requires_if("val", "arg")` 796 (@arg ($arg:expr) $modes:tt $ident:ident($($expr:expr),*) $($tail:tt)*) => { 797 clap_app!{ @arg ($arg.$ident($($expr),*)) $modes $($tail)* } 798 }; 799 // Inherit builder's functions with trailing comma, e.g. `index(2,)`, `requires_if("val", "arg",)` 800 (@arg ($arg:expr) $modes:tt $ident:ident($($expr:expr,)*) $($tail:tt)*) => { 801 clap_app!{ @arg ($arg.$ident($($expr),*)) $modes $($tail)* } 802 }; 803 804 // Build a subcommand outside of an app. 805 (@subcommand $name:ident => $($tail:tt)*) => { 806 clap_app!{ @app ($crate::SubCommand::with_name(stringify!($name))) $($tail)* } 807 }; 808 // Start the magic 809 (($name:expr) => $($tail:tt)*) => {{ 810 clap_app!{ @app ($crate::App::new($name)) $($tail)*} 811 }}; 812 813 ($name:ident => $($tail:tt)*) => {{ 814 clap_app!{ @app ($crate::App::new(stringify!($name))) $($tail)*} 815 }}; 816 } 817 818 macro_rules! impl_settings { 819 ($n:ident, $($v:ident => $c:path),+) => { 820 pub fn set(&mut self, s: $n) { 821 match s { 822 $($n::$v => self.0.insert($c)),+ 823 } 824 } 825 826 pub fn unset(&mut self, s: $n) { 827 match s { 828 $($n::$v => self.0.remove($c)),+ 829 } 830 } 831 832 pub fn is_set(&self, s: $n) -> bool { 833 match s { 834 $($n::$v => self.0.contains($c)),+ 835 } 836 } 837 }; 838 } 839 840 // Convenience for writing to stderr thanks to https://github.com/BurntSushi 841 macro_rules! wlnerr( 842 ($($arg:tt)*) => ({ 843 use std::io::{Write, stderr}; 844 writeln!(&mut stderr(), $($arg)*).ok(); 845 }) 846 ); 847 848 #[cfg(feature = "debug")] 849 #[cfg_attr(feature = "debug", macro_use)] 850 #[cfg_attr(feature = "debug", allow(unused_macros))] 851 mod debug_macros { 852 macro_rules! debugln { 853 ($fmt:expr) => (println!(concat!("DEBUG:clap:", $fmt))); 854 ($fmt:expr, $($arg:tt)*) => (println!(concat!("DEBUG:clap:",$fmt), $($arg)*)); 855 } 856 macro_rules! sdebugln { 857 ($fmt:expr) => (println!($fmt)); 858 ($fmt:expr, $($arg:tt)*) => (println!($fmt, $($arg)*)); 859 } 860 macro_rules! debug { 861 ($fmt:expr) => (print!(concat!("DEBUG:clap:", $fmt))); 862 ($fmt:expr, $($arg:tt)*) => (print!(concat!("DEBUG:clap:",$fmt), $($arg)*)); 863 } 864 macro_rules! sdebug { 865 ($fmt:expr) => (print!($fmt)); 866 ($fmt:expr, $($arg:tt)*) => (print!($fmt, $($arg)*)); 867 } 868 } 869 870 #[cfg(not(feature = "debug"))] 871 #[cfg_attr(not(feature = "debug"), macro_use)] 872 mod debug_macros { 873 macro_rules! debugln { 874 ($fmt:expr) => {}; 875 ($fmt:expr, $($arg:tt)*) => {}; 876 } 877 macro_rules! sdebugln { 878 ($fmt:expr) => {}; 879 ($fmt:expr, $($arg:tt)*) => {}; 880 } 881 macro_rules! debug { 882 ($fmt:expr) => {}; 883 ($fmt:expr, $($arg:tt)*) => {}; 884 } 885 } 886 887 // Helper/deduplication macro for printing the correct number of spaces in help messages 888 // used in: 889 // src/args/arg_builder/*.rs 890 // src/app/mod.rs 891 macro_rules! write_nspaces { 892 ($dst:expr, $num:expr) => {{ 893 debugln!("write_spaces!: num={}", $num); 894 for _ in 0..$num { 895 $dst.write_all(b" ")?; 896 } 897 }}; 898 } 899 900 // convenience macro for remove an item from a vec 901 //macro_rules! vec_remove_all { 902 // ($vec:expr, $to_rem:expr) => { 903 // debugln!("vec_remove_all! to_rem={:?}", $to_rem); 904 // for i in (0 .. $vec.len()).rev() { 905 // let should_remove = $to_rem.any(|name| name == &$vec[i]); 906 // if should_remove { $vec.swap_remove(i); } 907 // } 908 // }; 909 //} 910 macro_rules! find_from { 911 ($_self:expr, $arg_name:expr, $from:ident, $matcher:expr) => {{ 912 let mut ret = None; 913 for k in $matcher.arg_names() { 914 if let Some(f) = find_by_name!($_self, k, flags, iter) { 915 if let Some(ref v) = f.$from() { 916 if v.contains($arg_name) { 917 ret = Some(f.to_string()); 918 } 919 } 920 } 921 if let Some(o) = find_by_name!($_self, k, opts, iter) { 922 if let Some(ref v) = o.$from() { 923 if v.contains(&$arg_name) { 924 ret = Some(o.to_string()); 925 } 926 } 927 } 928 if let Some(pos) = find_by_name!($_self, k, positionals, values) { 929 if let Some(ref v) = pos.$from() { 930 if v.contains($arg_name) { 931 ret = Some(pos.b.name.to_owned()); 932 } 933 } 934 } 935 } 936 ret 937 }}; 938 } 939 940 //macro_rules! find_name_from { 941 // ($_self:expr, $arg_name:expr, $from:ident, $matcher:expr) => {{ 942 // let mut ret = None; 943 // for k in $matcher.arg_names() { 944 // if let Some(f) = find_by_name!($_self, k, flags, iter) { 945 // if let Some(ref v) = f.$from() { 946 // if v.contains($arg_name) { 947 // ret = Some(f.b.name); 948 // } 949 // } 950 // } 951 // if let Some(o) = find_by_name!($_self, k, opts, iter) { 952 // if let Some(ref v) = o.$from() { 953 // if v.contains(&$arg_name) { 954 // ret = Some(o.b.name); 955 // } 956 // } 957 // } 958 // if let Some(pos) = find_by_name!($_self, k, positionals, values) { 959 // if let Some(ref v) = pos.$from() { 960 // if v.contains($arg_name) { 961 // ret = Some(pos.b.name); 962 // } 963 // } 964 // } 965 // } 966 // ret 967 // }}; 968 //} 969 970 macro_rules! find_any_by_name { 971 ($p:expr, $name:expr) => {{ 972 fn as_trait_obj<'a, 'b, T: AnyArg<'a, 'b>>(x: &T) -> &AnyArg<'a, 'b> { 973 x 974 } 975 find_by_name!($p, $name, flags, iter) 976 .map(as_trait_obj) 977 .or(find_by_name!($p, $name, opts, iter) 978 .map(as_trait_obj) 979 .or(find_by_name!($p, $name, positionals, values).map(as_trait_obj))) 980 }}; 981 } 982 // Finds an arg by name 983 macro_rules! find_by_name { 984 ($p:expr, $name:expr, $what:ident, $how:ident) => { 985 $p.$what.$how().find(|o| o.b.name == $name) 986 }; 987 } 988 989 // Finds an option including if it's aliased 990 macro_rules! find_opt_by_long { 991 (@os $_self:ident, $long:expr) => {{ 992 _find_by_long!($_self, $long, opts) 993 }}; 994 ($_self:ident, $long:expr) => {{ 995 _find_by_long!($_self, $long, opts) 996 }}; 997 } 998 999 macro_rules! find_flag_by_long { 1000 (@os $_self:ident, $long:expr) => {{ 1001 _find_by_long!($_self, $long, flags) 1002 }}; 1003 ($_self:ident, $long:expr) => {{ 1004 _find_by_long!($_self, $long, flags) 1005 }}; 1006 } 1007 1008 macro_rules! _find_by_long { 1009 ($_self:ident, $long:expr, $what:ident) => {{ 1010 $_self 1011 .$what 1012 .iter() 1013 .filter(|a| a.s.long.is_some()) 1014 .find(|a| { 1015 a.s.long.unwrap() == $long 1016 || (a.s.aliases.is_some() 1017 && a.s 1018 .aliases 1019 .as_ref() 1020 .unwrap() 1021 .iter() 1022 .any(|&(alias, _)| alias == $long)) 1023 }) 1024 }}; 1025 } 1026 1027 // Finds an option 1028 macro_rules! find_opt_by_short { 1029 ($_self:ident, $short:expr) => {{ 1030 _find_by_short!($_self, $short, opts) 1031 }}; 1032 } 1033 1034 macro_rules! find_flag_by_short { 1035 ($_self:ident, $short:expr) => {{ 1036 _find_by_short!($_self, $short, flags) 1037 }}; 1038 } 1039 1040 macro_rules! _find_by_short { 1041 ($_self:ident, $short:expr, $what:ident) => {{ 1042 $_self 1043 .$what 1044 .iter() 1045 .filter(|a| a.s.short.is_some()) 1046 .find(|a| a.s.short.unwrap() == $short) 1047 }}; 1048 } 1049 1050 macro_rules! find_subcmd { 1051 ($_self:expr, $sc:expr) => {{ 1052 $_self.subcommands.iter().find(|s| { 1053 &*s.p.meta.name == $sc 1054 || (s.p.meta.aliases.is_some() 1055 && s.p 1056 .meta 1057 .aliases 1058 .as_ref() 1059 .unwrap() 1060 .iter() 1061 .any(|&(n, _)| n == $sc)) 1062 }) 1063 }}; 1064 } 1065 1066 macro_rules! shorts { 1067 ($_self:ident) => {{ 1068 _shorts_longs!($_self, short) 1069 }}; 1070 } 1071 1072 macro_rules! longs { 1073 ($_self:ident) => {{ 1074 _shorts_longs!($_self, long) 1075 }}; 1076 } 1077 1078 macro_rules! _shorts_longs { 1079 ($_self:ident, $what:ident) => {{ 1080 $_self 1081 .flags 1082 .iter() 1083 .filter(|f| f.s.$what.is_some()) 1084 .map(|f| f.s.$what.as_ref().unwrap()) 1085 .chain( 1086 $_self 1087 .opts 1088 .iter() 1089 .filter(|o| o.s.$what.is_some()) 1090 .map(|o| o.s.$what.as_ref().unwrap()), 1091 ) 1092 }}; 1093 } 1094 1095 macro_rules! arg_names { 1096 ($_self:ident) => {{ 1097 _names!(@args $_self) 1098 }}; 1099 } 1100 1101 macro_rules! sc_names { 1102 ($_self:ident) => {{ 1103 _names!(@sc $_self) 1104 }}; 1105 } 1106 1107 macro_rules! _names { 1108 (@args $_self:ident) => {{ 1109 $_self.flags.iter().map(|f| &*f.b.name).chain( 1110 $_self 1111 .opts 1112 .iter() 1113 .map(|o| &*o.b.name) 1114 .chain($_self.positionals.values().map(|p| &*p.b.name)), 1115 ) 1116 }}; 1117 (@sc $_self:ident) => {{ 1118 $_self.subcommands.iter().map(|s| &*s.p.meta.name).chain( 1119 $_self 1120 .subcommands 1121 .iter() 1122 .filter(|s| s.p.meta.aliases.is_some()) 1123 .flat_map(|s| s.p.meta.aliases.as_ref().unwrap().iter().map(|&(n, _)| n)), 1124 ) 1125 }}; 1126 } 1127