1 // Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu> 2 // 3 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or 4 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license 5 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your 6 // option. This file may not be copied, modified, or distributed 7 // except according to those terms. 8 9 #![deny(missing_docs)] 10 11 //! This crate defines the `StructOpt` trait and its custom derive. 12 //! 13 //! ## Features 14 //! 15 //! If you want to disable all the `clap` features (colors, 16 //! suggestions, ..) add `default-features = false` to the `structopt` 17 //! dependency: 18 //! 19 //! ```toml 20 //! [dependencies] 21 //! structopt = { version = "0.2", default-features = false } 22 //! ``` 23 //! 24 //! 25 //! Support for [`paw`](https://github.com/rust-cli/paw) (the 26 //! `Command line argument paw-rser abstraction for main`) is disabled 27 //! by default, but can be enabled in the `structopt` dependency 28 //! with the feature `paw`: 29 //! 30 //! ```toml 31 //! [dependencies] 32 //! structopt = { version = "0.2", features = [ "paw" ] } 33 //! paw = "1.0" 34 //! ``` 35 //! 36 //! ## How to `derive(StructOpt)` 37 //! 38 //! First, let's look at an example: 39 //! 40 //! ```should_panic 41 //! #[macro_use] 42 //! extern crate structopt; 43 //! 44 //! use std::path::PathBuf; 45 //! use structopt::StructOpt; 46 //! 47 //! #[derive(Debug, StructOpt)] 48 //! #[structopt(name = "example", about = "An example of StructOpt usage.")] 49 //! struct Opt { 50 //! /// Activate debug mode 51 //! #[structopt(short = "d", long = "debug")] 52 //! debug: bool, 53 //! /// Set speed 54 //! #[structopt(short = "s", long = "speed", default_value = "42")] 55 //! speed: f64, 56 //! /// Input file 57 //! #[structopt(parse(from_os_str))] 58 //! input: PathBuf, 59 //! /// Output file, stdout if not present 60 //! #[structopt(parse(from_os_str))] 61 //! output: Option<PathBuf>, 62 //! } 63 //! 64 //! fn main() { 65 //! let opt = Opt::from_args(); 66 //! println!("{:?}", opt); 67 //! } 68 //! ``` 69 //! 70 //! So `derive(StructOpt)` tells Rust to generate a command line parser, 71 //! and the various `structopt` attributes are simply 72 //! used for additional parameters. 73 //! 74 //! First, define a struct, whatever its name. This structure will 75 //! correspond to a `clap::App`. Every method of `clap::App` in the 76 //! form of `fn function_name(self, &str)` can be used through attributes 77 //! placed on the struct. In our example above, the `about` attribute 78 //! will become an `.about("An example of StructOpt usage.")` call on the 79 //! generated `clap::App`. There are a few attributes that will default 80 //! if not specified: 81 //! 82 //! - `name`: The binary name displayed in help messages. Defaults 83 //! to the crate name given by Cargo. 84 //! - `version`: Defaults to the crate version given by Cargo. 85 //! - `author`: Defaults to the crate author name given by Cargo. 86 //! - `about`: Defaults to the crate description given by Cargo. 87 //! 88 //! Methods from `clap::App` that don't take an `&str` can be called by 89 //! wrapping them in `raw()`, e.g. to activate colored help text: 90 //! 91 //! ``` 92 //! #[macro_use] 93 //! extern crate structopt; 94 //! 95 //! use structopt::StructOpt; 96 //! 97 //! #[derive(StructOpt, Debug)] 98 //! #[structopt(raw(setting = "structopt::clap::AppSettings::ColoredHelp"))] 99 //! struct Opt { 100 //! #[structopt(short = "s")] 101 //! speed: bool, 102 //! #[structopt(short = "d")] 103 //! debug: bool, 104 //! } 105 //! # fn main() {} 106 //! ``` 107 //! 108 //! Then, each field of the struct not marked as a subcommand corresponds 109 //! to a `clap::Arg`. As with the struct attributes, every method of 110 //! `clap::Arg` in the form of `fn function_name(self, &str)` can be used 111 //! through specifying it as an attribute. The `name` attribute can be used 112 //! to customize the `Arg::with_name()` call (defaults to the field name in 113 //! kebab-case). 114 //! For functions that do not take a `&str` as argument, the attribute can be 115 //! wrapped in `raw()`, e. g. `raw(aliases = r#"&["alias"]"#, next_line_help = "true")`. 116 //! 117 //! The type of the field gives the kind of argument: 118 //! 119 //! Type | Effect | Added method call to `clap::Arg` 120 //! -----------------------------|---------------------------------------------------|-------------------------------------- 121 //! `bool` | `true` if the flag is present | `.takes_value(false).multiple(false)` 122 //! `Option<T: FromStr>` | optional positional argument or option | `.takes_value(true).multiple(false)` 123 //! `Option<Option<T: FromStr>>` | optional option with optional value | `.takes_value(true).multiple(false).min_values(0).max_values(1)` 124 //! `Vec<T: FromStr>` | list of options or the other positional arguments | `.takes_value(true).multiple(true)` 125 //! `T: FromStr` | required option or positional argument | `.takes_value(true).multiple(false).required(!has_default)` 126 //! 127 //! The `FromStr` trait is used to convert the argument to the given 128 //! type, and the `Arg::validator` method is set to a method using 129 //! `to_string()` (`FromStr::Err` must implement `std::fmt::Display`). 130 //! If you would like to use a custom string parser other than `FromStr`, see 131 //! the [same titled section](#custom-string-parsers) below. 132 //! 133 //! Thus, the `speed` argument is generated as: 134 //! 135 //! ``` 136 //! # extern crate clap; 137 //! # fn parse_validator<T>(_: String) -> Result<(), String> { unimplemented!() } 138 //! # fn main() { 139 //! clap::Arg::with_name("speed") 140 //! .takes_value(true) 141 //! .multiple(false) 142 //! .required(false) 143 //! .validator(parse_validator::<f64>) 144 //! .short("s") 145 //! .long("speed") 146 //! .help("Set speed") 147 //! .default_value("42"); 148 //! # } 149 //! ``` 150 //! 151 //! ## Specifying argument types 152 //! 153 //! There are three types of arguments that can be supplied to each 154 //! (sub-)command: 155 //! 156 //! - short (e.g. `-h`), 157 //! - long (e.g. `--help`) 158 //! - and positional. 159 //! 160 //! Like clap, structopt defaults to creating positional arguments. 161 //! 162 //! If you want to generate a long argument you can specify either 163 //! `long = $NAME`, or just `long` to get a long flag generated using 164 //! the field name. The generated casing style can be modified using 165 //! the `rename_all` attribute. See the `rename_all` example for more. 166 //! 167 //! For short arguments, `short` will use the first letter of the 168 //! field name by default, but just like the long option it's also 169 //! possible to use a custom letter through `short = $LETTER`. 170 //! 171 //! If an argument is renamed using `name = $NAME` any following call to 172 //! `short` or `long` will use the new name. 173 //! 174 //! ``` 175 //! #[macro_use] 176 //! extern crate structopt; 177 //! 178 //! use structopt::StructOpt; 179 //! 180 //! #[derive(StructOpt)] 181 //! #[structopt(rename_all = "kebab-case")] 182 //! struct Opt { 183 //! /// This option can be specified with something like `--foo-option 184 //! /// value` or `--foo-option=value` 185 //! #[structopt(long)] 186 //! foo_option: String, 187 //! 188 //! /// This option can be specified with something like `-b value` (but 189 //! /// not `--bar-option value`). 190 //! #[structopt(short)] 191 //! bar_option: String, 192 //! 193 //! /// This option can be specified either `--baz value` or `-z value`. 194 //! #[structopt(short = "z", long = "baz")] 195 //! baz_option: String, 196 //! 197 //! /// This option can be specified either by `--custom value` or 198 //! /// `-c value`. 199 //! #[structopt(name = "custom", long, short)] 200 //! custom_option: String, 201 //! 202 //! /// This option is positional, meaning it is the first unadorned string 203 //! /// you provide (multiple others could follow). 204 //! my_positional: String, 205 //! } 206 //! 207 //! # fn main() { 208 //! # Opt::from_clap(&Opt::clap().get_matches_from( 209 //! # &["test", "--foo-option", "", "-b", "", "--baz", "", "--custom", "", "positional"])); 210 //! # } 211 //! ``` 212 //! 213 //! ## Help messages 214 //! 215 //! Help messages for the whole binary or individual arguments can be 216 //! specified using the `about` attribute on the struct and the `help` 217 //! attribute on the field, as we've already seen. For convenience, 218 //! they can also be specified using doc comments. For example: 219 //! 220 //! ``` 221 //! # #[macro_use] extern crate structopt; 222 //! #[derive(StructOpt)] 223 //! #[structopt(name = "foo")] 224 //! /// The help message that will be displayed when passing `--help`. 225 //! struct Foo { 226 //! #[structopt(short = "b")] 227 //! /// The description for the arg that will be displayed when passing `--help`. 228 //! bar: String 229 //! } 230 //! # fn main() {} 231 //! ``` 232 //! 233 //! If it is necessary or wanted to provide a more complex help message then the 234 //! previous used ones, it could still be a good idea to distinguish between the 235 //! actual help message a short summary. In this case `about` and `help` should 236 //! only contain the short and concise form while the two additional arguments 237 //! `long_about` and `long_help` can be used to store a descriptive and more in 238 //! depth message. 239 //! 240 //! If both - the short and the long version of the argument - are present, 241 //! the user can later chose between the short summary (`-h`) and the long 242 //! descriptive version (`--help`) of the help message. Also in case 243 //! of subcommands the short help message will automatically be used for the 244 //! command description inside the parents help message and the long version 245 //! as command description if help is requested on the actual subcommand. 246 //! 247 //! This feature can also be used with doc comments instead of arguments through 248 //! proper comment formatting. To be activated it requires, that the first line 249 //! of the comment is separated from the rest of the comment through an empty line. 250 //! In this case the first line is used as summary and the whole comment represents 251 //! the long descriptive message. 252 //! 253 //! ``` 254 //! # #[macro_use] extern crate structopt; 255 //! #[derive(StructOpt)] 256 //! #[structopt(name = "foo")] 257 //! /// The help message that will be displayed when passing `--help`. 258 //! struct Foo { 259 //! #[structopt(short = "b")] 260 //! /// Only this summary is visible when passing `-h`. 261 //! /// 262 //! /// But the whole comment will be displayed when passing `--help`. 263 //! /// This could be quite useful to provide further hints are usage 264 //! /// examples. 265 //! bar: String 266 //! } 267 //! # fn main() {} 268 //! ``` 269 //! 270 //! ## Subcommands 271 //! 272 //! Some applications, especially large ones, split their functionality 273 //! through the use of "subcommands". Each of these act somewhat like a separate 274 //! command, but is part of the larger group. 275 //! One example is `git`, which has subcommands such as `add`, `commit`, 276 //! and `clone`, to mention just a few. 277 //! 278 //! `clap` has this functionality, and `structopt` supports it through enums: 279 //! 280 //! ``` 281 //! # #[macro_use] extern crate structopt; 282 //! # use std::path::PathBuf; 283 //! #[derive(StructOpt)] 284 //! #[structopt(name = "git", about = "the stupid content tracker")] 285 //! enum Git { 286 //! #[structopt(name = "add")] 287 //! Add { 288 //! #[structopt(short = "i")] 289 //! interactive: bool, 290 //! #[structopt(short = "p")] 291 //! patch: bool, 292 //! #[structopt(parse(from_os_str))] 293 //! files: Vec<PathBuf> 294 //! }, 295 //! #[structopt(name = "fetch")] 296 //! Fetch { 297 //! #[structopt(long = "dry-run")] 298 //! dry_run: bool, 299 //! #[structopt(long = "all")] 300 //! all: bool, 301 //! repository: Option<String> 302 //! }, 303 //! #[structopt(name = "commit")] 304 //! Commit { 305 //! #[structopt(short = "m")] 306 //! message: Option<String>, 307 //! #[structopt(short = "a")] 308 //! all: bool 309 //! } 310 //! } 311 //! # fn main() {} 312 //! ``` 313 //! 314 //! Using `derive(StructOpt)` on an enum instead of a struct will produce 315 //! a `clap::App` that only takes subcommands. So `git add`, `git fetch`, 316 //! and `git commit` would be commands allowed for the above example. 317 //! 318 //! `structopt` also provides support for applications where certain flags 319 //! need to apply to all subcommands, as well as nested subcommands: 320 //! 321 //! ``` 322 //! # #[macro_use] extern crate structopt; 323 //! # fn main() {} 324 //! #[derive(StructOpt)] 325 //! #[structopt(name = "make-cookie")] 326 //! struct MakeCookie { 327 //! #[structopt(name = "supervisor", default_value = "Puck", long = "supervisor")] 328 //! supervising_faerie: String, 329 //! #[structopt(name = "tree")] 330 //! /// The faerie tree this cookie is being made in. 331 //! tree: Option<String>, 332 //! #[structopt(subcommand)] // Note that we mark a field as a subcommand 333 //! cmd: Command 334 //! } 335 //! 336 //! #[derive(StructOpt)] 337 //! enum Command { 338 //! #[structopt(name = "pound")] 339 //! /// Pound acorns into flour for cookie dough. 340 //! Pound { 341 //! acorns: u32 342 //! }, 343 //! #[structopt(name = "sparkle")] 344 //! /// Add magical sparkles -- the secret ingredient! 345 //! Sparkle { 346 //! #[structopt(short = "m", parse(from_occurrences))] 347 //! magicality: u64, 348 //! #[structopt(short = "c")] 349 //! color: String 350 //! }, 351 //! #[structopt(name = "finish")] 352 //! Finish(Finish), 353 //! } 354 //! 355 //! // Subcommand can also be externalized by using a 1-uple enum variant 356 //! #[derive(StructOpt)] 357 //! struct Finish { 358 //! #[structopt(short = "t")] 359 //! time: u32, 360 //! #[structopt(subcommand)] // Note that we mark a field as a subcommand 361 //! finish_type: FinishType 362 //! } 363 //! 364 //! // subsubcommand! 365 //! #[derive(StructOpt)] 366 //! enum FinishType { 367 //! #[structopt(name = "glaze")] 368 //! Glaze { 369 //! applications: u32 370 //! }, 371 //! #[structopt(name = "powder")] 372 //! Powder { 373 //! flavor: String, 374 //! dips: u32 375 //! } 376 //! } 377 //! ``` 378 //! 379 //! Marking a field with `structopt(subcommand)` will add the subcommands of the 380 //! designated enum to the current `clap::App`. The designated enum *must* also 381 //! be derived `StructOpt`. So the above example would take the following 382 //! commands: 383 //! 384 //! + `make-cookie pound 50` 385 //! + `make-cookie sparkle -mmm --color "green"` 386 //! + `make-cookie finish 130 glaze 3` 387 //! 388 //! ### Optional subcommands 389 //! 390 //! A nested subcommand can be marked optional: 391 //! 392 //! ``` 393 //! # #[macro_use] extern crate structopt; 394 //! # fn main() {} 395 //! #[derive(StructOpt)] 396 //! #[structopt(name = "foo")] 397 //! struct Foo { 398 //! file: String, 399 //! #[structopt(subcommand)] 400 //! cmd: Option<Command> 401 //! } 402 //! 403 //! #[derive(StructOpt)] 404 //! enum Command { 405 //! Bar, 406 //! Baz, 407 //! Quux 408 //! } 409 //! ``` 410 //! 411 //! ## Flattening 412 //! 413 //! It can sometimes be useful to group related arguments in a substruct, 414 //! while keeping the command-line interface flat. In these cases you can mark 415 //! a field as `flatten` and give it another type that derives `StructOpt`: 416 //! 417 //! ``` 418 //! # #[macro_use] extern crate structopt; 419 //! # use structopt::StructOpt; 420 //! # fn main() {} 421 //! #[derive(StructOpt)] 422 //! struct Cmdline { 423 //! #[structopt(short = "v", help = "switch on verbosity")] 424 //! verbose: bool, 425 //! #[structopt(flatten)] 426 //! daemon_opts: DaemonOpts, 427 //! } 428 //! 429 //! #[derive(StructOpt)] 430 //! struct DaemonOpts { 431 //! #[structopt(short = "u", help = "daemon user")] 432 //! user: String, 433 //! #[structopt(short = "g", help = "daemon group")] 434 //! group: String, 435 //! } 436 //! ``` 437 //! 438 //! In this example, the derived `Cmdline` parser will support the options `-v`, 439 //! `-u` and `-g`. 440 //! 441 //! This feature also makes it possible to define a `StructOpt` struct in a 442 //! library, parse the corresponding arguments in the main argument parser, and 443 //! pass off this struct to a handler provided by that library. 444 //! 445 //! ## Custom string parsers 446 //! 447 //! If the field type does not have a `FromStr` implementation, or you would 448 //! like to provide a custom parsing scheme other than `FromStr`, you may 449 //! provide a custom string parser using `parse(...)` like this: 450 //! 451 //! ``` 452 //! # #[macro_use] extern crate structopt; 453 //! # fn main() {} 454 //! use std::num::ParseIntError; 455 //! use std::path::PathBuf; 456 //! 457 //! fn parse_hex(src: &str) -> Result<u32, ParseIntError> { 458 //! u32::from_str_radix(src, 16) 459 //! } 460 //! 461 //! #[derive(StructOpt)] 462 //! struct HexReader { 463 //! #[structopt(short = "n", parse(try_from_str = "parse_hex"))] 464 //! number: u32, 465 //! #[structopt(short = "o", parse(from_os_str))] 466 //! output: PathBuf, 467 //! } 468 //! ``` 469 //! 470 //! There are five kinds of custom parsers: 471 //! 472 //! | Kind | Signature | Default | 473 //! |-------------------|---------------------------------------|---------------------------------| 474 //! | `from_str` | `fn(&str) -> T` | `::std::convert::From::from` | 475 //! | `try_from_str` | `fn(&str) -> Result<T, E>` | `::std::str::FromStr::from_str` | 476 //! | `from_os_str` | `fn(&OsStr) -> T` | `::std::convert::From::from` | 477 //! | `try_from_os_str` | `fn(&OsStr) -> Result<T, OsString>` | (no default function) | 478 //! | `from_occurrences`| `fn(u64) -> T` | `value as T` | 479 //! 480 //! The `from_occurrences` parser is special. Using `parse(from_occurrences)` 481 //! results in the _number of flags occurrences_ being stored in the relevant 482 //! field or being passed to the supplied function. In other words, it converts 483 //! something like `-vvv` to `3`. This is equivalent to 484 //! `.takes_value(false).multiple(true)`. Note that the default parser can only 485 //! be used with fields of integer types (`u8`, `usize`, `i64`, etc.). 486 //! 487 //! When supplying a custom string parser, `bool` will not be treated specially: 488 //! 489 //! Type | Effect | Added method call to `clap::Arg` 490 //! ------------|-------------------|-------------------------------------- 491 //! `Option<T>` | optional argument | `.takes_value(true).multiple(false)` 492 //! `Vec<T>` | list of arguments | `.takes_value(true).multiple(true)` 493 //! `T` | required argument | `.takes_value(true).multiple(false).required(!has_default)` 494 //! 495 //! In the `try_from_*` variants, the function will run twice on valid input: 496 //! once to validate, and once to parse. Hence, make sure the function is 497 //! side-effect-free. 498 499 extern crate clap as _clap; 500 501 #[allow(unused_imports)] 502 #[macro_use] 503 extern crate structopt_derive; 504 505 #[doc(hidden)] 506 pub use structopt_derive::*; 507 508 use std::ffi::OsString; 509 510 /// Re-export of clap 511 pub mod clap { 512 pub use _clap::*; 513 } 514 515 /// A struct that is converted from command line arguments. 516 pub trait StructOpt { 517 /// Returns the corresponding `clap::App`. clap<'a, 'b>() -> clap::App<'a, 'b>518 fn clap<'a, 'b>() -> clap::App<'a, 'b>; 519 520 /// Creates the struct from `clap::ArgMatches`. It cannot fail 521 /// with a parameter generated by `clap` by construction. from_clap(&clap::ArgMatches) -> Self522 fn from_clap(&clap::ArgMatches) -> Self; 523 524 /// Gets the struct from the command line arguments. Print the 525 /// error message and quit the program in case of failure. from_args() -> Self where Self: Sized,526 fn from_args() -> Self 527 where 528 Self: Sized, 529 { 530 Self::from_clap(&Self::clap().get_matches()) 531 } 532 533 /// Gets the struct from any iterator such as a `Vec` of your making. 534 /// Print the error message and quit the program in case of failure. from_iter<I>(iter: I) -> Self where Self: Sized, I: IntoIterator, I::Item: Into<OsString> + Clone,535 fn from_iter<I>(iter: I) -> Self 536 where 537 Self: Sized, 538 I: IntoIterator, 539 I::Item: Into<OsString> + Clone, 540 { 541 Self::from_clap(&Self::clap().get_matches_from(iter)) 542 } 543 544 /// Gets the struct from any iterator such as a `Vec` of your making. 545 /// 546 /// Returns a `clap::Error` in case of failure. This does *not* exit in the 547 /// case of `--help` or `--version`, to achieve the same behavior as 548 /// `from_iter()` you must call `.exit()` on the error value. from_iter_safe<I>(iter: I) -> Result<Self, clap::Error> where Self: Sized, I: IntoIterator, I::Item: Into<OsString> + Clone,549 fn from_iter_safe<I>(iter: I) -> Result<Self, clap::Error> 550 where 551 Self: Sized, 552 I: IntoIterator, 553 I::Item: Into<OsString> + Clone, 554 { 555 Ok(Self::from_clap(&Self::clap().get_matches_from_safe(iter)?)) 556 } 557 } 558