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