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