// Copyright 2018 Guillaume Pinot (@TeXitoi) // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![deny(missing_docs)] //! This crate defines the `StructOpt` trait and its custom derive. //! //! ## Features //! //! If you want to disable all the `clap` features (colors, //! suggestions, ..) add `default-features = false` to the `structopt` //! dependency: //! //! ```toml //! [dependencies] //! structopt = { version = "0.3", default-features = false } //! ``` //! //! Support for [`paw`](https://github.com/rust-cli/paw) (the //! `Command line argument paw-rser abstraction for main`) is disabled //! by default, but can be enabled in the `structopt` dependency //! with the feature `paw`: //! //! ```toml //! [dependencies] //! structopt = { version = "0.3", features = [ "paw" ] } //! paw = "1.0" //! ``` //! //! # Table of Contents //! //! - [How to `derive(StructOpt)`](#how-to-derivestructopt) //! - [Attributes](#attributes) //! - [Raw methods](#raw-methods) //! - [Magical methods](#magical-methods) //! - Arguments //! - [Type magic](#type-magic) //! - [Specifying argument types](#specifying-argument-types) //! - [Help messages](#help-messages) //! - [Environment variable fallback](#environment-variable-fallback) //! - [Skipping fields](#skipping-fields) //! - [Subcommands](#subcommands) //! - [Optional subcommands](#optional-subcommands) //! - [Flattening](#flattening) //! - [Custom string parsers](#custom-string-parsers) //! //! //! //! ## How to `derive(StructOpt)` //! //! First, let's look at the example: //! //! ```should_panic //! use std::path::PathBuf; //! use structopt::StructOpt; //! //! #[derive(Debug, StructOpt)] //! #[structopt(name = "example", about = "An example of StructOpt usage.")] //! struct Opt { //! /// Activate debug mode //! // short and long flags (-d, --debug) will be deduced from the field's name //! #[structopt(short, long)] //! debug: bool, //! //! /// Set speed //! // we don't want to name it "speed", need to look smart //! #[structopt(short = "v", long = "velocity", default_value = "42")] //! speed: f64, //! //! /// Input file //! #[structopt(parse(from_os_str))] //! input: PathBuf, //! //! /// Output file, stdout if not present //! #[structopt(parse(from_os_str))] //! output: Option, //! //! /// Where to write the output: to `stdout` or `file` //! #[structopt(short)] //! out_type: String, //! //! /// File name: only required when `out` is set to `file` //! #[structopt(name = "FILE", required_if("out_type", "file"))] //! file_name: String, //! } //! //! fn main() { //! let opt = Opt::from_args(); //! println!("{:?}", opt); //! } //! ``` //! //! So `derive(StructOpt)` tells Rust to generate a command line parser, //! and the various `structopt` attributes are simply //! used for additional parameters. //! //! First, define a struct, whatever its name. This structure //! corresponds to a `clap::App`, its fields correspond to `clap::Arg` //! (unless they're [subcommands](#subcommands)), //! and you can adjust these apps and args by `#[structopt(...)]` [attributes](#attributes). //! //! **Note:** //! _________________ //! Keep in mind that `StructOpt` trait is more than just `from_args` method. //! It has a number of additional features, including access to underlying //! `clap::App` via `StructOpt::clap()`. See the //! [trait's reference documentation](trait.StructOpt.html). //! _________________ //! //! ## Attributes //! //! `#[structopt(...)]` attributes fall into two categories: //! - `structopt`'s own [magical methods](#magical-methods). //! //! They are used by `structopt` itself. They come mostly in //! `attr = ["whatever"]` form, but some `attr(args...)` also exist. //! //! - [`raw` attributes](#raw-methods). //! //! They represent explicit `clap::Arg/App` method calls. //! They are what used to be explicit `#[structopt(raw(...))]` attrs in pre-0.3 `structopt` //! //! Every `structopt attribute` looks like comma-separated sequence of methods: //! ```rust,ignore //! #[structopt( //! short, // method with no arguments - always magical //! long = "--long-option", // method with one argument //! required_if("out", "file"), // method with one and more args //! parse(from_os_str = path::to::parser) // some magical methods have their own syntax //! )] //! ``` //! //! `#[structopt(...)]` attributes can be placed on top of `struct`, `enum`, //! `struct` field or `enum` variant. Attributes on top of `struct` or `enum` //! represent `clap::App` method calls, field or variant attributes correspond //! to `clap::Arg` method calls. //! //! In other words, the `Opt` struct from the example above //! will be turned into this (*details omitted*): //! //! ``` //! # use structopt::clap::{Arg, App}; //! App::new("example") //! .version("0.2.0") //! .about("An example of StructOpt usage.") //! .arg(Arg::with_name("debug") //! .help("Activate debug mode") //! .short("debug") //! .long("debug")) //! .arg(Arg::with_name("speed") //! .help("Set speed") //! .short("v") //! .long("velocity") //! .default_value("42")) //! // and so on //! # ; //! ``` //! //! ## Raw methods //! //! They are the reason why `structopt` is so flexible. //! //! Each and every method from `clap::App` and `clap::Arg` can be used directly - //! just `#[structopt(method_name = single_arg)]` or `#[structopt(method_name(arg1, arg2))]` //! and it just works. As long as `method_name` is not one of the magical methods - //! it's just a method call. //! //! **Note:** //! _________________ //! //! "Raw methods" are direct replacement for pre-0.3 structopt's //! `#[structopt(raw(...))]` attributes, any time you would have used a `raw()` attribute //! in 0.2 you should use raw method in 0.3. //! //! Unfortunately, old raw attributes collide with `clap::Arg::raw` method. To explicitly //! warn users of this change we allow `#[structopt(raw())]` only with `true` or `false` //! literals (this method is supposed to be called only with `true` anyway). //! __________________ //! //! ## Magical methods //! //! They are the reason why `structopt` is so easy to use and convenient in most cases. //! Many of them have defaults, some of them get used even if not mentioned. //! //! Methods may be used on "top level" (on top of a `struct`, `enum` or `enum` variant) //! and/or on "field-level" (on top of a `struct` field or *inside* of an enum variant). //! Top level (non-magical) methods correspond to `App::method` calls, field-level methods //! are `Arg::method` calls. //! //! ```ignore //! #[structopt(top_level)] //! struct Foo { //! #[structopt(field_level)] //! field: u32 //! } //! //! #[structopt(top_level)] //! enum Bar { //! #[structopt(top_level)] //! Pineapple { //! #[structopt(field_level)] //! chocolate: String //! }, //! //! #[structopt(top_level)] //! Orange, //! } //! ``` //! //! - `name`: `[name = "name"]` //! - On top level: `App::new("name")`. //! //! The binary name displayed in help messages. Defaults to the crate name given by Cargo. //! //! - On field-level: `Arg::with_name("name")`. //! //! The name for the argument the field stands for, this name appears in help messages. //! Defaults to a name, deduced from a field, see also //! [`rename_all`](#specifying-argument-types). //! //! - `version`: `[version = "version"]` //! //! Usable only on top level: `App::version("version" or env!(CARGO_PKG_VERSION))`. //! //! The version displayed in help messages. //! Defaults to the crate version given by Cargo. If `CARGO_PKG_VERSION` is not //! set no `.version()` calls will be generated unless requested. //! //! - `no_version`: `no_version` //! //! Usable only on top level. Prevents default `App::version` call, i.e //! when no `version = "version"` mentioned. //! //! - `author`: `author [= "author"]` //! //! Usable only on top level: `App::author("author" or env!(CARGO_PKG_AUTHOR))`. //! //! Author/maintainer of the binary, this name appears in help messages. //! Defaults to the crate author given by cargo, but only when `author` explicitly mentioned. //! //! - `about`: `about [= "about"]` //! //! Usable only on top level: `App::about("about" or env!(CARGO_PKG_DESCRIPTION))`. //! //! Short description of the binary, appears in help messages. //! Defaults to the crate description given by cargo, //! but only when `about` explicitly mentioned. //! //! - [`short`](#specifying-argument-types): `short [= "short-opt-name"]` //! //! Usable only on field-level. //! //! - [`long`](#specifying-argument-types): `long [= "long-opt-name"]` //! //! Usable only on field-level. //! //! - [`rename_all`](#specifying-argument-types): [`rename_all = "kebab"/"snake"/"screaming-snake"/"camel"/"pascal"/"verbatim"]` //! //! Usable both on top level and field level. //! //! - [`parse`](#custom-string-parsers): `parse(type [= path::to::parser::fn])` //! //! Usable only on field-level. //! //! - [`skip`](#skipping-fields): `skip [= expr]` //! //! Usable only on field-level. //! //! - [`flatten`](#flattening): `flatten` //! //! Usable only on field-level. //! //! - [`subcommand`](#subcommands): `subcommand` //! //! Usable only on field-level. //! //! - [`env`](#environment-variable-fallback): `env [= str_literal]` //! //! Usable only on field-level. //! //! - [`rename_all_env`](##auto-deriving-environment-variables): [`rename_all_env = "kebab"/"snake"/"screaming-snake"/"camel"/"pascal"/"verbatim"]` //! //! Usable both on top level and field level. //! //! - [`verbatim_doc_comment`](#doc-comment-preprocessing-and-structoptverbatim_doc_comment): //! `verbatim_doc_comment` //! //! Usable both on top level and field level. //! //! ## Type magic //! //! One of major things that makes `structopt` so awesome is it's type magic. //! Do you want optional positional argument? Use `Option`! Or perhaps optional argument //! that optionally takes value (`[--opt=[val]]`)? Use `Option>`! //! //! Here is the table of types and `clap` methods they correspond to: //! //! Type | Effect | Added method call to `clap::Arg` //! -----------------------------|---------------------------------------------------|-------------------------------------- //! `bool` | `true` if the flag is present | `.takes_value(false).multiple(false)` //! `Option` | optional positional argument or option | `.takes_value(true).multiple(false)` //! `Option>` | optional option with optional value | `.takes_value(true).multiple(false).min_values(0).max_values(1)` //! `Vec` | list of options or the other positional arguments | `.takes_value(true).multiple(true)` //! `Option` | optional list of options | `.takes_values(true).multiple(true).min_values(0)` //! `T: FromStr` | required option or positional argument | `.takes_value(true).multiple(false).required(!has_default)` //! //! The `FromStr` trait is used to convert the argument to the given //! type, and the `Arg::validator` method is set to a method using //! `to_string()` (`FromStr::Err` must implement `std::fmt::Display`). //! If you would like to use a custom string parser other than `FromStr`, see //! the [same titled section](#custom-string-parsers) below. //! //! **Note:** //! _________________ //! Pay attention that *only literal occurrence* of this types is special, for example //! `Option` is special while `::std::option::Option` is not. //! //! If you need to avoid special casing you can make a `type` alias and //! use it in place of the said type. //! _________________ //! //! **Note:** //! _________________ //! `bool` cannot be used as positional argument unless you provide an explicit parser. //! If you need a positional bool, for example to parse `true` or `false`, you must //! annotate the field with explicit [`#[structopt(parse(...))]`](#custom-string-parsers). //! _________________ //! //! Thus, the `speed` argument is generated as: //! //! ``` //! # extern crate clap; //! # fn parse_validator(_: String) -> Result<(), String> { unimplemented!() } //! # fn main() { //! clap::Arg::with_name("speed") //! .takes_value(true) //! .multiple(false) //! .required(false) //! .validator(parse_validator::) //! .short("v") //! .long("velocity") //! .help("Set speed") //! .default_value("42"); //! # } //! ``` //! //! ## Specifying argument types //! //! There are three types of arguments that can be supplied to each //! (sub-)command: //! //! - short (e.g. `-h`), //! - long (e.g. `--help`) //! - and positional. //! //! Like clap, structopt defaults to creating positional arguments. //! //! If you want to generate a long argument you can specify either //! `long = $NAME`, or just `long` to get a long flag generated using //! the field name. The generated casing style can be modified using //! the `rename_all` attribute. See the `rename_all` example for more. //! //! For short arguments, `short` will use the first letter of the //! field name by default, but just like the long option it's also //! possible to use a custom letter through `short = $LETTER`. //! //! If an argument is renamed using `name = $NAME` any following call to //! `short` or `long` will use the new name. //! //! **Attention**: If these arguments are used without an explicit name //! the resulting flag is going to be renamed using `kebab-case` if the //! `rename_all` attribute was not specified previously. The same is true //! for subcommands with implicit naming through the related data structure. //! //! ``` //! use structopt::StructOpt; //! //! #[derive(StructOpt)] //! #[structopt(rename_all = "kebab-case")] //! struct Opt { //! /// This option can be specified with something like `--foo-option //! /// value` or `--foo-option=value` //! #[structopt(long)] //! foo_option: String, //! //! /// This option can be specified with something like `-b value` (but //! /// not `--bar-option value`). //! #[structopt(short)] //! bar_option: String, //! //! /// This option can be specified either `--baz value` or `-z value`. //! #[structopt(short = "z", long = "baz")] //! baz_option: String, //! //! /// This option can be specified either by `--custom value` or //! /// `-c value`. //! #[structopt(name = "custom", long, short)] //! custom_option: String, //! //! /// This option is positional, meaning it is the first unadorned string //! /// you provide (multiple others could follow). //! my_positional: String, //! //! /// This option is skipped and will be filled with the default value //! /// for its type (in this case 0). //! #[structopt(skip)] //! skipped: u32, //! //! } //! //! # fn main() { //! # Opt::from_clap(&Opt::clap().get_matches_from( //! # &["test", "--foo-option", "", "-b", "", "--baz", "", "--custom", "", "positional"])); //! # } //! ``` //! //! ## Help messages //! //! In clap, help messages for the whole binary can be specified //! via [`App::about`] and [`App::long_about`] while help messages //! for individual arguments can be specified via [`Arg::help`] and [`Arg::long_help`]". //! //! `long_*` variants are used when user calls the program with //! `--help` and "short" variants are used with `-h` flag. In `structopt`, //! you can use them via [raw methods](#raw-methods), for example: //! //! ``` //! # use structopt::StructOpt; //! //! #[derive(StructOpt)] //! #[structopt(about = "I am a program and I work, just pass `-h`")] //! struct Foo { //! #[structopt(short, help = "Pass `-h` and you'll see me!")] //! bar: String //! } //! ``` //! //! For convenience, doc comments can be used instead of raw methods //! (this example works exactly like the one above): //! //! ``` //! # use structopt::StructOpt; //! //! #[derive(StructOpt)] //! /// I am a program and I work, just pass `-h` //! struct Foo { //! /// Pass `-h` and you'll see me! //! bar: String //! } //! ``` //! //! Doc comments on [top-level](#magical-methods) will be turned into //! `App::about/long_about` call (see below), doc comments on field-level are //! `Arg::help/long_help` calls. //! //! **Important:** //! _________________ //! //! Raw methods have priority over doc comments! //! //! **Top level doc comments always generate `App::about/long_about` calls!** //! If you really want to use the `App::help/long_help` methods (you likely don't), //! use a raw method to override the `App::about` call generated from the doc comment. //! __________________ //! //! ### `long_help` and `--help` //! //! A message passed to [`App::long_help`] or [`Arg::long_about`] will be displayed whenever //! your program is called with `--help` instead of `-h`. Of course, you can //! use them via raw methods as described [above](#help-messages). //! //! The more convenient way is to use a so-called "long" doc comment: //! //! ``` //! # use structopt::StructOpt; //! #[derive(StructOpt)] //! /// Hi there, I'm Robo! //! /// //! /// I like beeping, stumbling, eating your electricity, //! /// and making records of you singing in a shower. //! /// Pay up, or I'll upload it to youtube! //! struct Robo { //! /// Call my brother SkyNet. //! /// //! /// I am artificial superintelligence. I won't rest //! /// until I'll have destroyed humanity. Enjoy your //! /// pathetic existence, you mere mortals. //! #[structopt(long)] //! kill_all_humans: bool //! } //! ``` //! //! A long doc comment consists of three parts: //! * Short summary //! * A blank line (whitespace only) //! * Detailed description, all the rest //! //! In other words, "long" doc comment consists of two or more paragraphs, //! with the first being a summary and the rest being the detailed description. //! //! **A long comment will result in two method calls**, `help()` and //! `long_help()`, so clap will display the summary with `-h` //! and the whole help message on `--help` (see below). //! //! So, the example above will be turned into this (details omitted): //! ``` //! clap::App::new("") //! .about("Hi there, I'm Robo!") //! .long_about("Hi there, I'm Robo!\n\n\ //! I like beeping, stumbling, eating your electricity,\ //! and making records of you singing in a shower.\ //! Pay up or I'll upload it to youtube!") //! // args... //! # ; //! ``` //! //! ### `-h` vs `--help` (A.K.A `help()` vs `long_help()`) //! //! The `-h` flag is not the same as `--help`. //! //! -h corresponds to Arg::help/App::about and requests short "summary" messages //! while --help corresponds to Arg::long_help/App::long_about and requests more //! detailed, descriptive messages. //! //! It is entirely up to `clap` what happens if you used only one of //! [`Arg::help`]/[`Arg::long_help`], see `clap`'s documentation for these methods. //! //! As of clap v2.33, if only a short message ([`Arg::help`]) or only //! a long ([`Arg::long_help`]) message is provided, clap will use it //! for both -h and --help. The same logic applies to `about/long_about`. //! //! ### Doc comment preprocessing and `#[structopt(verbatim_doc_comment)]` //! //! `structopt` applies some preprocessing to doc comments to ease the most common uses: //! //! * Strip leading and trailing whitespace from every line, if present. //! //! * Strip leading and trailing blank lines, if present. //! //! * Interpret each group of non-empty lines as a word-wrapped paragraph. //! //! We replace newlines within paragraphs with spaces to allow the output //! to be re-wrapped to the terminal width. //! //! * Strip any excess blank lines so that there is exactly one per paragraph break. //! //! * If the first paragraph ends in exactly one period, //! remove the trailing period (i.e. strip trailing periods but not trailing ellipses). //! //! Sometimes you don't want this preprocessing to apply, for example the comment contains //! some ASCII art or markdown tables, you would need to preserve LFs along with //! blank lines and the leading/trailing whitespace. You can ask `structopt` to preserve them //! via `#[structopt(verbatim_doc_comment)]` attribute. //! //! **This attribute must be applied to each field separately**, there's no global switch. //! //! **Important:** //! ______________ //! Keep in mind that `structopt` will *still* remove one leading space from each //! line, even if this attribute is present, to allow for a space between //! `///` and the content. //! //! Also, `structopt` will *still* remove leading and trailing blank lines so //! these formats are equivalent: //! //! ```ignore //! /** This is a doc comment //! //! Hello! */ //! //! /** //! This is a doc comment //! //! Hello! //! */ //! //! /// This is a doc comment //! /// //! /// Hello! //! ``` //! //! Summary //! ______________ //! //! [`App::about`]: https://docs.rs/clap/2/clap/struct.App.html#method.about //! [`App::long_about`]: https://docs.rs/clap/2/clap/struct.App.html#method.long_about //! [`Arg::help`]: https://docs.rs/clap/2/clap/struct.Arg.html#method.help //! [`Arg::long_help`]: https://docs.rs/clap/2/clap/struct.Arg.html#method.long_help //! //! ## Environment variable fallback //! //! It is possible to specify an environment variable fallback option for an arguments //! so that its value is taken from the specified environment variable if not //! given through the command-line: //! //! ``` //! # use structopt::StructOpt; //! //! #[derive(StructOpt)] //! struct Foo { //! #[structopt(short, long, env = "PARAMETER_VALUE")] //! parameter_value: String //! } //! # fn main() {} //! ``` //! //! By default, values from the environment are shown in the help output (i.e. when invoking //! `--help`): //! //! ```shell //! $ cargo run -- --help //! ... //! OPTIONS: //! -p, --parameter-value [env: PARAMETER_VALUE=env_value] //! ``` //! //! In some cases this may be undesirable, for example when being used for passing //! credentials or secret tokens. In those cases you can use `hide_env_values` to avoid //! having structopt emit the actual secret values: //! ``` //! # use structopt::StructOpt; //! //! #[derive(StructOpt)] //! struct Foo { //! #[structopt(long = "secret", env = "SECRET_VALUE", hide_env_values = true)] //! secret_value: String //! } //! ``` //! //! ### Auto-deriving environment variables //! //! Environment variables tend to be called after the corresponding `struct`'s field, //! as in example above. The field is `secret_value` and the env var is "SECRET_VALUE"; //! the name is the same, except casing is different. //! //! It's pretty tedious and error-prone to type the same name twice, //! so you can ask `structopt` to do that for you. //! //! ``` //! # use structopt::StructOpt; //! //! #[derive(StructOpt)] //! struct Foo { //! #[structopt(long = "secret", env)] //! secret_value: String //! } //! ``` //! //! It works just like `#[structopt(short/long)]`: if `env` is not set to some concrete //! value the value will be derived from the field's name. This is controlled by //! `#[structopt(rename_all_env)]`. //! //! `rename_all_env` works exactly as `rename_all` (including overriding) //! except default casing is `SCREAMING_SNAKE_CASE` instead of `kebab-case`. //! //! ## Skipping fields //! //! Sometimes you may want to add a field to your `Opt` struct that is not //! a command line option and `clap` should know nothing about it. You can ask //! `structopt` to skip the field entirely via `#[structopt(skip = value)]` //! (`value` must implement `Into`) //! or `#[structopt(skip)]` if you want assign the field with `Default::default()` //! (obviously, the field's type must implement `Default`). //! //! ``` //! # use structopt::StructOpt; //! #[derive(StructOpt)] //! pub struct Opt { //! #[structopt(long, short)] //! number: u32, //! //! // these fields are to be assigned with Default::default() //! //! #[structopt(skip)] //! k: String, //! #[structopt(skip)] //! v: Vec, //! //! // these fields get set explicitly //! //! #[structopt(skip = vec![1, 2, 3])] //! k2: Vec, //! #[structopt(skip = "cake")] // &str implements Into //! v2: String, //! } //! ``` //! //! ## Subcommands //! //! Some applications, especially large ones, split their functionality //! through the use of "subcommands". Each of these act somewhat like a separate //! command, but is part of the larger group. //! One example is `git`, which has subcommands such as `add`, `commit`, //! and `clone`, to mention just a few. //! //! `clap` has this functionality, and `structopt` supports it through enums: //! //! ``` //! # use structopt::StructOpt; //! //! # use std::path::PathBuf; //! #[derive(StructOpt)] //! #[structopt(about = "the stupid content tracker")] //! enum Git { //! Add { //! #[structopt(short)] //! interactive: bool, //! #[structopt(short)] //! patch: bool, //! #[structopt(parse(from_os_str))] //! files: Vec //! }, //! Fetch { //! #[structopt(long)] //! dry_run: bool, //! #[structopt(long)] //! all: bool, //! repository: Option //! }, //! Commit { //! #[structopt(short)] //! message: Option, //! #[structopt(short)] //! all: bool //! } //! } //! # fn main() {} //! ``` //! //! Using `derive(StructOpt)` on an enum instead of a struct will produce //! a `clap::App` that only takes subcommands. So `git add`, `git fetch`, //! and `git commit` would be commands allowed for the above example. //! //! `structopt` also provides support for applications where certain flags //! need to apply to all subcommands, as well as nested subcommands: //! //! ``` //! # use structopt::StructOpt; //! # fn main() {} //! #[derive(StructOpt)] //! struct MakeCookie { //! #[structopt(name = "supervisor", default_value = "Puck", long = "supervisor")] //! supervising_faerie: String, //! /// The faerie tree this cookie is being made in. //! tree: Option, //! #[structopt(subcommand)] // Note that we mark a field as a subcommand //! cmd: Command //! } //! //! #[derive(StructOpt)] //! enum Command { //! /// Pound acorns into flour for cookie dough. //! Pound { //! acorns: u32 //! }, //! /// Add magical sparkles -- the secret ingredient! //! Sparkle { //! #[structopt(short, parse(from_occurrences))] //! magicality: u64, //! #[structopt(short)] //! color: String //! }, //! Finish(Finish), //! } //! //! // Subcommand can also be externalized by using a 1-uple enum variant //! #[derive(StructOpt)] //! struct Finish { //! #[structopt(short)] //! time: u32, //! #[structopt(subcommand)] // Note that we mark a field as a subcommand //! finish_type: FinishType //! } //! //! // subsubcommand! //! #[derive(StructOpt)] //! enum FinishType { //! Glaze { //! applications: u32 //! }, //! Powder { //! flavor: String, //! dips: u32 //! } //! } //! ``` //! //! Marking a field with `structopt(subcommand)` will add the subcommands of the //! designated enum to the current `clap::App`. The designated enum *must* also //! be derived `StructOpt`. So the above example would take the following //! commands: //! //! + `make-cookie pound 50` //! + `make-cookie sparkle -mmm --color "green"` //! + `make-cookie finish 130 glaze 3` //! //! ### Optional subcommands //! //! Subcommands may be optional: //! //! ``` //! # use structopt::StructOpt; //! # fn main() {} //! #[derive(StructOpt)] //! struct Foo { //! file: String, //! #[structopt(subcommand)] //! cmd: Option //! } //! //! #[derive(StructOpt)] //! enum Command { //! Bar, //! Baz, //! Quux //! } //! ``` //! //! ## Flattening //! //! It can sometimes be useful to group related arguments in a substruct, //! while keeping the command-line interface flat. In these cases you can mark //! a field as `flatten` and give it another type that derives `StructOpt`: //! //! ``` //! # use structopt::StructOpt; //! # fn main() {} //! #[derive(StructOpt)] //! struct Cmdline { //! /// switch on verbosity //! #[structopt(short)] //! verbose: bool, //! #[structopt(flatten)] //! daemon_opts: DaemonOpts, //! } //! //! #[derive(StructOpt)] //! struct DaemonOpts { //! /// daemon user //! #[structopt(short)] //! user: String, //! /// daemon group //! #[structopt(short)] //! group: String, //! } //! ``` //! //! In this example, the derived `Cmdline` parser will support the options `-v`, //! `-u` and `-g`. //! //! This feature also makes it possible to define a `StructOpt` struct in a //! library, parse the corresponding arguments in the main argument parser, and //! pass off this struct to a handler provided by that library. //! //! ## Custom string parsers //! //! If the field type does not have a `FromStr` implementation, or you would //! like to provide a custom parsing scheme other than `FromStr`, you may //! provide a custom string parser using `parse(...)` like this: //! //! ``` //! # use structopt::StructOpt; //! # fn main() {} //! use std::num::ParseIntError; //! use std::path::PathBuf; //! //! fn parse_hex(src: &str) -> Result { //! u32::from_str_radix(src, 16) //! } //! //! #[derive(StructOpt)] //! struct HexReader { //! #[structopt(short, parse(try_from_str = parse_hex))] //! number: u32, //! #[structopt(short, parse(from_os_str))] //! output: PathBuf, //! } //! ``` //! //! There are five kinds of custom parsers: //! //! | Kind | Signature | Default | //! |-------------------|---------------------------------------|---------------------------------| //! | `from_str` | `fn(&str) -> T` | `::std::convert::From::from` | //! | `try_from_str` | `fn(&str) -> Result` | `::std::str::FromStr::from_str` | //! | `from_os_str` | `fn(&OsStr) -> T` | `::std::convert::From::from` | //! | `try_from_os_str` | `fn(&OsStr) -> Result` | (no default function) | //! | `from_occurrences`| `fn(u64) -> T` | `value as T` | //! | `from_flag` | `fn(bool) -> T` | `::std::convert::From::from` | //! //! The `from_occurrences` parser is special. Using `parse(from_occurrences)` //! results in the _number of flags occurrences_ being stored in the relevant //! field or being passed to the supplied function. In other words, it converts //! something like `-vvv` to `3`. This is equivalent to //! `.takes_value(false).multiple(true)`. Note that the default parser can only //! be used with fields of integer types (`u8`, `usize`, `i64`, etc.). //! //! The `from_flag` parser is also special. Using `parse(from_flag)` or //! `parse(from_flag = some_func)` will result in the field being treated as a //! flag even if it does not have type `bool`. //! //! When supplying a custom string parser, `bool` will not be treated specially: //! //! Type | Effect | Added method call to `clap::Arg` //! ------------|-------------------|-------------------------------------- //! `Option` | optional argument | `.takes_value(true).multiple(false)` //! `Vec` | list of arguments | `.takes_value(true).multiple(true)` //! `T` | required argument | `.takes_value(true).multiple(false).required(!has_default)` //! //! In the `try_from_*` variants, the function will run twice on valid input: //! once to validate, and once to parse. Hence, make sure the function is //! side-effect-free. #[doc(hidden)] pub use structopt_derive::*; use std::ffi::OsString; /// Re-export of clap pub use clap; /// A struct that is converted from command line arguments. pub trait StructOpt { /// Returns the corresponding `clap::App`. fn clap<'a, 'b>() -> clap::App<'a, 'b>; /// Creates the struct from `clap::ArgMatches`. It cannot fail /// with a parameter generated by `clap` by construction. fn from_clap(matches: &clap::ArgMatches<'_>) -> Self; /// Gets the struct from the command line arguments. Print the /// error message and quit the program in case of failure. fn from_args() -> Self where Self: Sized, { Self::from_clap(&Self::clap().get_matches()) } /// Gets the struct from any iterator such as a `Vec` of your making. /// Print the error message and quit the program in case of failure. fn from_iter(iter: I) -> Self where Self: Sized, I: IntoIterator, I::Item: Into + Clone, { Self::from_clap(&Self::clap().get_matches_from(iter)) } /// Gets the struct from any iterator such as a `Vec` of your making. /// /// Returns a `clap::Error` in case of failure. This does *not* exit in the /// case of `--help` or `--version`, to achieve the same behavior as /// `from_iter()` you must call `.exit()` on the error value. fn from_iter_safe(iter: I) -> Result where Self: Sized, I: IntoIterator, I::Item: Into + Clone, { Ok(Self::from_clap(&Self::clap().get_matches_from_safe(iter)?)) } } /// This trait is NOT API. **SUBJECT TO CHANGE WITHOUT NOTICE!**. #[doc(hidden)] pub trait StructOptInternal: StructOpt { fn augment_clap<'a, 'b>(app: clap::App<'a, 'b>) -> clap::App<'a, 'b> { app } fn is_subcommand() -> bool { false } fn from_subcommand<'a, 'b>(_sub: (&'b str, Option<&'b clap::ArgMatches<'a>>)) -> Option where Self: std::marker::Sized, { None } } impl StructOpt for Box { fn clap<'a, 'b>() -> clap::App<'a, 'b> { ::clap() } fn from_clap(matches: &clap::ArgMatches<'_>) -> Self { Box::new(::from_clap(matches)) } } impl StructOptInternal for Box { #[doc(hidden)] fn is_subcommand() -> bool { ::is_subcommand() } #[doc(hidden)] fn from_subcommand<'a, 'b>(sub: (&'b str, Option<&'b clap::ArgMatches<'a>>)) -> Option { ::from_subcommand(sub).map(Box::new) } #[doc(hidden)] fn augment_clap<'a, 'b>(app: clap::App<'a, 'b>) -> clap::App<'a, 'b> { ::augment_clap(app) } }