diff options
author | Robin Krahl <robin.krahl@ireas.org> | 2020-01-07 11:18:04 +0000 |
---|---|---|
committer | Daniel Mueller <deso@posteo.net> | 2020-01-08 09:20:25 -0800 |
commit | 5e20a29b4fdc8a2d442d1093681b396dcb4b816b (patch) | |
tree | 55ab083fa8999d2ccbb5e921c1ffe52560dca152 /structopt/examples | |
parent | 203e691f46d591a2cc8acdfd850fa9f5b0fb8a98 (diff) | |
download | nitrocli-5e20a29b4fdc8a2d442d1093681b396dcb4b816b.tar.gz nitrocli-5e20a29b4fdc8a2d442d1093681b396dcb4b816b.tar.bz2 |
Add structopt dependency in version 0.3.7
This patch series replaces argparse with structopt in the argument
handling code. As a first step, we need structopt as a dependency.
Import subrepo structopt/:structopt at efbdda4753592e27bc430fb01f7b9650b2f3174d
Import subrepo bitflags/:bitflags at 30668016aca6bd3b02c766e8347e0b4080d4c296
Import subrepo clap/:clap at 784524f7eb193e35f81082cc69454c8c21b948f7
Import subrepo heck/:heck at 093d56fbf001e1506e56dbfa38631d99b1066df1
Import subrepo proc-macro-error/:proc-macro-error at 6c4cfe79a622c5de8ae68557993542be46eacae2
Import subrepo proc-macro2/:proc-macro2 at d5d48eddca4566e5438e8a2cbed4a74e049544de
Import subrepo quote/:quote at 727436c6c137b20f0f34dde5d8fda2679b9747ad
Import subrepo rustversion/:rustversion at 0c5663313516263059ce9059ef81fc7a1cf655ca
Import subrepo syn-mid/:syn-mid at 5d3d85414a9e6674e1857ec22a87b96e04a6851a
Import subrepo syn/:syn at e87c27e87f6f4ef8919d0372bdb056d53ef0d8f3
Import subrepo textwrap/:textwrap at abcd618beae3f74841032aa5b53c1086b0a57ca2
Import subrepo unicode-segmentation/:unicode-segmentation at 637c9874c4fe0c205ff27787faf150a40295c6c3
Import subrepo unicode-width/:unicode-width at 3033826f8bf05e82724140a981d5941e48fce393
Import subrepo unicode-xid/:unicode-xid at 4baae9fffb156ba229665b972a9cd5991787ceb7
Diffstat (limited to 'structopt/examples')
-rw-r--r-- | structopt/examples/README.md | 82 | ||||
-rw-r--r-- | structopt/examples/after_help.rs | 19 | ||||
-rw-r--r-- | structopt/examples/at_least_two.rs | 15 | ||||
-rw-r--r-- | structopt/examples/basic.rs | 48 | ||||
-rw-r--r-- | structopt/examples/deny_missing_docs.rs | 51 | ||||
-rw-r--r-- | structopt/examples/doc_comments.rs | 74 | ||||
-rw-r--r-- | structopt/examples/enum_in_args.rs | 25 | ||||
-rw-r--r-- | structopt/examples/enum_tuple.rs | 26 | ||||
-rw-r--r-- | structopt/examples/env.rs | 26 | ||||
-rw-r--r-- | structopt/examples/example.rs | 54 | ||||
-rw-r--r-- | structopt/examples/flatten.rs | 29 | ||||
-rw-r--r-- | structopt/examples/gen_completions.rs | 26 | ||||
-rw-r--r-- | structopt/examples/git.rs | 35 | ||||
-rw-r--r-- | structopt/examples/group.rs | 31 | ||||
-rw-r--r-- | structopt/examples/keyvalue.rs | 36 | ||||
-rw-r--r-- | structopt/examples/negative_flag.rs | 15 | ||||
-rw-r--r-- | structopt/examples/no_version.rs | 17 | ||||
-rw-r--r-- | structopt/examples/rename_all.rs | 74 | ||||
-rw-r--r-- | structopt/examples/skip.rs | 47 | ||||
-rw-r--r-- | structopt/examples/subcommand_aliases.rs | 21 | ||||
-rw-r--r-- | structopt/examples/true_or_false.rs | 41 |
21 files changed, 792 insertions, 0 deletions
diff --git a/structopt/examples/README.md b/structopt/examples/README.md new file mode 100644 index 0000000..f0db20b --- /dev/null +++ b/structopt/examples/README.md @@ -0,0 +1,82 @@ +# Collection of examples "how to use `structopt`" + +### [Help on the bottom](after_help.rs) + +How to append a postscript to the help message generated. + +### [At least N](at_least_two.rs) + +How to require presence of at least N values, like `val1 val2 ... valN ... valM`. + +### [Basic](basic.rs) + +A basic example how to use `structopt`. + +### [Deny missing docs](deny_missing_docs.rs) + +**This is not an example but a test**, it should be moved to `tests` folder +as soon as [this](https://github.com/rust-lang/rust/issues/24584) is fixed (if ever). + +### [Doc comments](doc_comments.rs) + +How to use doc comments in place of `help/long_help`. + +### [Enums as arguments](enum_in_args.rs) + +How to use `arg_enum!` with `StructOpt`. + +### [Arguments of subcommands in separate `struct`](enum_tuple.rs) + +How to extract subcommands' args into external structs. + +### [Environment variables](env.rs) + +How to use environment variable fallback an how it interacts with `default_value`. + +### [Advanced](example.rs) + +Somewhat complex example of usage of `structopt`. + +### [Flatten](flatten.rs) + +How to use `#[structopt(flatten)]` + +### [`bash` completions](gen_completions.rs) + +Generating `bash` completions with `structopt`. + +### [Git](git.rs) + +Pseudo-`git` example, shows how to use subcommands and how to document them. + +### [Groups](group.rs) + +Using `clap::Arg::group` with `structopt`. + +### [`key=value` pairs](keyvalue.rs) + +How to parse `key=value` pairs. + +### [`--no-*` flags](negative_flag.rs) + +How to add `no-thing` flag which is `true` by default and `false` if passed. + +### [No version](no_version.rs) + +How to completely remove version. + +### [Rename all](rename_all.rs) + +How `#[structopt(rename_all)]` works. + +### [Skip](skip.rs) + +How to use `#[structopt(skip)]`. + +### [Aliases](subcommand_aliases.rs) + +How to use aliases + +### [`true` or `false`](true_or_false.rs) + +How to express "`"true"` or `"false"` argument. diff --git a/structopt/examples/after_help.rs b/structopt/examples/after_help.rs new file mode 100644 index 0000000..db2845f --- /dev/null +++ b/structopt/examples/after_help.rs @@ -0,0 +1,19 @@ +//! How to append a postscript to the help message generated. + +use structopt::StructOpt; + +/// I am a program and I do things. +/// +/// Sometimes they even work. +#[derive(StructOpt, Debug)] +#[structopt(after_help = "Beware `-d`, dragons be here")] +struct Opt { + /// Release the dragon. + #[structopt(short)] + dragon: bool, +} + +fn main() { + let opt = Opt::from_args(); + println!("{:?}", opt); +} diff --git a/structopt/examples/at_least_two.rs b/structopt/examples/at_least_two.rs new file mode 100644 index 0000000..683db50 --- /dev/null +++ b/structopt/examples/at_least_two.rs @@ -0,0 +1,15 @@ +//! How to require presence of at least N values, +//! like `val1 val2 ... valN ... valM`. + +use structopt::StructOpt; + +#[derive(StructOpt, Debug)] +struct Opt { + #[structopt(required = true, min_values = 2)] + foos: Vec<String>, +} + +fn main() { + let opt = Opt::from_args(); + println!("{:?}", opt); +} diff --git a/structopt/examples/basic.rs b/structopt/examples/basic.rs new file mode 100644 index 0000000..510e0e0 --- /dev/null +++ b/structopt/examples/basic.rs @@ -0,0 +1,48 @@ +//! A somewhat comprehensive example of a typical `StructOpt` usage.use + +use std::path::PathBuf; +use structopt::StructOpt; + +/// A basic example +#[derive(StructOpt, Debug)] +#[structopt(name = "basic")] +struct Opt { + // A flag, true if used in the command line. Note doc comment will + // be used for the help message of the flag. The name of the + // argument will be, by default, based on the name of the field. + /// Activate debug mode + #[structopt(short, long)] + debug: bool, + + // The number of occurrences of the `v/verbose` flag + /// Verbose mode (-v, -vv, -vvv, etc.) + #[structopt(short, long, parse(from_occurrences))] + verbose: u8, + + /// Set speed + #[structopt(short, long, default_value = "42")] + speed: f64, + + /// Output file + #[structopt(short, long, parse(from_os_str))] + output: PathBuf, + + // the long option will be translated by default to kebab case, + // i.e. `--nb-cars`. + /// Number of cars + #[structopt(short = "c", long)] + nb_cars: Option<i32>, + + /// admin_level to consider + #[structopt(short, long)] + level: Vec<String>, + + /// Files to process + #[structopt(name = "FILE", parse(from_os_str))] + files: Vec<PathBuf>, +} + +fn main() { + let opt = Opt::from_args(); + println!("{:#?}", opt); +} diff --git a/structopt/examples/deny_missing_docs.rs b/structopt/examples/deny_missing_docs.rs new file mode 100644 index 0000000..82b1e63 --- /dev/null +++ b/structopt/examples/deny_missing_docs.rs @@ -0,0 +1,51 @@ +// 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. + +// This should be in tests but it will not work until +// https://github.com/rust-lang/rust/issues/24584 is fixed + +//! A test to check that structopt compiles with deny(missing_docs) + +#![deny(missing_docs)] + +use structopt::StructOpt; + +/// The options +#[derive(StructOpt, Debug, PartialEq)] +pub struct Opt { + #[structopt(short)] + verbose: bool, + #[structopt(subcommand)] + cmd: Option<Cmd>, +} + +/// Some subcommands +#[derive(StructOpt, Debug, PartialEq)] +pub enum Cmd { + /// command A + A, + /// command B + B { + /// Alice? + #[structopt(short)] + alice: bool, + }, + /// command C + C(COpt), +} + +/// The options for C +#[derive(StructOpt, Debug, PartialEq)] +pub struct COpt { + #[structopt(short)] + bob: bool, +} + +fn main() { + println!("{:?}", Opt::from_args()); +} diff --git a/structopt/examples/doc_comments.rs b/structopt/examples/doc_comments.rs new file mode 100644 index 0000000..810101f --- /dev/null +++ b/structopt/examples/doc_comments.rs @@ -0,0 +1,74 @@ +//! How to use doc comments in place of `help/long_help`. + +use structopt::StructOpt; + +/// A basic example for the usage of doc comments as replacement +/// of the arguments `help`, `long_help`, `about` and `long_about`. +#[derive(StructOpt, Debug)] +#[structopt(name = "basic")] +struct Opt { + /// Just use doc comments to replace `help`, `long_help`, + /// `about` or `long_about` input. + #[structopt(short, long)] + first_flag: bool, + + /// Split between `help` and `long_help`. + /// + /// In the previous case structopt is going to present + /// the whole comment both as text for the `help` and the + /// `long_help` argument. + /// + /// But if the doc comment is formatted like this example + /// -- with an empty second line splitting the heading and + /// the rest of the comment -- only the first line is used + /// as `help` argument. The `long_help` argument will still + /// contain the whole comment. + /// + /// ## Attention + /// + /// Any formatting next to empty lines that could be used + /// inside a doc comment is currently not preserved. If + /// lists or other well formatted content is required it is + /// necessary to use the related structopt argument with a + /// raw string as shown on the `third_flag` description. + #[structopt(short, long)] + second_flag: bool, + + #[structopt( + short, + long, + long_help = r"This is a raw string. + +It can be used to pass well formatted content (e.g. lists or source +code) in the description: + + - first example list entry + - second example list entry + " + )] + third_flag: bool, + + #[structopt(subcommand)] + sub_command: SubCommand, +} + +#[derive(StructOpt, Debug)] +#[structopt()] +enum SubCommand { + /// The same rules described previously for flags. Are + /// also true for in regards of sub-commands. + First, + + /// Applicable for both `about` an `help`. + /// + /// The formatting rules described in the comment of the + /// `second_flag` also apply to the description of + /// sub-commands which is normally given through the `about` + /// and `long_about` arguments. + Second, +} + +fn main() { + let opt = Opt::from_args(); + println!("{:?}", opt); +} diff --git a/structopt/examples/enum_in_args.rs b/structopt/examples/enum_in_args.rs new file mode 100644 index 0000000..70347da --- /dev/null +++ b/structopt/examples/enum_in_args.rs @@ -0,0 +1,25 @@ +//! How to use `arg_enum!` with `StructOpt`. + +use clap::arg_enum; +use structopt::StructOpt; + +arg_enum! { + #[derive(Debug)] + enum Baz { + Foo, + Bar, + FooBar + } +} + +#[derive(StructOpt, Debug)] +struct Opt { + /// Important argument. + #[structopt(possible_values = &Baz::variants(), case_insensitive = true)] + i: Baz, +} + +fn main() { + let opt = Opt::from_args(); + println!("{:?}", opt); +} diff --git a/structopt/examples/enum_tuple.rs b/structopt/examples/enum_tuple.rs new file mode 100644 index 0000000..0bad2e6 --- /dev/null +++ b/structopt/examples/enum_tuple.rs @@ -0,0 +1,26 @@ +//! How to extract subcommands' args into external structs. + +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +pub struct Foo { + pub bar: Option<String>, +} + +#[derive(Debug, StructOpt)] +pub enum Command { + #[structopt(name = "foo")] + Foo(Foo), +} + +#[derive(Debug, StructOpt)] +#[structopt(name = "classify")] +pub struct ApplicationArguments { + #[structopt(subcommand)] + pub command: Command, +} + +fn main() { + let opt = ApplicationArguments::from_args(); + println!("{:?}", opt); +} diff --git a/structopt/examples/env.rs b/structopt/examples/env.rs new file mode 100644 index 0000000..0477089 --- /dev/null +++ b/structopt/examples/env.rs @@ -0,0 +1,26 @@ +//! How to use environment variable fallback an how it +//! interacts with `default_value`. + +use structopt::StructOpt; + +/// Example for allowing to specify options via environment variables. +#[derive(StructOpt, Debug)] +#[structopt(name = "env")] +struct Opt { + // Use `env` to enable specifying the option with an environment + // variable. Command line arguments take precedence over env. + /// URL for the API server + #[structopt(long, env = "API_URL")] + api_url: String, + + // The default value is used if neither argument nor environment + // variable is specified. + /// Number of retries + #[structopt(long, env = "RETRIES", default_value = "5")] + retries: u32, +} + +fn main() { + let opt = Opt::from_args(); + println!("{:#?}", opt); +} diff --git a/structopt/examples/example.rs b/structopt/examples/example.rs new file mode 100644 index 0000000..7a9a514 --- /dev/null +++ b/structopt/examples/example.rs @@ -0,0 +1,54 @@ +//! Somewhat complex example of usage of structopt. + +use structopt::StructOpt; + +#[derive(StructOpt, Debug)] +#[structopt(name = "example")] +/// An example of StructOpt usage. +struct Opt { + // A flag, true if used in the command line. + #[structopt(short, long)] + /// Activate debug mode + debug: bool, + + // An argument of type float, with a default value. + #[structopt(short, long, default_value = "42")] + /// Set speed + speed: f64, + + // Needed parameter, the first on the command line. + /// Input file + input: String, + + // An optional parameter, will be `None` if not present on the + // command line. + /// Output file, stdout if not present + output: Option<String>, + + // An optional parameter with optional value, will be `None` if + // not present on the command line, will be `Some(None)` if no + // argument is provided (i.e. `--log`) and will be + // `Some(Some(String))` if argument is provided (e.g. `--log + // log.txt`). + #[structopt(long)] + #[allow(clippy::option_option)] + /// Log file, stdout if no file, no logging if not present + log: Option<Option<String>>, + + // An optional list of values, will be `None` if not present on + // the command line, will be `Some(vec![])` if no argument is + // provided (i.e. `--optv`) and will be `Some(Some(String))` if + // argument list is provided (e.g. `--optv a b c`). + #[structopt(long)] + optv: Option<Vec<String>>, + + // Skipped option: it won't be parsed and will be filled with the + // default value for its type (in this case it'll be an empty string). + #[structopt(skip)] + skipped: String, +} + +fn main() { + let opt = Opt::from_args(); + println!("{:?}", opt); +} diff --git a/structopt/examples/flatten.rs b/structopt/examples/flatten.rs new file mode 100644 index 0000000..d51647f --- /dev/null +++ b/structopt/examples/flatten.rs @@ -0,0 +1,29 @@ +//! How to use flattening. + +use structopt::StructOpt; + +#[derive(StructOpt, Debug)] +struct Cmdline { + /// switch verbosity on + #[structopt(short)] + verbose: bool, + + #[structopt(flatten)] + daemon_opts: DaemonOpts, +} + +#[derive(StructOpt, Debug)] +struct DaemonOpts { + /// daemon user + #[structopt(short)] + user: String, + + /// daemon group + #[structopt(short)] + group: String, +} + +fn main() { + let opt = Cmdline::from_args(); + println!("{:?}", opt); +} diff --git a/structopt/examples/gen_completions.rs b/structopt/examples/gen_completions.rs new file mode 100644 index 0000000..4f35b07 --- /dev/null +++ b/structopt/examples/gen_completions.rs @@ -0,0 +1,26 @@ +// Copyright 2019-present structopt developers +// +// 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. + +use structopt::clap::Shell; +use structopt::StructOpt; + +#[derive(StructOpt, Debug)] +/// An example of how to generate bash completions with structopt. +struct Opt { + #[structopt(short, long)] + /// Activate debug mode + debug: bool, +} + +fn main() { + // generate `bash` completions in "target" directory + Opt::clap().gen_completions(env!("CARGO_PKG_NAME"), Shell::Bash, "target"); + + let opt = Opt::from_args(); + println!("{:?}", opt); +} diff --git a/structopt/examples/git.rs b/structopt/examples/git.rs new file mode 100644 index 0000000..494e9d1 --- /dev/null +++ b/structopt/examples/git.rs @@ -0,0 +1,35 @@ +//! `git.rs` serves as a demonstration of how to use subcommands, +//! as well as a demonstration of adding documentation to subcommands. +//! Documentation can be added either through doc comments or +//! `help`/`about` attributes. + +use structopt::StructOpt; + +#[derive(StructOpt, Debug)] +#[structopt(name = "git")] +/// the stupid content tracker +enum Opt { + /// fetch branches from remote repository + Fetch { + #[structopt(long)] + dry_run: bool, + #[structopt(long)] + all: bool, + #[structopt(default_value = "origin")] + repository: String, + }, + #[structopt(help = "add files to the staging area")] + Add { + #[structopt(short)] + interactive: bool, + #[structopt(short)] + all: bool, + files: Vec<String>, + }, +} + +fn main() { + let matches = Opt::from_args(); + + println!("{:?}", matches); +} diff --git a/structopt/examples/group.rs b/structopt/examples/group.rs new file mode 100644 index 0000000..d53de6a --- /dev/null +++ b/structopt/examples/group.rs @@ -0,0 +1,31 @@ +//! How to use `clap::Arg::group` + +use structopt::{clap::ArgGroup, StructOpt}; + +#[derive(StructOpt, Debug)] +#[structopt(group = ArgGroup::with_name("verb").required(true))] +struct Opt { + /// Set a custom HTTP verb + #[structopt(long, group = "verb")] + method: Option<String>, + /// HTTP GET + #[structopt(long, group = "verb")] + get: bool, + /// HTTP HEAD + #[structopt(long, group = "verb")] + head: bool, + /// HTTP POST + #[structopt(long, group = "verb")] + post: bool, + /// HTTP PUT + #[structopt(long, group = "verb")] + put: bool, + /// HTTP DELETE + #[structopt(long, group = "verb")] + delete: bool, +} + +fn main() { + let opt = Opt::from_args(); + println!("{:?}", opt); +} diff --git a/structopt/examples/keyvalue.rs b/structopt/examples/keyvalue.rs new file mode 100644 index 0000000..12ce6fc --- /dev/null +++ b/structopt/examples/keyvalue.rs @@ -0,0 +1,36 @@ +//! How to parse "key=value" pairs with structopt. + +use std::error::Error; +use structopt::StructOpt; + +/// Parse a single key-value pair +fn parse_key_val<T, U>(s: &str) -> Result<(T, U), Box<dyn Error>> +where + T: std::str::FromStr, + T::Err: Error + 'static, + U: std::str::FromStr, + U::Err: Error + 'static, +{ + let pos = s + .find('=') + .ok_or_else(|| format!("invalid KEY=value: no `=` found in `{}`", s))?; + Ok((s[..pos].parse()?, s[pos + 1..].parse()?)) +} + +#[derive(StructOpt, Debug)] +struct Opt { + // number_of_values = 1 forces the user to repeat the -D option for each key-value pair: + // my_program -D a=1 -D b=2 + // Without number_of_values = 1 you can do: + // my_program -D a=1 b=2 + // but this makes adding an argument after the values impossible: + // my_program -D a=1 -D b=2 my_input_file + // becomes invalid. + #[structopt(short = "D", parse(try_from_str = parse_key_val), number_of_values = 1)] + defines: Vec<(String, i32)>, +} + +fn main() { + let opt = Opt::from_args(); + println!("{:?}", opt); +} diff --git a/structopt/examples/negative_flag.rs b/structopt/examples/negative_flag.rs new file mode 100644 index 0000000..b178bf5 --- /dev/null +++ b/structopt/examples/negative_flag.rs @@ -0,0 +1,15 @@ +//! How to add `no-thing` flag which is `true` by default and +//! `false` if passed. + +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +struct Opt { + #[structopt(long = "no-verbose", parse(from_flag = std::ops::Not::not))] + verbose: bool, +} + +fn main() { + let cmd = Opt::from_args(); + println!("{:#?}", cmd); +} diff --git a/structopt/examples/no_version.rs b/structopt/examples/no_version.rs new file mode 100644 index 0000000..a542ec1 --- /dev/null +++ b/structopt/examples/no_version.rs @@ -0,0 +1,17 @@ +//! How to completely remove version. + +use structopt::clap::AppSettings; +use structopt::StructOpt; + +#[derive(StructOpt, Debug)] +#[structopt( + name = "no_version", + no_version, + global_settings = &[AppSettings::DisableVersion] +)] +struct Opt {} + +fn main() { + let opt = Opt::from_args(); + println!("{:?}", opt); +} diff --git a/structopt/examples/rename_all.rs b/structopt/examples/rename_all.rs new file mode 100644 index 0000000..35f3c4f --- /dev/null +++ b/structopt/examples/rename_all.rs @@ -0,0 +1,74 @@ +//! Example on how the `rename_all` parameter works. +//! +//! `rename_all` can be used to override the casing style used during argument +//! generation. By default the `kebab-case` style will be used but there are a wide +//! variety of other styles available. +//! +//! ## Supported styles overview: +//! +//! - **Camel Case**: Indicate word boundaries with uppercase letter, excluding +//! the first word. +//! - **Kebab Case**: Keep all letters lowercase and indicate word boundaries +//! with hyphens. +//! - **Pascal Case**: Indicate word boundaries with uppercase letter, +//! including the first word. +//! - **Screaming Snake Case**: Keep all letters uppercase and indicate word +//! boundaries with underscores. +//! - **Snake Case**: Keep all letters lowercase and indicate word boundaries +//! with underscores. +//! - **Verbatim**: Use the original attribute name defined in the code. + +use structopt::StructOpt; + +#[derive(StructOpt, Debug)] +#[structopt(name = "rename_all", rename_all = "screaming_snake_case")] +enum Opt { + // This subcommand will be named `FIRST_COMMAND`. As the command doesn't + // override the initial casing style, ... + /// A screaming loud first command. Only use if necessary. + FirstCommand { + // this flag will be available as `--FOO` and `-F`. + /// This flag will even scream louder. + #[structopt(long, short)] + foo: bool, + }, + + // As we override the casing style for this variant the related subcommand + // will be named `SecondCommand`. + /// Not nearly as loud as the first command. + #[structopt(rename_all = "pascal_case")] + SecondCommand { + // We can also override it again on a single field. + /// Nice quiet flag. No one is annoyed. + #[structopt(rename_all = "snake_case", long)] + bar_option: bool, + + // Renaming will not be propagated into subcommand flagged enums. If + // a non default casing style is required it must be defined on the + // enum itself. + #[structopt(subcommand)] + cmds: Subcommands, + + // or flattened structs. + #[structopt(flatten)] + options: BonusOptions, + }, +} + +#[derive(StructOpt, Debug)] +enum Subcommands { + // This one will be available as `first-subcommand`. + FirstSubcommand, +} + +#[derive(StructOpt, Debug)] +struct BonusOptions { + // And this one will be available as `baz-option`. + #[structopt(long)] + baz_option: bool, +} + +fn main() { + let opt = Opt::from_args(); + println!("{:?}", opt); +} diff --git a/structopt/examples/skip.rs b/structopt/examples/skip.rs new file mode 100644 index 0000000..1f44769 --- /dev/null +++ b/structopt/examples/skip.rs @@ -0,0 +1,47 @@ +//! How to use `#[structopt(skip)]` + +use structopt::StructOpt; + +#[derive(StructOpt, Debug, PartialEq)] +pub struct Opt { + #[structopt(long, short)] + number: u32, + #[structopt(skip)] + k: Kind, + #[structopt(skip)] + v: Vec<u32>, + + #[structopt(skip = Kind::A)] + k2: Kind, + #[structopt(skip = vec![1, 2, 3])] + v2: Vec<u32>, + #[structopt(skip = "cake")] // &str implements Into<String> + s: String, +} + +#[derive(Debug, PartialEq)] +enum Kind { + A, + B, +} + +impl Default for Kind { + fn default() -> Self { + return Kind::B; + } +} + +fn main() { + assert_eq!( + Opt::from_iter(&["test", "-n", "10"]), + Opt { + number: 10, + k: Kind::B, + v: vec![], + + k2: Kind::A, + v2: vec![1, 2, 3], + s: String::from("cake") + } + ); +} diff --git a/structopt/examples/subcommand_aliases.rs b/structopt/examples/subcommand_aliases.rs new file mode 100644 index 0000000..30b8cc3 --- /dev/null +++ b/structopt/examples/subcommand_aliases.rs @@ -0,0 +1,21 @@ +//! How to assign some aliases to subcommands + +use structopt::clap::AppSettings; +use structopt::StructOpt; + +#[derive(StructOpt, Debug)] +// https://docs.rs/clap/2/clap/enum.AppSettings.html#variant.InferSubcommands +#[structopt(setting = AppSettings::InferSubcommands)] +enum Opt { + // https://docs.rs/clap/2/clap/struct.App.html#method.alias + #[structopt(alias = "foobar")] + Foo, + // https://docs.rs/clap/2/clap/struct.App.html#method.aliases + #[structopt(aliases = &["baz", "fizz"])] + Bar, +} + +fn main() { + let opt = Opt::from_args(); + println!("{:?}", opt); +} diff --git a/structopt/examples/true_or_false.rs b/structopt/examples/true_or_false.rs new file mode 100644 index 0000000..31a543e --- /dev/null +++ b/structopt/examples/true_or_false.rs @@ -0,0 +1,41 @@ +//! How to parse `--foo=true --bar=false` and turn them into bool. + +use structopt::StructOpt; + +fn true_or_false(s: &str) -> Result<bool, &'static str> { + match s { + "true" => Ok(true), + "false" => Ok(false), + _ => Err("expected `true` or `false`"), + } +} + +#[derive(StructOpt, Debug, PartialEq)] +struct Opt { + // Default parser for `try_from_str` is FromStr::from_str. + // `impl FromStr for bool` parses `true` or `false` so this + // works as expected. + #[structopt(long, parse(try_from_str))] + foo: bool, + + // Of course, this could be done with an explicit parser function. + #[structopt(long, parse(try_from_str = true_or_false))] + bar: bool, + + // `bool` can be positional only with explicit `parse(...)` annotation + #[structopt(long, parse(try_from_str))] + boom: bool, +} + +fn main() { + assert_eq!( + Opt::from_iter(&["test", "--foo=true", "--bar=false", "true"]), + Opt { + foo: true, + bar: false, + boom: true + } + ); + // no beauty, only truth and falseness + assert!(Opt::from_iter_safe(&["test", "--foo=beauty"]).is_err()); +} |