diff options
Diffstat (limited to 'structopt/src/lib.rs')
-rw-r--r-- | structopt/src/lib.rs | 1015 |
1 files changed, 0 insertions, 1015 deletions
diff --git a/structopt/src/lib.rs b/structopt/src/lib.rs deleted file mode 100644 index 70c0768..0000000 --- a/structopt/src/lib.rs +++ /dev/null @@ -1,1015 +0,0 @@ -// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu> -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<PathBuf>, -//! -//! /// 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<T>`! Or perhaps optional argument -//! that optionally takes value (`[--opt=[val]]`)? Use `Option<Option<T>>`! -//! -//! 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<T: FromStr>` | optional positional argument or option | `.takes_value(true).multiple(false)` -//! `Option<Option<T: FromStr>>` | optional option with optional value | `.takes_value(true).multiple(false).min_values(0).max_values(1)` -//! `Vec<T: FromStr>` | list of options or the other positional arguments | `.takes_value(true).multiple(true)` -//! `Option<Vec<T: FromStr>` | 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<T>` is special while `::std::option::Option<T>` 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<T>(_: String) -> Result<(), String> { unimplemented!() } -//! # fn main() { -//! clap::Arg::with_name("speed") -//! .takes_value(true) -//! .multiple(false) -//! .required(false) -//! .validator(parse_validator::<f64>) -//! .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(<summary>)` and -//! `long_help(<whole comment>)`, 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("<name>") -//! .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 <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<FieldType>`) -//! 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<u32>, -//! -//! // these fields get set explicitly -//! -//! #[structopt(skip = vec![1, 2, 3])] -//! k2: Vec<u32>, -//! #[structopt(skip = "cake")] // &str implements Into<String> -//! 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<PathBuf> -//! }, -//! Fetch { -//! #[structopt(long)] -//! dry_run: bool, -//! #[structopt(long)] -//! all: bool, -//! repository: Option<String> -//! }, -//! Commit { -//! #[structopt(short)] -//! message: Option<String>, -//! #[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<String>, -//! #[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<Command> -//! } -//! -//! #[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, ParseIntError> { -//! 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<T, E>` | `::std::str::FromStr::from_str` | -//! | `from_os_str` | `fn(&OsStr) -> T` | `::std::convert::From::from` | -//! | `try_from_os_str` | `fn(&OsStr) -> Result<T, OsString>` | (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<T>` | optional argument | `.takes_value(true).multiple(false)` -//! `Vec<T>` | 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<I>(iter: I) -> Self - where - Self: Sized, - I: IntoIterator, - I::Item: Into<OsString> + 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<I>(iter: I) -> Result<Self, clap::Error> - where - Self: Sized, - I: IntoIterator, - I::Item: Into<OsString> + 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<Self> - where - Self: std::marker::Sized, - { - None - } -} - -impl<T: StructOpt> StructOpt for Box<T> { - fn clap<'a, 'b>() -> clap::App<'a, 'b> { - <T as StructOpt>::clap() - } - - fn from_clap(matches: &clap::ArgMatches<'_>) -> Self { - Box::new(<T as StructOpt>::from_clap(matches)) - } -} - -impl<T: StructOptInternal> StructOptInternal for Box<T> { - #[doc(hidden)] - fn is_subcommand() -> bool { - <T as StructOptInternal>::is_subcommand() - } - - #[doc(hidden)] - fn from_subcommand<'a, 'b>(sub: (&'b str, Option<&'b clap::ArgMatches<'a>>)) -> Option<Self> { - <T as StructOptInternal>::from_subcommand(sub).map(Box::new) - } - - #[doc(hidden)] - fn augment_clap<'a, 'b>(app: clap::App<'a, 'b>) -> clap::App<'a, 'b> { - <T as StructOptInternal>::augment_clap(app) - } -} |