diff options
Diffstat (limited to 'structopt')
125 files changed, 0 insertions, 8447 deletions
diff --git a/structopt/.gitignore b/structopt/.gitignore deleted file mode 100644 index ea63af4..0000000 --- a/structopt/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -target -Cargo.lock -*~ - -.idea/ -.vscode/ diff --git a/structopt/.travis.yml b/structopt/.travis.yml deleted file mode 100644 index dff3050..0000000 --- a/structopt/.travis.yml +++ /dev/null @@ -1,24 +0,0 @@ -language: rust -matrix: - include: - - rust: stable - name: check if `cargo fmt --all` is applied - before_script: rustup component add rustfmt-preview - script: cargo fmt --all -- --check - - - language: node_js - node_js: node - name: check links - install: npm install -g markdown-link-check - script: - - markdown-link-check -c link-check-headers.json README.md - - markdown-link-check -c link-check-headers.json CHANGELOG.md - - markdown-link-check -c link-check-headers.json examples/README.md - - - rust: 1.36.0 - - rust: stable - - rust: beta - - rust: nightly - -script: - - cargo test $FEATURES diff --git a/structopt/CHANGELOG.md b/structopt/CHANGELOG.md deleted file mode 100644 index ed2a17f..0000000 --- a/structopt/CHANGELOG.md +++ /dev/null @@ -1,444 +0,0 @@ -# v0.3.7 (2019-12-28) - -Nothing's new. Just re-release of `v0.3.6` due to -[the mess with versioning](https://github.com/TeXitoi/structopt/issues/315#issuecomment-568502792). - -You may notice that `structopt-derive` was bumped to `v0.4.0`, that's OK, it's not a breaking change. -`structopt` will pull the right version in on its on. - -# v0.3.6 (2019-12-22) - YANKED - -This is unusually big patch release. It contains a number of bugfixes and -new features, some of them may theoretically be considered breaking. We did our best -to avoid any problems on user's side but, if it wasn't good enough, please -[file an issue ASAP](https://github.com/TeXitoi/structopt/issues). - -## Bugfixes - -* `structopt` used to treat `::path::to::type::Vec<T>` as `Vec<T>` - special type. [This was considered erroneous](https://github.com/TeXitoi/structopt/pull/287). - (same for `Option<T>` and `bool`). Now only exact `Vec<T>` match is a special type. - -* `#[structopt(version = expr)]` where `expr` is not a string literal used to get - overridden by auto generated `.version()` call, - [incorrectly](https://github.com/TeXitoi/structopt/issues/283). Now it doesn't. - -* Fixed bug with top-level `App::*` calls on multiple `struct`s, see - [#289](https://github.com/TeXitoi/structopt/issues/265). - -* Positional `bool` args with no explicit `#[structopt(parse(...))]` annotation are - now prohibited. This couldn't work well anyway, see - [this example](https://github.com/TeXitoi/structopt/blob/master/examples/true_or_false.rs) - for details. - -* Now we've instituted strict priority between doc comments, about, help, and the like. - See [the documentation](https://docs.rs/structopt/0.3/structopt/#help-messages). - - **HUGE THANKS to [`@ssokolow`](https://github.com/ssokolow)** for tidying up our documentation, - teaching me English and explaining why our doc used to suck. I promise I'll make the rest - of the doc up to your standards... sometime later! - -## New features - -* Implement `StructOpt` for `Box<impl StructOpt>` so from now on you can use `Box<T>` - with `flatten` and `subcommand` ([#304](https://github.com/TeXitoi/structopt/issues/304)). - - ```rust - enum Command { - #[structopt(name = "version")] - PrintVersion, - - #[structopt(name = "second")] - DoSomething { - #[structopt(flatten)] - config: Box<DoSomethingConfig>, - }, - - #[structopt(name = "first")] - DoSomethingElse { - #[structopt(flatten)] - config: Box<DoSomethingElseConfig>, - } - } - ``` - -* Introduced `#[structopt(verbatim_doc_comment)]` attribute that keeps line breaks in - doc comments, see - [the documentation](https://docs.rs/structopt/0.3/structopt/#doc-comment-preprocessing-and-structoptverbatim_doc_comment). - -* Introduced `#[structopt(rename_all_env)]` and `#[structopt(env)]` magical methods - so you can derive env var's name from field's name. See - [the documentation](https://docs.rs/structopt/0.3/structopt/#auto-deriving-environment-variables). - -## Improvements - -* Now we have nice README for our examples, - [check it out](https://github.com/TeXitoi/structopt/tree/master/examples)! - -* Some error messages were improved and clarified, thanks for all people involved! - - -# v0.3.5 (2019-11-22) - -* `try_from_str` functions are now called with a `&str` instead of a `&String` ([#282](https://github.com/TeXitoi/structopt/pull/282)) - -# v0.3.4 (2019-11-08) - -* `rename_all` does not apply to fields that were annotated with explicit - `short/long/name = "..."` anymore ([#265](https://github.com/TeXitoi/structopt/issues/265)) -* Now raw idents are handled correctly ([#269](https://github.com/TeXitoi/structopt/issues/269)) -* Some documentation improvements and clarification. - -# v0.3.3 (2019-10-10) - -* Add `from_flag` custom parser to create flags from non-bool types. - Fixes [#185](https://github.com/TeXitoi/structopt/issues/185) - -# v0.3.2 (2019-09-18) - -* `structopt` does not replace `:` with `, ` inside "author" strings while inside `<...>`. - Fixes [#156](https://github.com/TeXitoi/structopt/issues/156) -* Introduced [`#[structopt(skip = expr)]` syntax](https://docs.rs/structopt/0.3.2/structopt/#skipping-fields). - -# v0.3.1 (2019-09-06) - -* Fix error messages ([#241](https://github.com/TeXitoi/structopt/issues/241)) -* Fix "`skip` plus long doc comment" bug ([#245](https://github.com/TeXitoi/structopt/issues/245)) -* Now `structopt` emits dummy `StructOpt` implementation along with an error. It suppresses - meaningless errors like `from_args method is not found for Opt` -* `.version()` not get generated if `CARGO_PKG_VERSION` is not set anymore. - -# v0.3.0 (2019-08-30) - -## Breaking changes - -### Bump minimum rustc version to 1.36 by [@TeXitoi](https://github.com/TeXitoi) -Now `rustc` 1.36 is the minimum compiler version supported by `structopt`, -it likely won't work with older compilers. - -### Remove "nightly" feature -Once upon a time this feature had been used to enable some of improvements -in `proc-macro2` crate that were available only on nightly. Nowadays this feature doesn't -mean anything so it's now removed. - -### Support optional vectors of arguments for distinguishing between `-o 1 2`, `-o` and no option provided at all by [@sphynx](https://github.com/sphynx) ([#180](https://github.com/TeXitoi/structopt/issues/188)). - -```rust -#[derive(StructOpt)] -struct Opt { - #[structopt(long)] - fruit: Option<Vec<String>>, -} - -fn main() { - assert_eq!(Opt::from_args(&["test"]), None); - assert_eq!(Opt::from_args(&["test", "--fruit"]), Some(vec![])); - assert_eq!(Opt::from_args(&["test", "--fruit=apple orange"]), Some(vec!["apple", "orange"])); -} -``` - -If you need to fall back to the old behavior you can use a type alias: -```rust -type Something = Vec<String>; - -#[derive(StructOpt)] -struct Opt { - #[structopt(long)] - fruit: Option<Something>, -} -``` - -### Change default case from 'Verbatim' into 'Kebab' by [@0ndorio](https://github.com/0ndorio) ([#202](https://github.com/TeXitoi/structopt/issues/202)). -`structopt` 0.3 uses field renaming to deduce a name for long options and subcommands. - -```rust -#[derive(StructOpt)] -struct Opt { - #[structopt(long)] - http_addr: String, // will be renamed to `--http-addr` - - #[structopt(subcommand)] - addr_type: AddrType // this adds `addr-type` subcommand -} -``` - -`structopt` 0.2 used to leave things "as is", not renaming anything. If you want to keep old -behavior add `#[structopt(rename_all = "verbatim")]` on top of a `struct`/`enum`. - -### Change `version`, `author` and `about` attributes behavior. -Proposed by [@TeXitoi](https://github.com/TeXitoi) [(#217)](https://github.com/TeXitoi/structopt/issues/217), implemented by [@CreepySkeleton](https://github.com/CreepySkeleton) [(#229)](https://github.com/TeXitoi/structopt/pull/229). - -`structopt` have been deducing `version`, `author`, and `about` properties from `Cargo.toml` -for a long time (more accurately, from `CARGO_PKG_...` environment variables). -But many users found this behavior somewhat confusing, and a hack was added to cancel out -this behavior: `#[structopt(author = "")]`. - -In `structopt` 0.3 this has changed. -* `author` and `about` are no longer deduced by default. You should use `#[structopt(author, about)]` - to explicitly request `structopt` to deduce them. -* Contrary, `version` **is still deduced by default**. You can use `#[structopt(no_version)]` to - cancel it out. -* `#[structopt(author = "", about = "", version = "")]` is no longer a valid syntax - and will trigger an error. -* `#[structopt(version = "version", author = "author", about = "about")]` syntax - stays unaffected by this changes. - -### Raw attributes are removed ([#198](https://github.com/TeXitoi/structopt/pull/198)) by [@sphynx](https://github.com/sphynx) -In `structopt` 0.2 you were able to use any method from `clap::App` and `clap::Arg` via -raw attribute: `#[structopt(raw(method_name = "arg"))]`. This syntax was kind of awkward. - -```rust -#[derive(StructOpt, Debug)] -#[structopt(raw( - global_settings = "&[AppSettings::ColoredHelp, AppSettings::VersionlessSubcommands]" -))] -struct Opt { - #[structopt(short = "l", long = "level", raw(aliases = r#"&["set-level", "lvl"]"#))] - level: Vec<String>, -} -``` - -Raw attributes were removed in 0.3. Now you can use any method from `App` and `Arg` *directly*: -```rust -#[derive(StructOpt)] -#[structopt(global_settings(&[AppSettings::ColoredHelp, AppSettings::VersionlessSubcommands]))] -struct Opt { - #[structopt(short = "l", long = "level", aliases(&["set-level", "lvl"]))] - level: Vec<String>, -} -``` - -## Improvements - -### Support skipping struct fields -Proposed by [@Morganamilo](https://github.com/Morganamilo) in ([#174](https://github.com/TeXitoi/structopt/issues/174)) -implemented by [@sphynx](https://github.com/sphynx) in ([#213](https://github.com/TeXitoi/structopt/issues/213)). - -Sometimes you want to include some fields in your `StructOpt` `struct` that are not options -and `clap` should know nothing about them. In `structopt` 0.3 it's possible via the -`#[structopt(skip)]` attribute. The field in question will be assigned with `Default::default()` -value. - -```rust -#[derive(StructOpt)] -struct Opt { - #[structopt(short, long)] - speed: f32, - - car: String, - - // this field should not generate any arguments - #[structopt(skip)] - meta: Vec<u64> -} -``` - -### Add optional feature to support `paw` by [@gameldar](https://github.com/gameldar) ([#187](https://github.com/TeXitoi/structopt/issues/187)) - -### Significantly improve error reporting by [@CreepySkeleton](https://github.com/CreepySkeleton) ([#225](https://github.com/TeXitoi/structopt/pull/225/)) -Now (almost) every error message points to the location it originates from: - -```text -error: default_value is meaningless for bool - --> $DIR/bool_default_value.rs:14:24 - | -14 | #[structopt(short, default_value = true)] - | ^^^^^^^^^^^^^ -``` - -# v0.2.16 (2019-05-29) - -### Support optional options with optional argument, allowing `cmd [--opt[=value]]` by [@sphynx](https://github.com/sphynx) ([#188](https://github.com/TeXitoi/structopt/issues/188)) -Sometimes you want to represent an optional option that optionally takes an argument, -i.e `[--opt[=value]]`. This is represented by `Option<Option<T>>` - -```rust -#[derive(StructOpt)] -struct Opt { - #[structopt(long)] - fruit: Option<Option<String>>, -} - -fn main() { - assert_eq!(Opt::from_args(&["test"]), None); - assert_eq!(Opt::from_args(&["test", "--fruit"]), Some(None)); - assert_eq!(Opt::from_args(&["test", "--fruit=apple"]), Some("apple")); -} -``` - -# v0.2.15 (2019-03-08) - -* Fix [#168](https://github.com/TeXitoi/structopt/issues/168) by [@TeXitoi](https://github.com/TeXitoi) - -# v0.2.14 (2018-12-10) - -* Introduce smarter parsing of doc comments by [@0ndorio](https://github.com/0ndorio) - -# v0.2.13 (2018-11-01) - -* Automatic naming of fields and subcommands by [@0ndorio](https://github.com/0ndorio) - -# v0.2.12 (2018-10-11) - -* Fix minimal clap version by [@TeXitoi](https://github.com/TeXitoi) - -# v0.2.11 (2018-10-05) - -* Upgrade syn to 0.15 by [@konstin](https://github.com/konstin) - -# v0.2.10 (2018-06-07) - -* 1.21.0 is the minimum required rustc version by - [@TeXitoi](https://github.com/TeXitoi) - -# v0.2.9 (2018-06-05) - -* Fix a bug when using `flatten` by - [@fbenkstein](https://github.com/fbenkstein) -* Update syn, quote and proc_macro2 by - [@TeXitoi](https://github.com/TeXitoi) -* Fix a regression when there is multiple authors by - [@windwardly](https://github.com/windwardly) - -# v0.2.8 (2018-04-28) - -* Add `StructOpt::from_iter_safe()`, which returns an `Error` instead of - killing the program when it fails to parse, or parses one of the - short-circuiting flags. ([#98](https://github.com/TeXitoi/structopt/pull/98) - by [@quodlibetor](https://github.com/quodlibetor)) -* Allow users to enable `clap` features independently by - [@Kerollmops](https://github.com/Kerollmops) -* Fix a bug when flattening an enum - ([#103](https://github.com/TeXitoi/structopt/pull/103) by - [@TeXitoi](https://github.com/TeXitoi) - -# v0.2.7 (2018-04-12) - -* Add flattening, the insertion of options of another StructOpt struct - into another ([#92](https://github.com/TeXitoi/structopt/pull/92)) - by [@birkenfeld](https://github.com/birkenfeld) -* Fail compilation when using `default_value` or `required` with - `Option` ([#88](https://github.com/TeXitoi/structopt/pull/88)) by - [@Kerollmops](https://github.com/Kerollmops) - -# v0.2.6 (2018-03-31) - -* Fail compilation when using `default_value` or `required` with `bool` ([#80](https://github.com/TeXitoi/structopt/issues/80)) by [@TeXitoi](https://github.com/TeXitoi) -* Fix compilation with `#[deny(warnings)]` with the `!` type (https://github.com/rust-lang/rust/pull/49039#issuecomment-376398999) by [@TeXitoi](https://github.com/TeXitoi) -* Improve first example in the documentation ([#82](https://github.com/TeXitoi/structopt/issues/82)) by [@TeXitoi](https://github.com/TeXitoi) - -# v0.2.5 (2018-03-07) - -* Work around breakage when `proc-macro2`'s nightly feature is enabled. ([#77](https://github.com/Texitoi/structopt/pull/77) and [proc-macro2#67](https://github.com/alexcrichton/proc-macro2/issues/67)) by [@fitzgen](https://github.com/fitzgen) - -# v0.2.4 (2018-02-25) - -* Fix compilation with `#![deny(missig_docs]` ([#74](https://github.com/TeXitoi/structopt/issues/74)) by [@TeXitoi](https://github.com/TeXitoi) -* Fix [#76](https://github.com/TeXitoi/structopt/issues/76) by [@TeXitoi](https://github.com/TeXitoi) -* Re-licensed to Apache-2.0/MIT by [@CAD97](https://github.com/cad97) - -# v0.2.3 (2018-02-16) - -* An empty line in a doc comment will result in a double linefeed in the generated about/help call by [@TeXitoi](https://github.com/TeXitoi) - -# v0.2.2 (2018-02-12) - -* Fix [#66](https://github.com/TeXitoi/structopt/issues/66) by [@TeXitoi](https://github.com/TeXitoi) - -# v0.2.1 (2018-02-11) - -* Fix a bug around enum tuple and the about message in the global help by [@TeXitoi](https://github.com/TeXitoi) -* Fix [#65](https://github.com/TeXitoi/structopt/issues/65) by [@TeXitoi](https://github.com/TeXitoi) - -# v0.2.0 (2018-02-10) - -## Breaking changes - -### Don't special case `u64` by [@SergioBenitez](https://github.com/SergioBenitez) - -If you are using a `u64` in your struct to get the number of occurence of a flag, you should now add `parse(from_occurrences)` on the flag. - -For example -```rust -#[structopt(short = "v", long = "verbose")] -verbose: u64, -``` -must be changed by -```rust -#[structopt(short = "v", long = "verbose", parse(from_occurrences))] -verbose: u64, -``` - -This feature was surprising as shown in [#30](https://github.com/TeXitoi/structopt/issues/30). Using the `parse` feature seems much more natural. - -### Change the signature of `Structopt::from_clap` to take its argument by reference by [@TeXitoi](https://github.com/TeXitoi) - -There was no reason to take the argument by value. Most of the StructOpt users will not be impacted by this change. If you are using `StructOpt::from_clap`, just add a `&` before the argument. - -### Fail if attributes are not used by [@TeXitoi](https://github.com/TeXitoi) - -StructOpt was quite fuzzy in its attribute parsing: it was only searching for interresting things, e. g. something like `#[structopt(foo(bar))]` was accepted but not used. It now fails the compilation. - -You should have nothing to do here. This breaking change may highlight some missuse that can be bugs. - -In future versions, if there is cases that are not highlighed, they will be considerated as bugs, not breaking changes. - -### Use `raw()` wrapping instead of `_raw` suffixing by [@TeXitoi](https://github.com/TeXitoi) - -The syntax of raw attributes is changed to improve the syntax. - -You have to change `foo_raw = "bar", baz_raw = "foo"` by `raw(foo = "bar", baz = "foo")` or `raw(foo = "bar"), raw(baz = "foo")`. - -## New features - -* Add `parse(from_occurrences)` parser by [@SergioBenitez](https://github.com/SergioBenitez) -* Support 1-uple enum variant as subcommand by [@TeXitoi](https://github.com/TeXitoi) -* structopt-derive crate is now an implementation detail, structopt reexport the custom derive macro by [@TeXitoi](https://github.com/TeXitoi) -* Add the `StructOpt::from_iter` method by [@Kerollmops](https://github.com/Kerollmops) - -## Documentation - -* Improve doc by [@bestouff](https://github.com/bestouff) -* All the documentation is now on the structopt crate by [@TeXitoi](https://github.com/TeXitoi) - -# v0.1.7 (2018-01-23) - -* Allow opting out of clap default features by [@ski-csis](https://github.com/ski-csis) - -# v0.1.6 (2017-11-25) - -* Improve documentation by [@TeXitoi](https://github.com/TeXitoi) -* Fix bug [#31](https://github.com/TeXitoi/structopt/issues/31) by [@TeXitoi](https://github.com/TeXitoi) - -# v0.1.5 (2017-11-14) - -* Fix a bug with optional subsubcommand and Enum by [@TeXitoi](https://github.com/TeXitoi) - -# v0.1.4 (2017-11-09) - -* Implement custom string parser from either `&str` or `&OsStr` by [@kennytm](https://github.com/kennytm) - -# v0.1.3 (2017-11-01) - -* Improve doc by [@TeXitoi](https://github.com/TeXitoi) - -# v0.1.2 (2017-11-01) - -* Fix bugs [#24](https://github.com/TeXitoi/structopt/issues/24) and [#25](https://github.com/TeXitoi/structopt/issues/25) by [@TeXitoi](https://github.com/TeXitoi) -* Support of methods with something else that a string as argument thanks to `_raw` suffix by [@Flakebi](https://github.com/Flakebi) - -# v0.1.1 (2017-09-22) - -* Better formating of multiple authors by [@killercup](https://github.com/killercup) - -# v0.1.0 (2017-07-17) - -* Subcommand support by [@williamyaoh](https://github.com/williamyaoh) - -# v0.0.5 (2017-06-16) - -* Using doc comment to populate help by [@killercup](https://github.com/killercup) - -# v0.0.3 (2017-02-11) - -* First version with flags, arguments and options support by [@TeXitoi](https://github.com/TeXitoi) diff --git a/structopt/Cargo.toml b/structopt/Cargo.toml deleted file mode 100644 index b43728b..0000000 --- a/structopt/Cargo.toml +++ /dev/null @@ -1,35 +0,0 @@ -[package] -name = "structopt" -version = "0.3.7" -edition = "2018" -authors = ["Guillaume Pinot <texitoi@texitoi.eu>", "others"] -description = "Parse command line argument by defining a struct." -documentation = "https://docs.rs/structopt" -repository = "https://github.com/TeXitoi/structopt" -keywords = ["clap", "cli", "derive", "docopt"] -categories = ["command-line-interface"] -license = "Apache-2.0/MIT" -readme = "README.md" - -[features] -default = ["clap/default"] -suggestions = ["clap/suggestions"] -color = ["clap/color"] -wrap_help = ["clap/wrap_help"] -yaml = ["clap/yaml"] -lints = ["clap/lints"] -debug = ["clap/debug"] -no_cargo = ["clap/no_cargo"] -doc = ["clap/doc"] -paw = ["structopt-derive/paw"] - -[badges] -travis-ci = { repository = "TeXitoi/structopt" } - -[dependencies] -clap = { version = "2.33", default-features = false } -structopt-derive = { path = "structopt-derive", version = "=0.4.0" } - -[dev-dependencies] -trybuild = "1.0.5" -rustversion = "1" diff --git a/structopt/LICENSE-APACHE b/structopt/LICENSE-APACHE deleted file mode 100644 index 261eeb9..0000000 --- a/structopt/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/structopt/LICENSE-MIT b/structopt/LICENSE-MIT deleted file mode 100644 index e931b83..0000000 --- a/structopt/LICENSE-MIT +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu> - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/structopt/README.md b/structopt/README.md deleted file mode 100644 index 48ac3c3..0000000 --- a/structopt/README.md +++ /dev/null @@ -1,148 +0,0 @@ -# StructOpt [![Build status](https://travis-ci.org/TeXitoi/structopt.svg?branch=master)](https://travis-ci.org/TeXitoi/structopt) [![](https://img.shields.io/crates/v/structopt.svg)](https://crates.io/crates/structopt) [![](https://docs.rs/structopt/badge.svg)](https://docs.rs/structopt) - -Parse command line arguments by defining a struct. It combines [clap](https://crates.io/crates/clap) with custom derive. - -## Documentation - -Find it on [Docs.rs](https://docs.rs/structopt). You can also check the [examples](https://github.com/TeXitoi/structopt/tree/master/examples) and the [changelog](https://github.com/TeXitoi/structopt/blob/master/CHANGELOG.md). - -## Example - -Add `structopt` to your dependencies of your `Cargo.toml`: -```toml -[dependencies] -structopt = "0.3" -``` - -And then, in your rust file: -```rust -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); -} -``` - -Using this example: -``` -$ ./basic -error: The following required arguments were not provided: - --output <output> - -USAGE: - basic --output <output> --speed <speed> - -For more information try --help -$ ./basic --help -basic 0.3.0 -Guillaume Pinot <texitoi@texitoi.eu>, others -A basic example - -USAGE: - basic [FLAGS] [OPTIONS] --output <output> [--] [file]... - -FLAGS: - -d, --debug Activate debug mode - -h, --help Prints help information - -V, --version Prints version information - -v, --verbose Verbose mode (-v, -vv, -vvv, etc.) - -OPTIONS: - -l, --level <level>... admin_level to consider - -c, --nb-cars <nb-cars> Number of cars - -o, --output <output> Output file - -s, --speed <speed> Set speed [default: 42] - -ARGS: - <file>... Files to process -$ ./basic -o foo.txt -Opt { - debug: false, - verbose: 0, - speed: 42.0, - output: "foo.txt", - nb_cars: None, - level: [], - files: [], -} -$ ./basic -o foo.txt -dvvvs 1337 -l alice -l bob --nb-cars 4 bar.txt baz.txt -Opt { - debug: true, - verbose: 3, - speed: 1337.0, - output: "foo.txt", - nb_cars: Some( - 4, - ), - level: [ - "alice", - "bob", - ], - files: [ - "bar.txt", - "baz.txt", - ], -} -``` - -## StructOpt rustc version policy - -- Minimum rustc version modification must be specified in the [changelog](https://github.com/TeXitoi/structopt/blob/master/CHANGELOG.md) and in the [travis configuration](https://github.com/TeXitoi/structopt/blob/master/.travis.yml). -- Contributors can increment minimum rustc version without any justification if the new version is required by the latest version of one of StructOpt's dependencies (`cargo update` will not fail on StructOpt). -- Contributors can increment minimum rustc version if the library user experience is improved. - -## License - -Licensed under either of - -- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or <https://www.apache.org/licenses/LICENSE-2.0>) -- MIT license ([LICENSE-MIT](LICENSE-MIT) or <https://opensource.org/licenses/MIT>) - -at your option. - -### Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in the work by you, as defined in the Apache-2.0 license, shall be -dual licensed as above, without any additional terms or conditions. diff --git a/structopt/examples/README.md b/structopt/examples/README.md deleted file mode 100644 index f0db20b..0000000 --- a/structopt/examples/README.md +++ /dev/null @@ -1,82 +0,0 @@ -# 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 deleted file mode 100644 index db2845f..0000000 --- a/structopt/examples/after_help.rs +++ /dev/null @@ -1,19 +0,0 @@ -//! 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 deleted file mode 100644 index 683db50..0000000 --- a/structopt/examples/at_least_two.rs +++ /dev/null @@ -1,15 +0,0 @@ -//! 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 deleted file mode 100644 index 510e0e0..0000000 --- a/structopt/examples/basic.rs +++ /dev/null @@ -1,48 +0,0 @@ -//! 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 deleted file mode 100644 index 82b1e63..0000000 --- a/structopt/examples/deny_missing_docs.rs +++ /dev/null @@ -1,51 +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. - -// 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 deleted file mode 100644 index 810101f..0000000 --- a/structopt/examples/doc_comments.rs +++ /dev/null @@ -1,74 +0,0 @@ -//! 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 deleted file mode 100644 index 70347da..0000000 --- a/structopt/examples/enum_in_args.rs +++ /dev/null @@ -1,25 +0,0 @@ -//! 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 deleted file mode 100644 index 0bad2e6..0000000 --- a/structopt/examples/enum_tuple.rs +++ /dev/null @@ -1,26 +0,0 @@ -//! 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 deleted file mode 100644 index 0477089..0000000 --- a/structopt/examples/env.rs +++ /dev/null @@ -1,26 +0,0 @@ -//! 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 deleted file mode 100644 index 7a9a514..0000000 --- a/structopt/examples/example.rs +++ /dev/null @@ -1,54 +0,0 @@ -//! 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 deleted file mode 100644 index d51647f..0000000 --- a/structopt/examples/flatten.rs +++ /dev/null @@ -1,29 +0,0 @@ -//! 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 deleted file mode 100644 index 4f35b07..0000000 --- a/structopt/examples/gen_completions.rs +++ /dev/null @@ -1,26 +0,0 @@ -// 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 deleted file mode 100644 index 494e9d1..0000000 --- a/structopt/examples/git.rs +++ /dev/null @@ -1,35 +0,0 @@ -//! `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 deleted file mode 100644 index d53de6a..0000000 --- a/structopt/examples/group.rs +++ /dev/null @@ -1,31 +0,0 @@ -//! 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 deleted file mode 100644 index 12ce6fc..0000000 --- a/structopt/examples/keyvalue.rs +++ /dev/null @@ -1,36 +0,0 @@ -//! 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 deleted file mode 100644 index b178bf5..0000000 --- a/structopt/examples/negative_flag.rs +++ /dev/null @@ -1,15 +0,0 @@ -//! 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 deleted file mode 100644 index a542ec1..0000000 --- a/structopt/examples/no_version.rs +++ /dev/null @@ -1,17 +0,0 @@ -//! 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 deleted file mode 100644 index 35f3c4f..0000000 --- a/structopt/examples/rename_all.rs +++ /dev/null @@ -1,74 +0,0 @@ -//! 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 deleted file mode 100644 index 1f44769..0000000 --- a/structopt/examples/skip.rs +++ /dev/null @@ -1,47 +0,0 @@ -//! 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 deleted file mode 100644 index 30b8cc3..0000000 --- a/structopt/examples/subcommand_aliases.rs +++ /dev/null @@ -1,21 +0,0 @@ -//! 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 deleted file mode 100644 index 31a543e..0000000 --- a/structopt/examples/true_or_false.rs +++ /dev/null @@ -1,41 +0,0 @@ -//! 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()); -} diff --git a/structopt/link-check-headers.json b/structopt/link-check-headers.json deleted file mode 100644 index c1bb248..0000000 --- a/structopt/link-check-headers.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "httpHeaders": [ - { - "urls": [ - "https://", - "http://" - ], - "headers": { - "User-Agent": "broken links checker (https://github.com/TeXitoi/structopt)", - "Accept": "text/html" - } - } - ] -} 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) - } -} diff --git a/structopt/structopt-derive/Cargo.toml b/structopt/structopt-derive/Cargo.toml deleted file mode 100644 index ad547af..0000000 --- a/structopt/structopt-derive/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -name = "structopt-derive" -version = "0.4.0" -edition = "2018" -authors = ["Guillaume Pinot <texitoi@texitoi.eu>"] -description = "Parse command line argument by defining a struct, derive crate." -documentation = "https://docs.rs/structopt-derive" -repository = "https://github.com/TeXitoi/structopt" -keywords = ["clap", "cli", "derive", "docopt"] -categories = ["command-line-interface"] -license = "Apache-2.0/MIT" - -[badges] -travis-ci = { repository = "TeXitoi/structopt" } - -[dependencies] -syn = { version = "1", features = ["full"] } -quote = "1" -proc-macro2 = "1" -heck = "0.3.0" -proc-macro-error = "0.4.3" - -[features] -paw = [] - -[lib] -proc-macro = true diff --git a/structopt/structopt-derive/LICENSE-APACHE b/structopt/structopt-derive/LICENSE-APACHE deleted file mode 100644 index 261eeb9..0000000 --- a/structopt/structopt-derive/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/structopt/structopt-derive/LICENSE-MIT b/structopt/structopt-derive/LICENSE-MIT deleted file mode 100644 index e931b83..0000000 --- a/structopt/structopt-derive/LICENSE-MIT +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu> - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/structopt/structopt-derive/src/attrs.rs b/structopt/structopt-derive/src/attrs.rs deleted file mode 100644 index ce684a2..0000000 --- a/structopt/structopt-derive/src/attrs.rs +++ /dev/null @@ -1,620 +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. - -use crate::doc_comments::process_doc_comment; -use crate::{parse::*, spanned::Sp, ty::Ty}; - -use std::env; - -use heck::{CamelCase, KebabCase, MixedCase, ShoutySnakeCase, SnakeCase}; -use proc_macro2::{Span, TokenStream}; -use proc_macro_error::abort; -use quote::{quote, quote_spanned, ToTokens}; -use syn::{self, ext::IdentExt, spanned::Spanned, Attribute, Expr, Ident, LitStr, MetaNameValue}; - -#[derive(Clone)] -pub enum Kind { - Arg(Sp<Ty>), - Subcommand(Sp<Ty>), - FlattenStruct, - Skip(Option<Expr>), -} - -#[derive(Clone)] -pub struct Method { - name: Ident, - args: TokenStream, -} - -#[derive(Clone)] -pub struct Parser { - pub kind: Sp<ParserKind>, - pub func: TokenStream, -} - -#[derive(Debug, PartialEq, Clone)] -pub enum ParserKind { - FromStr, - TryFromStr, - FromOsStr, - TryFromOsStr, - FromOccurrences, - FromFlag, -} - -/// Defines the casing for the attributes long representation. -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum CasingStyle { - /// Indicate word boundaries with uppercase letter, excluding the first word. - Camel, - /// Keep all letters lowercase and indicate word boundaries with hyphens. - Kebab, - /// Indicate word boundaries with uppercase letter, including the first word. - Pascal, - /// Keep all letters uppercase and indicate word boundaries with underscores. - ScreamingSnake, - /// Keep all letters lowercase and indicate word boundaries with underscores. - Snake, - /// Use the original attribute name defined in the code. - Verbatim, -} - -#[derive(Clone)] -pub enum Name { - Derived(Ident), - Assigned(LitStr), -} - -#[derive(Clone)] -pub struct Attrs { - name: Name, - casing: Sp<CasingStyle>, - env_casing: Sp<CasingStyle>, - doc_comment: Vec<Method>, - methods: Vec<Method>, - parser: Sp<Parser>, - author: Option<Method>, - about: Option<Method>, - version: Option<Method>, - no_version: Option<Ident>, - verbatim_doc_comment: Option<Ident>, - has_custom_parser: bool, - kind: Sp<Kind>, -} - -impl Method { - pub fn new(name: Ident, args: TokenStream) -> Self { - Method { name, args } - } - - fn from_lit_or_env(ident: Ident, lit: Option<LitStr>, env_var: &str) -> Option<Self> { - let mut lit = match lit { - Some(lit) => lit, - - None => match env::var(env_var) { - Ok(val) => LitStr::new(&val, ident.span()), - Err(_) => { - abort!(ident.span(), - "cannot derive `{}` from Cargo.toml", ident; - note = "`{}` environment variable is not set", env_var; - help = "use `{} = \"...\"` to set {} manually", ident, ident; - ); - } - }, - }; - - if ident == "author" { - let edited = process_author_str(&lit.value()); - lit = LitStr::new(&edited, lit.span()); - } - - Some(Method::new(ident, quote!(#lit))) - } -} - -impl ToTokens for Method { - fn to_tokens(&self, ts: &mut TokenStream) { - let Method { ref name, ref args } = self; - quote!(.#name(#args)).to_tokens(ts); - } -} - -impl Parser { - fn default_spanned(span: Span) -> Sp<Self> { - let kind = Sp::new(ParserKind::TryFromStr, span); - let func = quote_spanned!(span=> ::std::str::FromStr::from_str); - Sp::new(Parser { kind, func }, span) - } - - fn from_spec(parse_ident: Ident, spec: ParserSpec) -> Sp<Self> { - use ParserKind::*; - - let kind = match &*spec.kind.to_string() { - "from_str" => FromStr, - "try_from_str" => TryFromStr, - "from_os_str" => FromOsStr, - "try_from_os_str" => TryFromOsStr, - "from_occurrences" => FromOccurrences, - "from_flag" => FromFlag, - s => abort!(spec.kind.span(), "unsupported parser `{}`", s), - }; - - let func = match spec.parse_func { - None => match kind { - FromStr | FromOsStr => { - quote_spanned!(spec.kind.span()=> ::std::convert::From::from) - } - TryFromStr => quote_spanned!(spec.kind.span()=> ::std::str::FromStr::from_str), - TryFromOsStr => abort!( - spec.kind.span(), - "you must set parser for `try_from_os_str` explicitly" - ), - FromOccurrences => quote_spanned!(spec.kind.span()=> { |v| v as _ }), - FromFlag => quote_spanned!(spec.kind.span()=> ::std::convert::From::from), - }, - - Some(func) => match func { - syn::Expr::Path(_) => quote!(#func), - _ => abort!(func.span(), "`parse` argument must be a function path"), - }, - }; - - let kind = Sp::new(kind, spec.kind.span()); - let parser = Parser { kind, func }; - Sp::new(parser, parse_ident.span()) - } -} - -impl CasingStyle { - fn from_lit(name: LitStr) -> Sp<Self> { - use CasingStyle::*; - - let normalized = name.value().to_camel_case().to_lowercase(); - let cs = |kind| Sp::new(kind, name.span()); - - match normalized.as_ref() { - "camel" | "camelcase" => cs(Camel), - "kebab" | "kebabcase" => cs(Kebab), - "pascal" | "pascalcase" => cs(Pascal), - "screamingsnake" | "screamingsnakecase" => cs(ScreamingSnake), - "snake" | "snakecase" => cs(Snake), - "verbatim" | "verbatimcase" => cs(Verbatim), - s => abort!(name.span(), "unsupported casing: `{}`", s), - } - } -} - -impl Name { - pub fn translate(self, style: CasingStyle) -> LitStr { - use CasingStyle::*; - - match self { - Name::Assigned(lit) => lit, - Name::Derived(ident) => { - let s = ident.unraw().to_string(); - let s = match style { - Pascal => s.to_camel_case(), - Kebab => s.to_kebab_case(), - Camel => s.to_mixed_case(), - ScreamingSnake => s.to_shouty_snake_case(), - Snake => s.to_snake_case(), - Verbatim => s, - }; - LitStr::new(&s, ident.span()) - } - } - } -} - -impl Attrs { - fn new( - default_span: Span, - name: Name, - casing: Sp<CasingStyle>, - env_casing: Sp<CasingStyle>, - ) -> Self { - Self { - name, - casing, - env_casing, - doc_comment: vec![], - methods: vec![], - parser: Parser::default_spanned(default_span), - about: None, - author: None, - version: None, - no_version: None, - verbatim_doc_comment: None, - - has_custom_parser: false, - kind: Sp::new(Kind::Arg(Sp::new(Ty::Other, default_span)), default_span), - } - } - - /// push `.method("str literal")` - fn push_str_method(&mut self, name: Sp<String>, arg: Sp<String>) { - if *name == "name" { - self.name = Name::Assigned(arg.as_lit()); - } else { - self.methods - .push(Method::new(name.as_ident(), quote!(#arg))) - } - } - - fn push_attrs(&mut self, attrs: &[Attribute]) { - use crate::parse::StructOptAttr::*; - - for attr in parse_structopt_attributes(attrs) { - match attr { - Short(ident) | Long(ident) => { - self.push_str_method( - ident.into(), - self.name.clone().translate(*self.casing).into(), - ); - } - - Env(ident) => { - self.push_str_method( - ident.into(), - self.name.clone().translate(*self.env_casing).into(), - ); - } - - Subcommand(ident) => { - let ty = Sp::call_site(Ty::Other); - let kind = Sp::new(Kind::Subcommand(ty), ident.span()); - self.set_kind(kind); - } - - Flatten(ident) => { - let kind = Sp::new(Kind::FlattenStruct, ident.span()); - self.set_kind(kind); - } - - Skip(ident, expr) => { - let kind = Sp::new(Kind::Skip(expr), ident.span()); - self.set_kind(kind); - } - - NoVersion(ident) => self.no_version = Some(ident), - - VerbatimDocComment(ident) => self.verbatim_doc_comment = Some(ident), - - About(ident, about) => { - self.about = Method::from_lit_or_env(ident, about, "CARGO_PKG_DESCRIPTION"); - } - - Author(ident, author) => { - self.author = Method::from_lit_or_env(ident, author, "CARGO_PKG_AUTHORS"); - } - - Version(ident, version) => { - self.version = Some(Method::new(ident, quote!(#version))) - } - - NameLitStr(name, lit) => { - self.push_str_method(name.into(), lit.into()); - } - - NameExpr(name, expr) => self.methods.push(Method::new(name, quote!(#expr))), - - MethodCall(name, args) => self.methods.push(Method::new(name, quote!(#(#args),*))), - - RenameAll(_, casing_lit) => { - self.casing = CasingStyle::from_lit(casing_lit); - } - - RenameAllEnv(_, casing_lit) => { - self.env_casing = CasingStyle::from_lit(casing_lit); - } - - Parse(ident, spec) => { - self.has_custom_parser = true; - self.parser = Parser::from_spec(ident, spec); - } - } - } - } - - fn push_doc_comment(&mut self, attrs: &[Attribute], name: &str) { - use crate::Lit::*; - use crate::Meta::*; - - let comment_parts: Vec<_> = attrs - .iter() - .filter(|attr| attr.path.is_ident("doc")) - .filter_map(|attr| { - if let Ok(NameValue(MetaNameValue { lit: Str(s), .. })) = attr.parse_meta() { - Some(s.value()) - } else { - // non #[doc = "..."] attributes are not our concern - // we leave them for rustc to handle - None - } - }) - .collect(); - - self.doc_comment = - process_doc_comment(comment_parts, name, self.verbatim_doc_comment.is_none()); - } - - pub fn from_struct( - span: Span, - attrs: &[Attribute], - name: Name, - argument_casing: Sp<CasingStyle>, - env_casing: Sp<CasingStyle>, - ) -> Self { - let mut res = Self::new(span, name, argument_casing, env_casing); - res.push_attrs(attrs); - res.push_doc_comment(attrs, "about"); - - if res.has_custom_parser { - abort!( - res.parser.span(), - "`parse` attribute is only allowed on fields" - ); - } - match &*res.kind { - Kind::Subcommand(_) => abort!(res.kind.span(), "subcommand is only allowed on fields"), - Kind::FlattenStruct => abort!(res.kind.span(), "flatten is only allowed on fields"), - Kind::Skip(_) => abort!(res.kind.span(), "skip is only allowed on fields"), - Kind::Arg(_) => res, - } - } - - pub fn from_field( - field: &syn::Field, - struct_casing: Sp<CasingStyle>, - env_casing: Sp<CasingStyle>, - ) -> Self { - let name = field.ident.clone().unwrap(); - let mut res = Self::new( - field.span(), - Name::Derived(name.clone()), - struct_casing, - env_casing, - ); - res.push_doc_comment(&field.attrs, "help"); - res.push_attrs(&field.attrs); - - match &*res.kind { - Kind::FlattenStruct => { - if res.has_custom_parser { - abort!( - res.parser.span(), - "parse attribute is not allowed for flattened entry" - ); - } - if res.has_explicit_methods() || res.has_doc_methods() { - abort!( - res.kind.span(), - "methods and doc comments are not allowed for flattened entry" - ); - } - } - Kind::Subcommand(_) => { - if res.has_custom_parser { - abort!( - res.parser.span(), - "parse attribute is not allowed for subcommand" - ); - } - if res.has_explicit_methods() { - abort!( - res.kind.span(), - "methods in attributes are not allowed for subcommand" - ); - } - - let ty = Ty::from_syn_ty(&field.ty); - match *ty { - Ty::OptionOption => { - abort!( - ty.span(), - "Option<Option<T>> type is not allowed for subcommand" - ); - } - Ty::OptionVec => { - abort!( - ty.span(), - "Option<Vec<T>> type is not allowed for subcommand" - ); - } - _ => (), - } - - res.kind = Sp::new(Kind::Subcommand(ty), res.kind.span()); - } - Kind::Skip(_) => { - if res.has_explicit_methods() { - abort!( - res.kind.span(), - "methods are not allowed for skipped fields" - ); - } - } - Kind::Arg(orig_ty) => { - let mut ty = Ty::from_syn_ty(&field.ty); - if res.has_custom_parser { - match *ty { - Ty::Option | Ty::Vec | Ty::OptionVec => (), - _ => ty = Sp::new(Ty::Other, ty.span()), - } - } - - match *ty { - Ty::Bool => { - if res.is_positional() && !res.has_custom_parser { - abort!(ty.span(), - "`bool` cannot be used as positional parameter with default parser"; - help = "if you want to create a flag add `long` or `short`"; - help = "If you really want a boolean parameter \ - add an explicit parser, for example `parse(try_from_str)`"; - note = "see also https://github.com/TeXitoi/structopt/tree/master/examples/true_or_false.rs"; - ) - } - if let Some(m) = res.find_method("default_value") { - abort!(m.name.span(), "default_value is meaningless for bool") - } - if let Some(m) = res.find_method("required") { - abort!(m.name.span(), "required is meaningless for bool") - } - } - Ty::Option => { - if let Some(m) = res.find_method("default_value") { - abort!(m.name.span(), "default_value is meaningless for Option") - } - if let Some(m) = res.find_method("required") { - abort!(m.name.span(), "required is meaningless for Option") - } - } - Ty::OptionOption => { - if res.is_positional() { - abort!( - ty.span(), - "Option<Option<T>> type is meaningless for positional argument" - ) - } - } - Ty::OptionVec => { - if res.is_positional() { - abort!( - ty.span(), - "Option<Vec<T>> type is meaningless for positional argument" - ) - } - } - - _ => (), - } - res.kind = Sp::new(Kind::Arg(ty), orig_ty.span()); - } - } - - res - } - - fn set_kind(&mut self, kind: Sp<Kind>) { - if let Kind::Arg(_) = *self.kind { - self.kind = kind; - } else { - abort!( - kind.span(), - "subcommand, flatten and skip cannot be used together" - ); - } - } - - pub fn has_method(&self, name: &str) -> bool { - self.find_method(name).is_some() - } - - pub fn find_method(&self, name: &str) -> Option<&Method> { - self.methods.iter().find(|m| m.name == name) - } - - /// generate methods from attributes on top of struct or enum - pub fn top_level_methods(&self) -> TokenStream { - let version = match (&self.no_version, &self.version) { - (Some(no_version), Some(_)) => abort!( - no_version.span(), - "`no_version` and `version = \"version\"` can't be used together" - ), - - (None, Some(m)) => m.to_token_stream(), - - (None, None) => std::env::var("CARGO_PKG_VERSION") - .map(|version| quote!( .version(#version) )) - .unwrap_or_default(), - - (Some(_), None) => quote!(), - }; - - let author = &self.author; - let about = &self.about; - let methods = &self.methods; - let doc_comment = &self.doc_comment; - - quote!( #(#doc_comment)* #author #version #about #(#methods)* ) - } - - /// generate methods on top of a field - pub fn field_methods(&self) -> TokenStream { - let methods = &self.methods; - let doc_comment = &self.doc_comment; - quote!( #(#doc_comment)* #(#methods)* ) - } - - pub fn cased_name(&self) -> LitStr { - self.name.clone().translate(*self.casing) - } - - pub fn parser(&self) -> &Sp<Parser> { - &self.parser - } - - pub fn kind(&self) -> Sp<Kind> { - self.kind.clone() - } - - pub fn casing(&self) -> Sp<CasingStyle> { - self.casing.clone() - } - - pub fn env_casing(&self) -> Sp<CasingStyle> { - self.env_casing.clone() - } - - pub fn is_positional(&self) -> bool { - self.methods - .iter() - .all(|m| m.name != "long" && m.name != "short") - } - - pub fn has_explicit_methods(&self) -> bool { - self.methods - .iter() - .any(|m| m.name != "help" && m.name != "long_help") - } - - pub fn has_doc_methods(&self) -> bool { - !self.doc_comment.is_empty() - || self.methods.iter().any(|m| { - m.name == "help" - || m.name == "long_help" - || m.name == "about" - || m.name == "long_about" - }) - } -} - -/// replace all `:` with `, ` when not inside the `<>` -/// -/// `"author1:author2:author3" => "author1, author2, author3"` -/// `"author1 <http://website1.com>:author2" => "author1 <http://website1.com>, author2" -fn process_author_str(author: &str) -> String { - let mut res = String::with_capacity(author.len()); - let mut inside_angle_braces = 0usize; - - for ch in author.chars() { - if inside_angle_braces > 0 && ch == '>' { - inside_angle_braces -= 1; - res.push(ch); - } else if ch == '<' { - inside_angle_braces += 1; - res.push(ch); - } else if inside_angle_braces == 0 && ch == ':' { - res.push_str(", "); - } else { - res.push(ch); - } - } - - res -} diff --git a/structopt/structopt-derive/src/doc_comments.rs b/structopt/structopt-derive/src/doc_comments.rs deleted file mode 100644 index 06e1b14..0000000 --- a/structopt/structopt-derive/src/doc_comments.rs +++ /dev/null @@ -1,103 +0,0 @@ -//! The preprocessing we apply to doc comments. -//! -//! structopt works in terms of "paragraphs". Paragraph is a sequence of -//! non-empty adjacent lines, delimited by sequences of blank (whitespace only) lines. - -use crate::attrs::Method; -use quote::{format_ident, quote}; -use std::iter; - -pub fn process_doc_comment(lines: Vec<String>, name: &str, preprocess: bool) -> Vec<Method> { - // multiline comments (`/** ... */`) may have LFs (`\n`) in them, - // we need to split so we could handle the lines correctly - // - // we also need to remove leading and trailing blank lines - let mut lines: Vec<&str> = lines - .iter() - .skip_while(|s| is_blank(s)) - .flat_map(|s| s.split('\n')) - .collect(); - - while let Some(true) = lines.last().map(|s| is_blank(s)) { - lines.pop(); - } - - // remove one leading space no matter what - for line in lines.iter_mut() { - if line.starts_with(' ') { - *line = &line[1..]; - } - } - - if lines.is_empty() { - return vec![]; - } - - let short_name = format_ident!("{}", name); - let long_name = format_ident!("long_{}", name); - - if let Some(first_blank) = lines.iter().position(|s| is_blank(s)) { - let (short, long) = if preprocess { - let paragraphs = split_paragraphs(&lines); - let short = paragraphs[0].clone(); - let long = paragraphs.join("\n\n"); - (remove_period(short), long) - } else { - let short = lines[..first_blank].join("\n"); - let long = lines.join("\n"); - (short, long) - }; - - vec![ - Method::new(short_name, quote!(#short)), - Method::new(long_name, quote!(#long)), - ] - } else { - let short = if preprocess { - let s = merge_lines(&lines); - remove_period(s) - } else { - lines.join("\n") - }; - - vec![Method::new(short_name, quote!(#short))] - } -} - -fn split_paragraphs(lines: &[&str]) -> Vec<String> { - let mut last_line = 0; - iter::from_fn(|| { - let slice = &lines[last_line..]; - let start = slice.iter().position(|s| !is_blank(s)).unwrap_or(0); - - let slice = &slice[start..]; - let len = slice - .iter() - .position(|s| is_blank(s)) - .unwrap_or(slice.len()); - - last_line += start + len; - - if len != 0 { - Some(merge_lines(&slice[..len])) - } else { - None - } - }) - .collect() -} - -fn remove_period(mut s: String) -> String { - if s.ends_with('.') && !s.ends_with("..") { - s.pop(); - } - s -} - -fn is_blank(s: &str) -> bool { - s.trim().is_empty() -} - -fn merge_lines(lines: &[&str]) -> String { - lines.iter().map(|s| s.trim()).collect::<Vec<_>>().join(" ") -} diff --git a/structopt/structopt-derive/src/lib.rs b/structopt/structopt-derive/src/lib.rs deleted file mode 100644 index 87eaf1f..0000000 --- a/structopt/structopt-derive/src/lib.rs +++ /dev/null @@ -1,667 +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. - -//! This crate is custom derive for `StructOpt`. It should not be used -//! directly. See [structopt documentation](https://docs.rs/structopt) -//! for the usage of `#[derive(StructOpt)]`. - -#![allow(clippy::large_enum_variant)] - -extern crate proc_macro; - -mod attrs; -mod doc_comments; -mod parse; -mod spanned; -mod ty; - -use crate::{ - attrs::{Attrs, CasingStyle, Kind, Name, ParserKind}, - spanned::Sp, - ty::{sub_type, Ty}, -}; - -use proc_macro2::{Span, TokenStream}; -use proc_macro_error::{abort, abort_call_site, proc_macro_error, set_dummy}; -use quote::{quote, quote_spanned}; -use syn::{punctuated::Punctuated, spanned::Spanned, token::Comma, *}; - -/// Default casing style for generated arguments. -const DEFAULT_CASING: CasingStyle = CasingStyle::Kebab; - -/// Default casing style for environment variables -const DEFAULT_ENV_CASING: CasingStyle = CasingStyle::ScreamingSnake; - -/// Output for the `gen_xxx()` methods were we need more than a simple stream of tokens. -/// -/// The output of a generation method is not only the stream of new tokens but also the attribute -/// information of the current element. These attribute information may contain valuable information -/// for any kind of child arguments. -struct GenOutput { - tokens: TokenStream, - attrs: Attrs, -} - -/// Generates the `StructOpt` impl. -#[proc_macro_derive(StructOpt, attributes(structopt))] -#[proc_macro_error] -pub fn structopt(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let input: DeriveInput = syn::parse(input).unwrap(); - let gen = impl_structopt(&input); - gen.into() -} - -/// Generate a block of code to add arguments/subcommands corresponding to -/// the `fields` to an app. -fn gen_augmentation( - fields: &Punctuated<Field, Comma>, - app_var: &Ident, - parent_attribute: &Attrs, -) -> TokenStream { - let mut subcmds = fields.iter().filter_map(|field| { - let attrs = Attrs::from_field( - field, - parent_attribute.casing(), - parent_attribute.env_casing(), - ); - let kind = attrs.kind(); - if let Kind::Subcommand(ty) = &*kind { - let subcmd_type = match (**ty, sub_type(&field.ty)) { - (Ty::Option, Some(sub_type)) => sub_type, - _ => &field.ty, - }; - let required = if **ty == Ty::Option { - quote!() - } else { - quote_spanned! { kind.span()=> - let #app_var = #app_var.setting( - ::structopt::clap::AppSettings::SubcommandRequiredElseHelp - ); - } - }; - - let span = field.span(); - let ts = quote! { - let #app_var = <#subcmd_type as ::structopt::StructOptInternal>::augment_clap( - #app_var - ); - #required - }; - Some((span, ts)) - } else { - None - } - }); - - let subcmd = subcmds.next().map(|(_, ts)| ts); - if let Some((span, _)) = subcmds.next() { - abort!( - span, - "multiple subcommand sets are not allowed, that's the second" - ); - } - - let args = fields.iter().filter_map(|field| { - let attrs = Attrs::from_field( - field, - parent_attribute.casing(), - parent_attribute.env_casing(), - ); - let kind = attrs.kind(); - match &*kind { - Kind::Subcommand(_) | Kind::Skip(_) => None, - Kind::FlattenStruct => { - let ty = &field.ty; - Some(quote_spanned! { kind.span()=> - let #app_var = <#ty as ::structopt::StructOptInternal>::augment_clap(#app_var); - let #app_var = if <#ty as ::structopt::StructOptInternal>::is_subcommand() { - #app_var.setting(::structopt::clap::AppSettings::SubcommandRequiredElseHelp) - } else { - #app_var - }; - }) - } - Kind::Arg(ty) => { - let convert_type = match **ty { - Ty::Vec | Ty::Option => sub_type(&field.ty).unwrap_or(&field.ty), - Ty::OptionOption | Ty::OptionVec => { - sub_type(&field.ty).and_then(sub_type).unwrap_or(&field.ty) - } - _ => &field.ty, - }; - - let occurrences = *attrs.parser().kind == ParserKind::FromOccurrences; - let flag = *attrs.parser().kind == ParserKind::FromFlag; - - let parser = attrs.parser(); - let func = &parser.func; - let validator = match *parser.kind { - ParserKind::TryFromStr => quote_spanned! { func.span()=> - .validator(|s| { - #func(s.as_str()) - .map(|_: #convert_type| ()) - .map_err(|e| e.to_string()) - }) - }, - ParserKind::TryFromOsStr => quote_spanned! { func.span()=> - .validator_os(|s| #func(&s).map(|_: #convert_type| ())) - }, - _ => quote!(), - }; - - let modifier = match **ty { - Ty::Bool => quote_spanned! { ty.span()=> - .takes_value(false) - .multiple(false) - }, - - Ty::Option => quote_spanned! { ty.span()=> - .takes_value(true) - .multiple(false) - #validator - }, - - Ty::OptionOption => quote_spanned! { ty.span()=> - .takes_value(true) - .multiple(false) - .min_values(0) - .max_values(1) - #validator - }, - - Ty::OptionVec => quote_spanned! { ty.span()=> - .takes_value(true) - .multiple(true) - .min_values(0) - #validator - }, - - Ty::Vec => quote_spanned! { ty.span()=> - .takes_value(true) - .multiple(true) - #validator - }, - - Ty::Other if occurrences => quote_spanned! { ty.span()=> - .takes_value(false) - .multiple(true) - }, - - Ty::Other if flag => quote_spanned! { ty.span()=> - .takes_value(false) - .multiple(false) - }, - - Ty::Other => { - let required = !attrs.has_method("default_value"); - quote_spanned! { ty.span()=> - .takes_value(true) - .multiple(false) - .required(#required) - #validator - } - } - }; - - let name = attrs.cased_name(); - let methods = attrs.field_methods(); - - Some(quote_spanned! { field.span()=> - let #app_var = #app_var.arg( - ::structopt::clap::Arg::with_name(#name) - #modifier - #methods - ); - }) - } - } - }); - - let app_methods = parent_attribute.top_level_methods(); - quote! {{ - let #app_var = #app_var#app_methods; - #( #args )* - #subcmd - #app_var - }} -} - -fn gen_constructor(fields: &Punctuated<Field, Comma>, parent_attribute: &Attrs) -> TokenStream { - let fields = fields.iter().map(|field| { - let attrs = Attrs::from_field( - field, - parent_attribute.casing(), - parent_attribute.env_casing(), - ); - let field_name = field.ident.as_ref().unwrap(); - let kind = attrs.kind(); - match &*kind { - Kind::Subcommand(ty) => { - let subcmd_type = match (**ty, sub_type(&field.ty)) { - (Ty::Option, Some(sub_type)) => sub_type, - _ => &field.ty, - }; - let unwrapper = match **ty { - Ty::Option => quote!(), - _ => quote_spanned!( ty.span()=> .unwrap() ), - }; - quote_spanned! { kind.span()=> - #field_name: <#subcmd_type as ::structopt::StructOptInternal>::from_subcommand( - matches.subcommand()) - #unwrapper - } - } - - Kind::FlattenStruct => quote_spanned! { kind.span()=> - #field_name: ::structopt::StructOpt::from_clap(matches) - }, - - Kind::Skip(val) => match val { - None => quote_spanned!(kind.span()=> #field_name: Default::default()), - Some(val) => quote_spanned!(kind.span()=> #field_name: (#val).into()), - }, - - Kind::Arg(ty) => { - use crate::attrs::ParserKind::*; - - let parser = attrs.parser(); - let func = &parser.func; - let span = parser.kind.span(); - let (value_of, values_of, parse) = match *parser.kind { - FromStr => ( - quote_spanned!(span=> value_of), - quote_spanned!(span=> values_of), - func.clone(), - ), - TryFromStr => ( - quote_spanned!(span=> value_of), - quote_spanned!(span=> values_of), - quote_spanned!(func.span()=> |s| #func(s).unwrap()), - ), - FromOsStr => ( - quote_spanned!(span=> value_of_os), - quote_spanned!(span=> values_of_os), - func.clone(), - ), - TryFromOsStr => ( - quote_spanned!(span=> value_of_os), - quote_spanned!(span=> values_of_os), - quote_spanned!(func.span()=> |s| #func(s).unwrap()), - ), - FromOccurrences => ( - quote_spanned!(span=> occurrences_of), - quote!(), - func.clone(), - ), - FromFlag => (quote!(), quote!(), func.clone()), - }; - - let flag = *attrs.parser().kind == ParserKind::FromFlag; - let occurrences = *attrs.parser().kind == ParserKind::FromOccurrences; - let name = attrs.cased_name(); - let field_value = match **ty { - Ty::Bool => quote_spanned!(ty.span()=> matches.is_present(#name)), - - Ty::Option => quote_spanned! { ty.span()=> - matches.#value_of(#name) - .map(#parse) - }, - - Ty::OptionOption => quote_spanned! { ty.span()=> - if matches.is_present(#name) { - Some(matches.#value_of(#name).map(#parse)) - } else { - None - } - }, - - Ty::OptionVec => quote_spanned! { ty.span()=> - if matches.is_present(#name) { - Some(matches.#values_of(#name) - .map_or_else(Vec::new, |v| v.map(#parse).collect())) - } else { - None - } - }, - - Ty::Vec => quote_spanned! { ty.span()=> - matches.#values_of(#name) - .map_or_else(Vec::new, |v| v.map(#parse).collect()) - }, - - Ty::Other if occurrences => quote_spanned! { ty.span()=> - #parse(matches.#value_of(#name)) - }, - - Ty::Other if flag => quote_spanned! { ty.span()=> - #parse(matches.is_present(#name)) - }, - - Ty::Other => quote_spanned! { ty.span()=> - matches.#value_of(#name) - .map(#parse) - .unwrap() - }, - }; - - quote_spanned!(field.span()=> #field_name: #field_value ) - } - } - }); - - quote! {{ - #( #fields ),* - }} -} - -fn gen_from_clap( - struct_name: &Ident, - fields: &Punctuated<Field, Comma>, - parent_attribute: &Attrs, -) -> TokenStream { - let field_block = gen_constructor(fields, parent_attribute); - - quote! { - fn from_clap(matches: &::structopt::clap::ArgMatches) -> Self { - #struct_name #field_block - } - } -} - -fn gen_clap(attrs: &[Attribute]) -> GenOutput { - let name = std::env::var("CARGO_PKG_NAME").ok().unwrap_or_default(); - - let attrs = Attrs::from_struct( - Span::call_site(), - attrs, - Name::Assigned(LitStr::new(&name, Span::call_site())), - Sp::call_site(DEFAULT_CASING), - Sp::call_site(DEFAULT_ENV_CASING), - ); - let tokens = { - let name = attrs.cased_name(); - quote!(::structopt::clap::App::new(#name)) - }; - - GenOutput { tokens, attrs } -} - -fn gen_clap_struct(struct_attrs: &[Attribute]) -> GenOutput { - let initial_clap_app_gen = gen_clap(struct_attrs); - let clap_tokens = initial_clap_app_gen.tokens; - - let augmented_tokens = quote! { - fn clap<'a, 'b>() -> ::structopt::clap::App<'a, 'b> { - let app = #clap_tokens; - <Self as ::structopt::StructOptInternal>::augment_clap(app) - } - }; - - GenOutput { - tokens: augmented_tokens, - attrs: initial_clap_app_gen.attrs, - } -} - -fn gen_augment_clap(fields: &Punctuated<Field, Comma>, parent_attribute: &Attrs) -> TokenStream { - let app_var = Ident::new("app", Span::call_site()); - let augmentation = gen_augmentation(fields, &app_var, parent_attribute); - quote! { - fn augment_clap<'a, 'b>( - #app_var: ::structopt::clap::App<'a, 'b> - ) -> ::structopt::clap::App<'a, 'b> { - #augmentation - } - } -} - -fn gen_clap_enum(enum_attrs: &[Attribute]) -> GenOutput { - let initial_clap_app_gen = gen_clap(enum_attrs); - let clap_tokens = initial_clap_app_gen.tokens; - - let tokens = quote! { - fn clap<'a, 'b>() -> ::structopt::clap::App<'a, 'b> { - let app = #clap_tokens - .setting(::structopt::clap::AppSettings::SubcommandRequiredElseHelp); - <Self as ::structopt::StructOptInternal>::augment_clap(app) - } - }; - - GenOutput { - tokens, - attrs: initial_clap_app_gen.attrs, - } -} - -fn gen_augment_clap_enum( - variants: &Punctuated<Variant, Comma>, - parent_attribute: &Attrs, -) -> TokenStream { - use syn::Fields::*; - - let subcommands = variants.iter().map(|variant| { - let attrs = Attrs::from_struct( - variant.span(), - &variant.attrs, - Name::Derived(variant.ident.clone()), - parent_attribute.casing(), - parent_attribute.env_casing(), - ); - let app_var = Ident::new("subcommand", Span::call_site()); - let arg_block = match variant.fields { - Named(ref fields) => gen_augmentation(&fields.named, &app_var, &attrs), - Unit => quote!( #app_var ), - Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => { - let ty = &unnamed[0]; - quote_spanned! { ty.span()=> - { - let #app_var = <#ty as ::structopt::StructOptInternal>::augment_clap( - #app_var - ); - if <#ty as ::structopt::StructOptInternal>::is_subcommand() { - #app_var.setting( - ::structopt::clap::AppSettings::SubcommandRequiredElseHelp - ) - } else { - #app_var - } - } - } - } - Unnamed(..) => abort_call_site!("{}: tuple enums are not supported", variant.ident), - }; - - let name = attrs.cased_name(); - let from_attrs = attrs.top_level_methods(); - - quote! { - .subcommand({ - let #app_var = ::structopt::clap::SubCommand::with_name(#name); - let #app_var = #arg_block; - #app_var#from_attrs - }) - } - }); - - let app_methods = parent_attribute.top_level_methods(); - - quote! { - fn augment_clap<'a, 'b>( - app: ::structopt::clap::App<'a, 'b> - ) -> ::structopt::clap::App<'a, 'b> { - app #app_methods #( #subcommands )* - } - } -} - -fn gen_from_clap_enum(name: &Ident) -> TokenStream { - quote! { - fn from_clap(matches: &::structopt::clap::ArgMatches) -> Self { - <#name as ::structopt::StructOptInternal>::from_subcommand(matches.subcommand()) - .unwrap() - } - } -} - -fn gen_from_subcommand( - name: &Ident, - variants: &Punctuated<Variant, Comma>, - parent_attribute: &Attrs, -) -> TokenStream { - use syn::Fields::*; - - let match_arms = variants.iter().map(|variant| { - let attrs = Attrs::from_struct( - variant.span(), - &variant.attrs, - Name::Derived(variant.ident.clone()), - parent_attribute.casing(), - parent_attribute.env_casing(), - ); - let sub_name = attrs.cased_name(); - let variant_name = &variant.ident; - let constructor_block = match variant.fields { - Named(ref fields) => gen_constructor(&fields.named, &attrs), - Unit => quote!(), - Unnamed(ref fields) if fields.unnamed.len() == 1 => { - let ty = &fields.unnamed[0]; - quote!( ( <#ty as ::structopt::StructOpt>::from_clap(matches) ) ) - } - Unnamed(..) => abort_call_site!("{}: tuple enums are not supported", variant.ident), - }; - - quote! { - (#sub_name, Some(matches)) => - Some(#name :: #variant_name #constructor_block) - } - }); - - quote! { - fn from_subcommand<'a, 'b>( - sub: (&'b str, Option<&'b ::structopt::clap::ArgMatches<'a>>) - ) -> Option<Self> { - match sub { - #( #match_arms ),*, - _ => None - } - } - } -} - -#[cfg(feature = "paw")] -fn gen_paw_impl(name: &Ident) -> TokenStream { - quote! { - impl paw::ParseArgs for #name { - type Error = std::io::Error; - - fn parse_args() -> std::result::Result<Self, Self::Error> { - Ok(<#name as ::structopt::StructOpt>::from_args()) - } - } - } -} -#[cfg(not(feature = "paw"))] -fn gen_paw_impl(_: &Ident) -> TokenStream { - TokenStream::new() -} - -fn impl_structopt_for_struct( - name: &Ident, - fields: &Punctuated<Field, Comma>, - attrs: &[Attribute], -) -> TokenStream { - let basic_clap_app_gen = gen_clap_struct(attrs); - let augment_clap = gen_augment_clap(fields, &basic_clap_app_gen.attrs); - let from_clap = gen_from_clap(name, fields, &basic_clap_app_gen.attrs); - let paw_impl = gen_paw_impl(name); - - let clap_tokens = basic_clap_app_gen.tokens; - quote! { - #[allow(unused_variables)] - #[allow(unknown_lints)] - #[allow(clippy::all)] - #[allow(dead_code, unreachable_code)] - impl ::structopt::StructOpt for #name { - #clap_tokens - #from_clap - } - - #[allow(unused_variables)] - #[allow(unknown_lints)] - #[allow(clippy::all)] - #[allow(dead_code, unreachable_code)] - impl ::structopt::StructOptInternal for #name { - #augment_clap - fn is_subcommand() -> bool { false } - } - - #paw_impl - } -} - -fn impl_structopt_for_enum( - name: &Ident, - variants: &Punctuated<Variant, Comma>, - attrs: &[Attribute], -) -> TokenStream { - let basic_clap_app_gen = gen_clap_enum(attrs); - - let augment_clap = gen_augment_clap_enum(variants, &basic_clap_app_gen.attrs); - let from_clap = gen_from_clap_enum(name); - let from_subcommand = gen_from_subcommand(name, variants, &basic_clap_app_gen.attrs); - let paw_impl = gen_paw_impl(name); - - let clap_tokens = basic_clap_app_gen.tokens; - quote! { - #[allow(unknown_lints)] - #[allow(unused_variables, dead_code, unreachable_code)] - #[allow(clippy)] - impl ::structopt::StructOpt for #name { - #clap_tokens - #from_clap - } - - #[allow(unused_variables)] - #[allow(unknown_lints)] - #[allow(clippy::all)] - #[allow(dead_code, unreachable_code)] - impl ::structopt::StructOptInternal for #name { - #augment_clap - #from_subcommand - fn is_subcommand() -> bool { true } - } - - #paw_impl - } -} - -fn impl_structopt(input: &DeriveInput) -> TokenStream { - use syn::Data::*; - - let struct_name = &input.ident; - - set_dummy(quote! { - impl ::structopt::StructOpt for #struct_name { - fn clap<'a, 'b>() -> ::structopt::clap::App<'a, 'b> { - unimplemented!() - } - fn from_clap(_matches: &::structopt::clap::ArgMatches) -> Self { - unimplemented!() - } - } - }); - - match input.data { - Struct(DataStruct { - fields: syn::Fields::Named(ref fields), - .. - }) => impl_structopt_for_struct(struct_name, &fields.named, &input.attrs), - Enum(ref e) => impl_structopt_for_enum(struct_name, &e.variants, &input.attrs), - _ => abort_call_site!("structopt only supports non-tuple structs and enums"), - } -} diff --git a/structopt/structopt-derive/src/parse.rs b/structopt/structopt-derive/src/parse.rs deleted file mode 100644 index a704742..0000000 --- a/structopt/structopt-derive/src/parse.rs +++ /dev/null @@ -1,304 +0,0 @@ -use std::iter::FromIterator; - -use proc_macro_error::{abort, ResultExt}; -use quote::ToTokens; -use syn::{ - self, parenthesized, - parse::{Parse, ParseBuffer, ParseStream}, - parse2, - punctuated::Punctuated, - spanned::Spanned, - Attribute, Expr, ExprLit, Ident, Lit, LitBool, LitStr, Token, -}; - -pub struct StructOptAttributes { - pub paren_token: syn::token::Paren, - pub attrs: Punctuated<StructOptAttr, Token![,]>, -} - -impl Parse for StructOptAttributes { - fn parse(input: ParseStream<'_>) -> syn::Result<Self> { - let content; - let paren_token = parenthesized!(content in input); - let attrs = content.parse_terminated(StructOptAttr::parse)?; - - Ok(StructOptAttributes { paren_token, attrs }) - } -} - -pub enum StructOptAttr { - // single-identifier attributes - Short(Ident), - Long(Ident), - Env(Ident), - Flatten(Ident), - Subcommand(Ident), - NoVersion(Ident), - VerbatimDocComment(Ident), - - // ident [= "string literal"] - About(Ident, Option<LitStr>), - Author(Ident, Option<LitStr>), - - // ident = "string literal" - Version(Ident, LitStr), - RenameAllEnv(Ident, LitStr), - RenameAll(Ident, LitStr), - NameLitStr(Ident, LitStr), - - // parse(parser_kind [= parser_func]) - Parse(Ident, ParserSpec), - - // ident [= arbitrary_expr] - Skip(Ident, Option<Expr>), - - // ident = arbitrary_expr - NameExpr(Ident, Expr), - - // ident(arbitrary_expr,*) - MethodCall(Ident, Vec<Expr>), -} - -impl Parse for StructOptAttr { - fn parse(input: ParseStream<'_>) -> syn::Result<Self> { - use self::StructOptAttr::*; - - let name: Ident = input.parse()?; - let name_str = name.to_string(); - - if input.peek(Token![=]) { - // `name = value` attributes. - let assign_token = input.parse::<Token![=]>()?; // skip '=' - - if input.peek(LitStr) { - let lit: LitStr = input.parse()?; - let lit_str = lit.value(); - - let check_empty_lit = |s| { - if lit_str.is_empty() { - abort!( - lit.span(), - "`#[structopt({} = \"\")]` is deprecated in structopt 0.3, \ - now it's default behavior", - s - ); - } - }; - - match &*name_str.to_string() { - "rename_all" => Ok(RenameAll(name, lit)), - "rename_all_env" => Ok(RenameAllEnv(name, lit)), - - "version" => { - check_empty_lit("version"); - Ok(Version(name, lit)) - } - - "author" => { - check_empty_lit("author"); - Ok(Author(name, Some(lit))) - } - - "about" => { - check_empty_lit("about"); - Ok(About(name, Some(lit))) - } - - "skip" => { - let expr = ExprLit { - attrs: vec![], - lit: Lit::Str(lit), - }; - let expr = Expr::Lit(expr); - Ok(Skip(name, Some(expr))) - } - - _ => Ok(NameLitStr(name, lit)), - } - } else { - match input.parse::<Expr>() { - Ok(expr) => { - if name_str == "skip" { - Ok(Skip(name, Some(expr))) - } else { - Ok(NameExpr(name, expr)) - } - } - - Err(_) => abort! { - assign_token.span(), - "expected `string literal` or `expression` after `=`" - }, - } - } - } else if input.peek(syn::token::Paren) { - // `name(...)` attributes. - let nested; - parenthesized!(nested in input); - - match name_str.as_ref() { - "parse" => { - let parser_specs: Punctuated<ParserSpec, Token![,]> = - nested.parse_terminated(ParserSpec::parse)?; - - if parser_specs.len() == 1 { - Ok(Parse(name, parser_specs[0].clone())) - } else { - abort!(name.span(), "parse must have exactly one argument") - } - } - - "raw" => match nested.parse::<LitBool>() { - Ok(bool_token) => { - let expr = ExprLit { - attrs: vec![], - lit: Lit::Bool(bool_token), - }; - let expr = Expr::Lit(expr); - Ok(MethodCall(name, vec![expr])) - } - - Err(_) => { - abort!(name.span(), - "`#[structopt(raw(...))` attributes are removed in structopt 0.3, \ - they are replaced with raw methods"; - help = "if you meant to call `clap::Arg::raw()` method \ - you should use bool literal, like `raw(true)` or `raw(false)`"; - note = raw_method_suggestion(nested); - ); - } - }, - - _ => { - let method_args: Punctuated<_, Token![,]> = - nested.parse_terminated(Expr::parse)?; - Ok(MethodCall(name, Vec::from_iter(method_args))) - } - } - } else { - // Attributes represented with a sole identifier. - match name_str.as_ref() { - "long" => Ok(Long(name)), - "short" => Ok(Short(name)), - "env" => Ok(Env(name)), - "flatten" => Ok(Flatten(name)), - "subcommand" => Ok(Subcommand(name)), - "no_version" => Ok(NoVersion(name)), - "verbatim_doc_comment" => Ok(VerbatimDocComment(name)), - - "about" => (Ok(About(name, None))), - "author" => (Ok(Author(name, None))), - - "skip" => Ok(Skip(name, None)), - - "version" => abort!( - name.span(), - "#[structopt(version)] is invalid attribute, \ - structopt 0.3 inherits version from Cargo.toml by default, \ - no attribute needed" - ), - - _ => abort!(name.span(), "unexpected attribute: {}", name_str), - } - } - } -} - -#[derive(Clone)] -pub struct ParserSpec { - pub kind: Ident, - pub eq_token: Option<Token![=]>, - pub parse_func: Option<Expr>, -} - -impl Parse for ParserSpec { - fn parse(input: ParseStream<'_>) -> syn::Result<Self> { - let kind = input - .parse() - .map_err(|_| input.error("parser specification must start with identifier"))?; - let eq_token = input.parse()?; - let parse_func = match eq_token { - None => None, - Some(_) => Some(input.parse()?), - }; - Ok(ParserSpec { - kind, - eq_token, - parse_func, - }) - } -} - -struct CommaSeparated<T>(Punctuated<T, Token![,]>); - -impl<T: Parse> Parse for CommaSeparated<T> { - fn parse(input: ParseStream<'_>) -> syn::Result<Self> { - let res = Punctuated::parse_separated_nonempty(input)?; - Ok(CommaSeparated(res)) - } -} - -fn raw_method_suggestion(ts: ParseBuffer) -> String { - let do_parse = move || -> Result<(Ident, CommaSeparated<Expr>), syn::Error> { - let name = ts.parse()?; - let _eq: Token![=] = ts.parse()?; - let val: LitStr = ts.parse()?; - Ok((name, syn::parse_str(&val.value())?)) - }; - - fn to_string<T: ToTokens>(val: &T) -> String { - val.to_token_stream() - .to_string() - .replace(" ", "") - .replace(",", ", ") - } - - if let Ok((name, val)) = do_parse() { - let exprs = val.0; - let suggestion = if exprs.len() == 1 { - let val = to_string(&exprs[0]); - format!(" = {}", val) - } else { - let val = exprs - .into_iter() - .map(|expr| to_string(&expr)) - .collect::<Vec<_>>() - .join(", "); - - format!("({})", val) - }; - - format!( - "if you need to call `clap::Arg/App::{}` method you \ - can do it like this: #[structopt({}{})]", - name, name, suggestion - ) - } else { - "if you need to call some method from `clap::Arg/App` \ - you should use raw method, see \ - https://docs.rs/structopt/0.3/structopt/#raw-methods" - .into() - } -} - -pub fn parse_structopt_attributes(all_attrs: &[Attribute]) -> Vec<StructOptAttr> { - all_attrs - .iter() - .filter(|attr| attr.path.is_ident("structopt")) - .flat_map(|attr| { - let attrs: StructOptAttributes = parse2(attr.tokens.clone()) - .map_err(|e| match &*e.to_string() { - // this error message is misleading and points to Span::call_site() - // so we patch it with something meaningful - "unexpected end of input, expected parentheses" => { - let span = attr.path.span(); - let patch_msg = "expected parentheses after `structopt`"; - syn::Error::new(span, patch_msg) - } - _ => e, - }) - .unwrap_or_abort(); - attrs.attrs - }) - .collect() -} diff --git a/structopt/structopt-derive/src/spanned.rs b/structopt/structopt-derive/src/spanned.rs deleted file mode 100644 index 2dd595b..0000000 --- a/structopt/structopt-derive/src/spanned.rs +++ /dev/null @@ -1,101 +0,0 @@ -use proc_macro2::{Ident, Span, TokenStream}; -use quote::ToTokens; -use std::ops::{Deref, DerefMut}; -use syn::LitStr; - -/// An entity with a span attached. -#[derive(Debug, Clone)] -pub struct Sp<T> { - span: Span, - val: T, -} - -impl<T> Sp<T> { - pub fn new(val: T, span: Span) -> Self { - Sp { val, span } - } - - pub fn call_site(val: T) -> Self { - Sp { - val, - span: Span::call_site(), - } - } - - pub fn span(&self) -> Span { - self.span - } -} - -impl<T: ToString> Sp<T> { - pub fn as_ident(&self) -> Ident { - Ident::new(&self.to_string(), self.span) - } - - pub fn as_lit(&self) -> LitStr { - LitStr::new(&self.to_string(), self.span) - } -} - -impl<T> Deref for Sp<T> { - type Target = T; - - fn deref(&self) -> &T { - &self.val - } -} - -impl<T> DerefMut for Sp<T> { - fn deref_mut(&mut self) -> &mut T { - &mut self.val - } -} - -impl From<Ident> for Sp<String> { - fn from(ident: Ident) -> Self { - Sp { - val: ident.to_string(), - span: ident.span(), - } - } -} - -impl From<LitStr> for Sp<String> { - fn from(lit: LitStr) -> Self { - Sp { - val: lit.value(), - span: lit.span(), - } - } -} - -impl<'a> From<Sp<&'a str>> for Sp<String> { - fn from(sp: Sp<&'a str>) -> Self { - Sp::new(sp.val.into(), sp.span) - } -} - -impl<U, T: PartialEq<U>> PartialEq<U> for Sp<T> { - fn eq(&self, other: &U) -> bool { - self.val == *other - } -} - -impl<T: AsRef<str>> AsRef<str> for Sp<T> { - fn as_ref(&self) -> &str { - self.val.as_ref() - } -} - -impl<T: ToTokens> ToTokens for Sp<T> { - fn to_tokens(&self, stream: &mut TokenStream) { - // this is the simplest way out of correct ones to change span on - // arbitrary token tree I can come up with - let tt = self.val.to_token_stream().into_iter().map(|mut tt| { - tt.set_span(self.span.clone()); - tt - }); - - stream.extend(tt); - } -} diff --git a/structopt/structopt-derive/src/ty.rs b/structopt/structopt-derive/src/ty.rs deleted file mode 100644 index 06eb3ec..0000000 --- a/structopt/structopt-derive/src/ty.rs +++ /dev/null @@ -1,108 +0,0 @@ -//! Special types handling - -use crate::spanned::Sp; - -use syn::{ - spanned::Spanned, GenericArgument, Path, PathArguments, PathArguments::AngleBracketed, - PathSegment, Type, TypePath, -}; - -#[derive(Copy, Clone, PartialEq, Debug)] -pub enum Ty { - Bool, - Vec, - Option, - OptionOption, - OptionVec, - Other, -} - -impl Ty { - pub fn from_syn_ty(ty: &syn::Type) -> Sp<Self> { - use Ty::*; - let t = |kind| Sp::new(kind, ty.span()); - - if is_simple_ty(ty, "bool") { - t(Bool) - } else if is_generic_ty(ty, "Vec") { - t(Vec) - } else if let Some(subty) = subty_if_name(ty, "Option") { - if is_generic_ty(subty, "Option") { - t(OptionOption) - } else if is_generic_ty(subty, "Vec") { - t(OptionVec) - } else { - t(Option) - } - } else { - t(Other) - } - } -} - -pub fn sub_type(ty: &syn::Type) -> Option<&syn::Type> { - subty_if(ty, |_| true) -} - -fn only_last_segment(ty: &syn::Type) -> Option<&PathSegment> { - match ty { - Type::Path(TypePath { - qself: None, - path: - Path { - leading_colon: None, - segments, - }, - }) => only_one(segments.iter()), - - _ => None, - } -} - -fn subty_if<F>(ty: &syn::Type, f: F) -> Option<&syn::Type> -where - F: FnOnce(&PathSegment) -> bool, -{ - only_last_segment(ty) - .filter(|segment| f(segment)) - .and_then(|segment| { - if let AngleBracketed(args) = &segment.arguments { - only_one(args.args.iter()).and_then(|genneric| { - if let GenericArgument::Type(ty) = genneric { - Some(ty) - } else { - None - } - }) - } else { - None - } - }) -} - -fn subty_if_name<'a>(ty: &'a syn::Type, name: &str) -> Option<&'a syn::Type> { - subty_if(ty, |seg| seg.ident == name) -} - -fn is_simple_ty(ty: &syn::Type, name: &str) -> bool { - only_last_segment(ty) - .map(|segment| { - if let PathArguments::None = segment.arguments { - segment.ident == name - } else { - false - } - }) - .unwrap_or(false) -} - -fn is_generic_ty(ty: &syn::Type, name: &str) -> bool { - subty_if_name(ty, name).is_some() -} - -fn only_one<I, T>(mut iter: I) -> Option<T> -where - I: Iterator<Item = T>, -{ - iter.next().filter(|_| iter.next().is_none()) -} diff --git a/structopt/tests/argument_naming.rs b/structopt/tests/argument_naming.rs deleted file mode 100644 index e7fe3d5..0000000 --- a/structopt/tests/argument_naming.rs +++ /dev/null @@ -1,311 +0,0 @@ -use structopt::StructOpt; - -#[test] -fn test_single_word_enum_variant_is_default_renamed_into_kebab_case() { - #[derive(StructOpt, Debug, PartialEq)] - enum Opt { - Command { foo: u32 }, - } - - assert_eq!( - Opt::Command { foo: 0 }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "command", "0"])) - ); -} - -#[test] -fn test_multi_word_enum_variant_is_renamed() { - #[derive(StructOpt, Debug, PartialEq)] - enum Opt { - FirstCommand { foo: u32 }, - } - - assert_eq!( - Opt::FirstCommand { foo: 0 }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "first-command", "0"])) - ); -} - -#[test] -fn test_standalone_long_generates_kebab_case() { - #[derive(StructOpt, Debug, PartialEq)] - #[allow(non_snake_case)] - struct Opt { - #[structopt(long)] - FOO_OPTION: bool, - } - - assert_eq!( - Opt { FOO_OPTION: true }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "--foo-option"])) - ); -} - -#[test] -fn test_custom_long_overwrites_default_name() { - #[derive(StructOpt, Debug, PartialEq)] - struct Opt { - #[structopt(long = "foo")] - foo_option: bool, - } - - assert_eq!( - Opt { foo_option: true }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "--foo"])) - ); -} - -#[test] -fn test_standalone_long_uses_previous_defined_custom_name() { - #[derive(StructOpt, Debug, PartialEq)] - struct Opt { - #[structopt(name = "foo", long)] - foo_option: bool, - } - - assert_eq!( - Opt { foo_option: true }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "--foo"])) - ); -} - -#[test] -fn test_standalone_long_ignores_afterwards_defined_custom_name() { - #[derive(StructOpt, Debug, PartialEq)] - struct Opt { - #[structopt(long, name = "foo")] - foo_option: bool, - } - - assert_eq!( - Opt { foo_option: true }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "--foo-option"])) - ); -} - -#[test] -fn test_standalone_short_generates_kebab_case() { - #[derive(StructOpt, Debug, PartialEq)] - #[allow(non_snake_case)] - struct Opt { - #[structopt(short)] - FOO_OPTION: bool, - } - - assert_eq!( - Opt { FOO_OPTION: true }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-f"])) - ); -} - -#[test] -fn test_custom_short_overwrites_default_name() { - #[derive(StructOpt, Debug, PartialEq)] - struct Opt { - #[structopt(short = "o")] - foo_option: bool, - } - - assert_eq!( - Opt { foo_option: true }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-o"])) - ); -} - -#[test] -fn test_standalone_short_uses_previous_defined_custom_name() { - #[derive(StructOpt, Debug, PartialEq)] - struct Opt { - #[structopt(name = "option", short)] - foo_option: bool, - } - - assert_eq!( - Opt { foo_option: true }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-o"])) - ); -} - -#[test] -fn test_standalone_short_ignores_afterwards_defined_custom_name() { - #[derive(StructOpt, Debug, PartialEq)] - struct Opt { - #[structopt(short, name = "option")] - foo_option: bool, - } - - assert_eq!( - Opt { foo_option: true }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-f"])) - ); -} - -#[test] -fn test_standalone_long_uses_previous_defined_casing() { - #[derive(StructOpt, Debug, PartialEq)] - struct Opt { - #[structopt(rename_all = "screaming_snake", long)] - foo_option: bool, - } - - assert_eq!( - Opt { foo_option: true }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "--FOO_OPTION"])) - ); -} - -#[test] -fn test_standalone_short_uses_previous_defined_casing() { - #[derive(StructOpt, Debug, PartialEq)] - struct Opt { - #[structopt(rename_all = "screaming_snake", short)] - foo_option: bool, - } - - assert_eq!( - Opt { foo_option: true }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-F"])) - ); -} - -#[test] -fn test_standalone_long_works_with_verbatim_casing() { - #[derive(StructOpt, Debug, PartialEq)] - #[allow(non_snake_case)] - struct Opt { - #[structopt(rename_all = "verbatim", long)] - _fOO_oPtiON: bool, - } - - assert_eq!( - Opt { _fOO_oPtiON: true }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "--_fOO_oPtiON"])) - ); -} - -#[test] -fn test_standalone_short_works_with_verbatim_casing() { - #[derive(StructOpt, Debug, PartialEq)] - struct Opt { - #[structopt(rename_all = "verbatim", short)] - _foo: bool, - } - - assert_eq!( - Opt { _foo: true }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-_"])) - ); -} - -#[test] -fn test_rename_all_is_propagated_from_struct_to_fields() { - #[derive(StructOpt, Debug, PartialEq)] - #[structopt(rename_all = "screaming_snake")] - struct Opt { - #[structopt(long)] - foo: bool, - } - - assert_eq!( - Opt { foo: true }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "--FOO"])) - ); -} - -#[test] -fn test_rename_all_is_not_propagated_from_struct_into_flattened() { - #[derive(StructOpt, Debug, PartialEq)] - #[structopt(rename_all = "screaming_snake")] - struct Opt { - #[structopt(flatten)] - foo: Foo, - } - - #[derive(StructOpt, Debug, PartialEq)] - struct Foo { - #[structopt(long)] - foo: bool, - } - - assert_eq!( - Opt { - foo: Foo { foo: true } - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "--foo"])) - ); -} - -#[test] -fn test_rename_all_is_not_propagated_from_struct_into_subcommand() { - #[derive(StructOpt, Debug, PartialEq)] - #[structopt(rename_all = "screaming_snake")] - struct Opt { - #[structopt(subcommand)] - foo: Foo, - } - - #[derive(StructOpt, Debug, PartialEq)] - enum Foo { - Command { - #[structopt(long)] - foo: bool, - }, - } - - assert_eq!( - Opt { - foo: Foo::Command { foo: true } - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "command", "--foo"])) - ); -} - -#[test] -fn test_rename_all_is_propagated_from_enum_to_variants_and_their_fields() { - #[derive(StructOpt, Debug, PartialEq)] - #[structopt(rename_all = "screaming_snake")] - enum Opt { - FirstVariant, - SecondVariant { - #[structopt(long)] - foo: bool, - }, - } - - assert_eq!( - Opt::FirstVariant, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "FIRST_VARIANT"])) - ); - - assert_eq!( - Opt::SecondVariant { foo: true }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "SECOND_VARIANT", "--FOO"])) - ); -} - -#[test] -fn test_rename_all_is_propagation_can_be_overridden() { - #[derive(StructOpt, Debug, PartialEq)] - #[structopt(rename_all = "screaming_snake")] - enum Opt { - #[structopt(rename_all = "kebab_case")] - FirstVariant { - #[structopt(long)] - foo_option: bool, - }, - SecondVariant { - #[structopt(rename_all = "kebab_case", long)] - foo_option: bool, - }, - } - - assert_eq!( - Opt::FirstVariant { foo_option: true }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "first-variant", "--foo-option"])) - ); - - assert_eq!( - Opt::SecondVariant { foo_option: true }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "SECOND_VARIANT", "--foo-option"])) - ); -} diff --git a/structopt/tests/arguments.rs b/structopt/tests/arguments.rs deleted file mode 100644 index 96a0938..0000000 --- a/structopt/tests/arguments.rs +++ /dev/null @@ -1,86 +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. - -use structopt::clap; -use structopt::StructOpt; - -#[test] -fn required_argument() { - #[derive(StructOpt, PartialEq, Debug)] - struct Opt { - arg: i32, - } - assert_eq!(Opt { arg: 42 }, Opt::from_iter(&["test", "42"])); - assert!(Opt::clap().get_matches_from_safe(&["test"]).is_err()); - assert!(Opt::clap() - .get_matches_from_safe(&["test", "42", "24"]) - .is_err()); -} - -#[test] -fn optional_argument() { - #[derive(StructOpt, PartialEq, Debug)] - struct Opt { - arg: Option<i32>, - } - assert_eq!(Opt { arg: Some(42) }, Opt::from_iter(&["test", "42"])); - assert_eq!(Opt { arg: None }, Opt::from_iter(&["test"])); - assert!(Opt::clap() - .get_matches_from_safe(&["test", "42", "24"]) - .is_err()); -} - -#[test] -fn argument_with_default() { - #[derive(StructOpt, PartialEq, Debug)] - struct Opt { - #[structopt(default_value = "42")] - arg: i32, - } - assert_eq!(Opt { arg: 24 }, Opt::from_iter(&["test", "24"])); - assert_eq!(Opt { arg: 42 }, Opt::from_iter(&["test"])); - assert!(Opt::clap() - .get_matches_from_safe(&["test", "42", "24"]) - .is_err()); -} - -#[test] -fn arguments() { - #[derive(StructOpt, PartialEq, Debug)] - struct Opt { - arg: Vec<i32>, - } - assert_eq!(Opt { arg: vec![24] }, Opt::from_iter(&["test", "24"])); - assert_eq!(Opt { arg: vec![] }, Opt::from_iter(&["test"])); - assert_eq!( - Opt { arg: vec![24, 42] }, - Opt::from_iter(&["test", "24", "42"]) - ); -} - -#[test] -fn arguments_safe() { - #[derive(StructOpt, PartialEq, Debug)] - struct Opt { - arg: Vec<i32>, - } - assert_eq!( - Opt { arg: vec![24] }, - Opt::from_iter_safe(&["test", "24"]).unwrap() - ); - assert_eq!(Opt { arg: vec![] }, Opt::from_iter_safe(&["test"]).unwrap()); - assert_eq!( - Opt { arg: vec![24, 42] }, - Opt::from_iter_safe(&["test", "24", "42"]).unwrap() - ); - - assert_eq!( - clap::ErrorKind::ValueValidation, - Opt::from_iter_safe(&["test", "NOPE"]).err().unwrap().kind - ); -} diff --git a/structopt/tests/author_version_about.rs b/structopt/tests/author_version_about.rs deleted file mode 100644 index 0c4a4fb..0000000 --- a/structopt/tests/author_version_about.rs +++ /dev/null @@ -1,46 +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. - -mod utils; - -use structopt::StructOpt; -use utils::*; - -#[test] -fn no_author_version_about() { - #[derive(StructOpt, PartialEq, Debug)] - #[structopt(name = "foo", no_version)] - struct Opt {} - - let output = get_long_help::<Opt>(); - assert!(output.starts_with("foo \n\nUSAGE:")); -} - -#[test] -fn use_env() { - #[derive(StructOpt, PartialEq, Debug)] - #[structopt(author, about)] - struct Opt {} - - let output = get_long_help::<Opt>(); - assert!(output.starts_with("structopt 0.")); - assert!(output.contains("Guillaume Pinot <texitoi@texitoi.eu>, others")); - assert!(output.contains("Parse command line argument by defining a struct.")); -} - -#[test] -fn explicit_version_not_str() { - const VERSION: &str = "custom version"; - - #[derive(StructOpt)] - #[structopt(version = VERSION)] - pub struct Opt {} - - let output = get_long_help::<Opt>(); - assert!(output.contains("custom version")); -} diff --git a/structopt/tests/custom-string-parsers.rs b/structopt/tests/custom-string-parsers.rs deleted file mode 100644 index 89070ed..0000000 --- a/structopt/tests/custom-string-parsers.rs +++ /dev/null @@ -1,306 +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. - -use structopt::StructOpt; - -use std::ffi::{CString, OsStr, OsString}; -use std::num::ParseIntError; -use std::path::PathBuf; - -#[derive(StructOpt, PartialEq, Debug)] -struct PathOpt { - #[structopt(short, long, parse(from_os_str))] - path: PathBuf, - - #[structopt(short, default_value = "../", parse(from_os_str))] - default_path: PathBuf, - - #[structopt(short, parse(from_os_str))] - vector_path: Vec<PathBuf>, - - #[structopt(short, parse(from_os_str))] - option_path_1: Option<PathBuf>, - - #[structopt(short = "q", parse(from_os_str))] - option_path_2: Option<PathBuf>, -} - -#[test] -fn test_path_opt_simple() { - assert_eq!( - PathOpt { - path: PathBuf::from("/usr/bin"), - default_path: PathBuf::from("../"), - vector_path: vec![ - PathBuf::from("/a/b/c"), - PathBuf::from("/d/e/f"), - PathBuf::from("/g/h/i"), - ], - option_path_1: None, - option_path_2: Some(PathBuf::from("j.zip")), - }, - PathOpt::from_clap(&PathOpt::clap().get_matches_from(&[ - "test", "-p", "/usr/bin", "-v", "/a/b/c", "-v", "/d/e/f", "-v", "/g/h/i", "-q", - "j.zip", - ])) - ); -} - -fn parse_hex(input: &str) -> Result<u64, ParseIntError> { - u64::from_str_radix(input, 16) -} - -#[derive(StructOpt, PartialEq, Debug)] -struct HexOpt { - #[structopt(short, parse(try_from_str = parse_hex))] - number: u64, -} - -#[test] -#[allow(clippy::unreadable_literal)] -fn test_parse_hex() { - assert_eq!( - HexOpt { number: 5 }, - HexOpt::from_clap(&HexOpt::clap().get_matches_from(&["test", "-n", "5"])) - ); - assert_eq!( - HexOpt { number: 0xabcdef }, - HexOpt::from_clap(&HexOpt::clap().get_matches_from(&["test", "-n", "abcdef"])) - ); - - let err = HexOpt::clap() - .get_matches_from_safe(&["test", "-n", "gg"]) - .unwrap_err(); - assert!(err.message.contains("invalid digit found in string"), err); -} - -fn custom_parser_1(_: &str) -> &'static str { - "A" -} -fn custom_parser_2(_: &str) -> Result<&'static str, u32> { - Ok("B") -} -fn custom_parser_3(_: &OsStr) -> &'static str { - "C" -} -fn custom_parser_4(_: &OsStr) -> Result<&'static str, OsString> { - Ok("D") -} - -#[derive(StructOpt, PartialEq, Debug)] -struct NoOpOpt { - #[structopt(short, parse(from_str = custom_parser_1))] - a: &'static str, - #[structopt(short, parse(try_from_str = custom_parser_2))] - b: &'static str, - #[structopt(short, parse(from_os_str = custom_parser_3))] - c: &'static str, - #[structopt(short, parse(try_from_os_str = custom_parser_4))] - d: &'static str, -} - -#[test] -fn test_every_custom_parser() { - assert_eq!( - NoOpOpt { - a: "A", - b: "B", - c: "C", - d: "D" - }, - NoOpOpt::from_clap( - &NoOpOpt::clap().get_matches_from(&["test", "-a=?", "-b=?", "-c=?", "-d=?"]) - ) - ); -} - -// Note: can't use `Vec<u8>` directly, as structopt would instead look for -// conversion function from `&str` to `u8`. -type Bytes = Vec<u8>; - -#[derive(StructOpt, PartialEq, Debug)] -struct DefaultedOpt { - #[structopt(short, parse(from_str))] - bytes: Bytes, - - #[structopt(short, parse(try_from_str))] - integer: u64, - - #[structopt(short, parse(from_os_str))] - path: PathBuf, -} - -#[test] -fn test_parser_with_default_value() { - assert_eq!( - DefaultedOpt { - bytes: b"E\xc2\xb2=p\xc2\xb2c\xc2\xb2+m\xc2\xb2c\xe2\x81\xb4".to_vec(), - integer: 9000, - path: PathBuf::from("src/lib.rs"), - }, - DefaultedOpt::from_clap(&DefaultedOpt::clap().get_matches_from(&[ - "test", - "-b", - "E²=p²c²+m²c⁴", - "-i", - "9000", - "-p", - "src/lib.rs", - ])) - ); -} - -#[derive(PartialEq, Debug)] -struct Foo(u8); - -fn foo(value: u64) -> Foo { - Foo(value as u8) -} - -#[derive(StructOpt, PartialEq, Debug)] -struct Occurrences { - #[structopt(short, long, parse(from_occurrences))] - signed: i32, - - #[structopt(short, parse(from_occurrences))] - little_signed: i8, - - #[structopt(short, parse(from_occurrences))] - unsigned: usize, - - #[structopt(short = "r", parse(from_occurrences))] - little_unsigned: u8, - - #[structopt(short, long, parse(from_occurrences = foo))] - custom: Foo, -} - -#[test] -fn test_parser_occurrences() { - assert_eq!( - Occurrences { - signed: 3, - little_signed: 1, - unsigned: 0, - little_unsigned: 4, - custom: Foo(5), - }, - Occurrences::from_clap(&Occurrences::clap().get_matches_from(&[ - "test", "-s", "--signed", "--signed", "-l", "-rrrr", "-cccc", "--custom", - ])) - ); -} - -#[test] -fn test_custom_bool() { - fn parse_bool(s: &str) -> Result<bool, String> { - match s { - "true" => Ok(true), - "false" => Ok(false), - _ => Err(format!("invalid bool {}", s)), - } - } - #[derive(StructOpt, PartialEq, Debug)] - struct Opt { - #[structopt(short, parse(try_from_str = parse_bool))] - debug: bool, - #[structopt( - short, - default_value = "false", - parse(try_from_str = parse_bool) - )] - verbose: bool, - #[structopt(short, parse(try_from_str = parse_bool))] - tribool: Option<bool>, - #[structopt(short, parse(try_from_str = parse_bool))] - bitset: Vec<bool>, - } - - assert!(Opt::clap().get_matches_from_safe(&["test"]).is_err()); - assert!(Opt::clap().get_matches_from_safe(&["test", "-d"]).is_err()); - assert!(Opt::clap() - .get_matches_from_safe(&["test", "-dfoo"]) - .is_err()); - assert_eq!( - Opt { - debug: false, - verbose: false, - tribool: None, - bitset: vec![], - }, - Opt::from_iter(&["test", "-dfalse"]) - ); - assert_eq!( - Opt { - debug: true, - verbose: false, - tribool: None, - bitset: vec![], - }, - Opt::from_iter(&["test", "-dtrue"]) - ); - assert_eq!( - Opt { - debug: true, - verbose: false, - tribool: None, - bitset: vec![], - }, - Opt::from_iter(&["test", "-dtrue", "-vfalse"]) - ); - assert_eq!( - Opt { - debug: true, - verbose: true, - tribool: None, - bitset: vec![], - }, - Opt::from_iter(&["test", "-dtrue", "-vtrue"]) - ); - assert_eq!( - Opt { - debug: true, - verbose: false, - tribool: Some(false), - bitset: vec![], - }, - Opt::from_iter(&["test", "-dtrue", "-tfalse"]) - ); - assert_eq!( - Opt { - debug: true, - verbose: false, - tribool: Some(true), - bitset: vec![], - }, - Opt::from_iter(&["test", "-dtrue", "-ttrue"]) - ); - assert_eq!( - Opt { - debug: true, - verbose: false, - tribool: None, - bitset: vec![false, true, false, false], - }, - Opt::from_iter(&["test", "-dtrue", "-bfalse", "-btrue", "-bfalse", "-bfalse"]) - ); -} - -#[test] -fn test_cstring() { - #[derive(StructOpt)] - struct Opt { - #[structopt(parse(try_from_str = CString::new))] - c_string: CString, - } - assert!(Opt::clap().get_matches_from_safe(&["test"]).is_err()); - assert_eq!(Opt::from_iter(&["test", "bla"]).c_string.to_bytes(), b"bla"); - assert!(Opt::clap() - .get_matches_from_safe(&["test", "bla\0bla"]) - .is_err()); -} diff --git a/structopt/tests/deny-warnings.rs b/structopt/tests/deny-warnings.rs deleted file mode 100644 index 721204a..0000000 --- a/structopt/tests/deny-warnings.rs +++ /dev/null @@ -1,47 +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(warnings)] - -use structopt::StructOpt; - -fn try_str(s: &str) -> Result<String, std::convert::Infallible> { - Ok(s.into()) -} - -#[test] -fn warning_never_struct() { - #[derive(Debug, PartialEq, StructOpt)] - struct Opt { - #[structopt(parse(try_from_str = try_str))] - s: String, - } - assert_eq!( - Opt { - s: "foo".to_string() - }, - Opt::from_iter(&["test", "foo"]) - ); -} - -#[test] -fn warning_never_enum() { - #[derive(Debug, PartialEq, StructOpt)] - enum Opt { - Foo { - #[structopt(parse(try_from_str = try_str))] - s: String, - }, - } - assert_eq!( - Opt::Foo { - s: "foo".to_string() - }, - Opt::from_iter(&["test", "foo", "foo"]) - ); -} diff --git a/structopt/tests/doc-comments-help.rs b/structopt/tests/doc-comments-help.rs deleted file mode 100644 index 27649b8..0000000 --- a/structopt/tests/doc-comments-help.rs +++ /dev/null @@ -1,162 +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. - -mod utils; - -use structopt::StructOpt; -use utils::*; - -#[test] -fn doc_comments() { - /// Lorem ipsum - #[derive(StructOpt, PartialEq, Debug)] - struct LoremIpsum { - /// Fooify a bar - /// and a baz - #[structopt(short, long)] - foo: bool, - } - - let help = get_long_help::<LoremIpsum>(); - assert!(help.contains("Lorem ipsum")); - assert!(help.contains("Fooify a bar and a baz")); -} - -#[test] -fn help_is_better_than_comments() { - /// Lorem ipsum - #[derive(StructOpt, PartialEq, Debug)] - #[structopt(name = "lorem-ipsum", about = "Dolor sit amet")] - struct LoremIpsum { - /// Fooify a bar - #[structopt(short, long, help = "DO NOT PASS A BAR UNDER ANY CIRCUMSTANCES")] - foo: bool, - } - - let help = get_long_help::<LoremIpsum>(); - assert!(help.contains("Dolor sit amet")); - assert!(!help.contains("Lorem ipsum")); - assert!(help.contains("DO NOT PASS A BAR")); -} - -#[test] -fn empty_line_in_doc_comment_is_double_linefeed() { - /// Foo. - /// - /// Bar - #[derive(StructOpt, PartialEq, Debug)] - #[structopt(name = "lorem-ipsum", no_version)] - struct LoremIpsum {} - - let help = get_long_help::<LoremIpsum>(); - assert!(help.starts_with("lorem-ipsum \nFoo.\n\nBar\n\nUSAGE:")); -} - -#[test] -fn field_long_doc_comment_both_help_long_help() { - /// Lorem ipsumclap - #[derive(StructOpt, PartialEq, Debug)] - #[structopt(name = "lorem-ipsum", about = "Dolor sit amet")] - struct LoremIpsum { - /// Dot is removed from multiline comments. - /// - /// Long help - #[structopt(long)] - foo: bool, - - /// Dot is removed from one short comment. - #[structopt(long)] - bar: bool, - } - - let short_help = get_help::<LoremIpsum>(); - let long_help = get_long_help::<LoremIpsum>(); - - assert!(short_help.contains("Dot is removed from one short comment")); - assert!(!short_help.contains("Dot is removed from one short comment.")); - assert!(short_help.contains("Dot is removed from multiline comments")); - assert!(!short_help.contains("Dot is removed from multiline comments.")); - assert!(long_help.contains("Long help")); - assert!(!short_help.contains("Long help")); -} - -#[test] -fn top_long_doc_comment_both_help_long_help() { - /// Lorem ipsumclap - #[derive(StructOpt, Debug)] - #[structopt(name = "lorem-ipsum", about = "Dolor sit amet")] - struct LoremIpsum { - #[structopt(subcommand)] - foo: SubCommand, - } - - #[derive(StructOpt, Debug)] - pub enum SubCommand { - /// DO NOT PASS A BAR UNDER ANY CIRCUMSTANCES - /// - /// Or something else - Foo { - #[structopt(help = "foo")] - bars: Vec<String>, - }, - } - - let short_help = get_help::<LoremIpsum>(); - let long_help = get_subcommand_long_help::<LoremIpsum>("foo"); - - assert!(!short_help.contains("Or something else")); - assert!(long_help.contains("DO NOT PASS A BAR UNDER ANY CIRCUMSTANCES")); - assert!(long_help.contains("Or something else")); -} - -#[test] -fn verbatim_doc_comment() { - /// DANCE! - /// - /// () - /// | - /// ( () ) - /// ) ________ // ) - /// () |\ \ // - /// ( \\__ \ ______\// - /// \__) | | - /// | | | - /// \ | | - /// \|_______| - /// // \\ - /// (( || - /// \\ || - /// ( () || - /// ( () ) ) - #[derive(StructOpt, Debug)] - #[structopt(verbatim_doc_comment)] - struct SeeFigure1 { - #[structopt(long)] - foo: bool, - } - - let help = get_long_help::<SeeFigure1>(); - let sample = r#" - () - | - ( () ) - ) ________ // ) - () |\ \ // -( \\__ \ ______\// - \__) | | - | | | - \ | | - \|_______| - // \\ - (( || - \\ || - ( () || - ( () ) )"#; - - assert!(help.contains(sample)) -} diff --git a/structopt/tests/explicit_name_no_renaming.rs b/structopt/tests/explicit_name_no_renaming.rs deleted file mode 100644 index eff7a86..0000000 --- a/structopt/tests/explicit_name_no_renaming.rs +++ /dev/null @@ -1,32 +0,0 @@ -mod utils; - -use structopt::StructOpt; -use utils::*; - -#[test] -fn explicit_short_long_no_rename() { - #[derive(StructOpt, PartialEq, Debug)] - struct Opt { - #[structopt(short = ".", long = ".foo")] - foo: Vec<String>, - } - - assert_eq!( - Opt { - foo: vec!["short".into(), "long".into()] - }, - Opt::from_iter(&["test", "-.", "short", "--.foo", "long"]) - ); -} - -#[test] -fn explicit_name_no_rename() { - #[derive(StructOpt, PartialEq, Debug)] - struct Opt { - #[structopt(name = ".options")] - foo: Vec<String>, - } - - let help = get_long_help::<Opt>(); - assert!(help.contains("[.options]...")) -} diff --git a/structopt/tests/flags.rs b/structopt/tests/flags.rs deleted file mode 100644 index 39a5dc3..0000000 --- a/structopt/tests/flags.rs +++ /dev/null @@ -1,162 +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. - -use structopt::StructOpt; - -#[test] -fn unique_flag() { - #[derive(StructOpt, PartialEq, Debug)] - struct Opt { - #[structopt(short, long)] - alice: bool, - } - - assert_eq!( - Opt { alice: false }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test"])) - ); - assert_eq!( - Opt { alice: true }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a"])) - ); - assert_eq!( - Opt { alice: true }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "--alice"])) - ); - assert!(Opt::clap().get_matches_from_safe(&["test", "-i"]).is_err()); - assert!(Opt::clap() - .get_matches_from_safe(&["test", "-a", "foo"]) - .is_err()); - assert!(Opt::clap() - .get_matches_from_safe(&["test", "-a", "-a"]) - .is_err()); - assert!(Opt::clap() - .get_matches_from_safe(&["test", "-a", "--alice"]) - .is_err()); -} - -#[test] -fn multiple_flag() { - #[derive(StructOpt, PartialEq, Debug)] - struct Opt { - #[structopt(short, long, parse(from_occurrences))] - alice: u64, - #[structopt(short, long, parse(from_occurrences))] - bob: u8, - } - - assert_eq!( - Opt { alice: 0, bob: 0 }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test"])) - ); - assert_eq!( - Opt { alice: 1, bob: 0 }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a"])) - ); - assert_eq!( - Opt { alice: 2, bob: 0 }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a", "-a"])) - ); - assert_eq!( - Opt { alice: 2, bob: 2 }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a", "--alice", "-bb"])) - ); - assert_eq!( - Opt { alice: 3, bob: 1 }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-aaa", "--bob"])) - ); - assert!(Opt::clap().get_matches_from_safe(&["test", "-i"]).is_err()); - assert!(Opt::clap() - .get_matches_from_safe(&["test", "-a", "foo"]) - .is_err()); -} - -fn parse_from_flag(b: bool) -> std::sync::atomic::AtomicBool { - std::sync::atomic::AtomicBool::new(b) -} - -#[test] -fn non_bool_flags() { - #[derive(StructOpt, Debug)] - struct Opt { - #[structopt(short, long, parse(from_flag = parse_from_flag))] - alice: std::sync::atomic::AtomicBool, - #[structopt(short, long, parse(from_flag))] - bob: std::sync::atomic::AtomicBool, - } - - let falsey = Opt::from_clap(&Opt::clap().get_matches_from(&["test"])); - assert!(!falsey.alice.load(std::sync::atomic::Ordering::Relaxed)); - assert!(!falsey.bob.load(std::sync::atomic::Ordering::Relaxed)); - - let alice = Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a"])); - assert!(alice.alice.load(std::sync::atomic::Ordering::Relaxed)); - assert!(!alice.bob.load(std::sync::atomic::Ordering::Relaxed)); - - let bob = Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-b"])); - assert!(!bob.alice.load(std::sync::atomic::Ordering::Relaxed)); - assert!(bob.bob.load(std::sync::atomic::Ordering::Relaxed)); - - let both = Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-b", "-a"])); - assert!(both.alice.load(std::sync::atomic::Ordering::Relaxed)); - assert!(both.bob.load(std::sync::atomic::Ordering::Relaxed)); -} - -#[test] -fn combined_flags() { - #[derive(StructOpt, PartialEq, Debug)] - struct Opt { - #[structopt(short, long)] - alice: bool, - #[structopt(short, long, parse(from_occurrences))] - bob: u64, - } - - assert_eq!( - Opt { - alice: false, - bob: 0 - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test"])) - ); - assert_eq!( - Opt { - alice: true, - bob: 0 - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a"])) - ); - assert_eq!( - Opt { - alice: true, - bob: 0 - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a"])) - ); - assert_eq!( - Opt { - alice: false, - bob: 1 - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-b"])) - ); - assert_eq!( - Opt { - alice: true, - bob: 1 - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "--alice", "--bob"])) - ); - assert_eq!( - Opt { - alice: true, - bob: 4 - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-bb", "-a", "-bb"])) - ); -} diff --git a/structopt/tests/flatten.rs b/structopt/tests/flatten.rs deleted file mode 100644 index 4983d86..0000000 --- a/structopt/tests/flatten.rs +++ /dev/null @@ -1,95 +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. - -use structopt::StructOpt; - -#[test] -fn flatten() { - #[derive(StructOpt, PartialEq, Debug)] - struct Common { - arg: i32, - } - - #[derive(StructOpt, PartialEq, Debug)] - struct Opt { - #[structopt(flatten)] - common: Common, - } - assert_eq!( - Opt { - common: Common { arg: 42 } - }, - Opt::from_iter(&["test", "42"]) - ); - assert!(Opt::clap().get_matches_from_safe(&["test"]).is_err()); - assert!(Opt::clap() - .get_matches_from_safe(&["test", "42", "24"]) - .is_err()); -} - -#[test] -#[should_panic] -fn flatten_twice() { - #[derive(StructOpt, PartialEq, Debug)] - struct Common { - arg: i32, - } - - #[derive(StructOpt, PartialEq, Debug)] - struct Opt { - #[structopt(flatten)] - c1: Common, - // Defines "arg" twice, so this should not work. - #[structopt(flatten)] - c2: Common, - } - Opt::from_iter(&["test", "42", "43"]); -} - -#[test] -fn flatten_in_subcommand() { - #[derive(StructOpt, PartialEq, Debug)] - struct Common { - arg: i32, - } - - #[derive(StructOpt, PartialEq, Debug)] - struct Add { - #[structopt(short)] - interactive: bool, - #[structopt(flatten)] - common: Common, - } - - #[derive(StructOpt, PartialEq, Debug)] - enum Opt { - Fetch { - #[structopt(short)] - all: bool, - #[structopt(flatten)] - common: Common, - }, - - Add(Add), - } - - assert_eq!( - Opt::Fetch { - all: false, - common: Common { arg: 42 } - }, - Opt::from_iter(&["test", "fetch", "42"]) - ); - assert_eq!( - Opt::Add(Add { - interactive: true, - common: Common { arg: 43 } - }), - Opt::from_iter(&["test", "add", "-i", "43"]) - ); -} diff --git a/structopt/tests/issues.rs b/structopt/tests/issues.rs deleted file mode 100644 index 4d250ae..0000000 --- a/structopt/tests/issues.rs +++ /dev/null @@ -1,67 +0,0 @@ -// https://github.com/TeXitoi/structopt/issues/151 -// https://github.com/TeXitoi/structopt/issues/289 - -#[test] -fn issue_151() { - use structopt::{clap::ArgGroup, StructOpt}; - - #[derive(StructOpt, Debug)] - #[structopt(group = ArgGroup::with_name("verb").required(true).multiple(true))] - struct Opt { - #[structopt(long, group = "verb")] - foo: bool, - #[structopt(long, group = "verb")] - bar: bool, - } - - #[derive(Debug, StructOpt)] - struct Cli { - #[structopt(flatten)] - a: Opt, - } - - assert!(Cli::clap().get_matches_from_safe(&["test"]).is_err()); - assert!(Cli::clap() - .get_matches_from_safe(&["test", "--foo"]) - .is_ok()); - assert!(Cli::clap() - .get_matches_from_safe(&["test", "--bar"]) - .is_ok()); - assert!(Cli::clap() - .get_matches_from_safe(&["test", "--zebra"]) - .is_err()); - assert!(Cli::clap() - .get_matches_from_safe(&["test", "--foo", "--bar"]) - .is_ok()); -} - -#[test] -fn issue_289() { - use structopt::{clap::AppSettings, StructOpt}; - - #[derive(StructOpt)] - #[structopt(setting = AppSettings::InferSubcommands)] - enum Args { - SomeCommand(SubSubCommand), - AnotherCommand, - } - - #[derive(StructOpt)] - #[structopt(setting = AppSettings::InferSubcommands)] - enum SubSubCommand { - TestCommand, - } - - assert!(Args::clap() - .get_matches_from_safe(&["test", "some-command", "test-command"]) - .is_ok()); - assert!(Args::clap() - .get_matches_from_safe(&["test", "some", "test-command"]) - .is_ok()); - assert!(Args::clap() - .get_matches_from_safe(&["test", "some-command", "test"]) - .is_ok()); - assert!(Args::clap() - .get_matches_from_safe(&["test", "some", "test"]) - .is_ok()); -} diff --git a/structopt/tests/macro-errors.rs b/structopt/tests/macro-errors.rs deleted file mode 100644 index ae4f5a2..0000000 --- a/structopt/tests/macro-errors.rs +++ /dev/null @@ -1,13 +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 - -#[rustversion::attr(any(not(stable), before(1.39)), ignore)] -#[test] -fn ui() { - let t = trybuild::TestCases::new(); - t.compile_fail("tests/ui/*.rs"); -} diff --git a/structopt/tests/nested-subcommands.rs b/structopt/tests/nested-subcommands.rs deleted file mode 100644 index 1fbd166..0000000 --- a/structopt/tests/nested-subcommands.rs +++ /dev/null @@ -1,193 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, PartialEq, Debug)] -struct Opt { - #[structopt(short, long)] - force: bool, - #[structopt(short, long, parse(from_occurrences))] - verbose: u64, - #[structopt(subcommand)] - cmd: Sub, -} - -#[derive(StructOpt, PartialEq, Debug)] -enum Sub { - Fetch {}, - Add {}, -} - -#[derive(StructOpt, PartialEq, Debug)] -struct Opt2 { - #[structopt(short, long)] - force: bool, - #[structopt(short, long, parse(from_occurrences))] - verbose: u64, - #[structopt(subcommand)] - cmd: Option<Sub>, -} - -#[test] -fn test_no_cmd() { - let result = Opt::clap().get_matches_from_safe(&["test"]); - assert!(result.is_err()); - - assert_eq!( - Opt2 { - force: false, - verbose: 0, - cmd: None - }, - Opt2::from_clap(&Opt2::clap().get_matches_from(&["test"])) - ); -} - -#[test] -fn test_fetch() { - assert_eq!( - Opt { - force: false, - verbose: 3, - cmd: Sub::Fetch {} - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-vvv", "fetch"])) - ); - assert_eq!( - Opt { - force: true, - verbose: 0, - cmd: Sub::Fetch {} - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "--force", "fetch"])) - ); -} - -#[test] -fn test_add() { - assert_eq!( - Opt { - force: false, - verbose: 0, - cmd: Sub::Add {} - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "add"])) - ); - assert_eq!( - Opt { - force: false, - verbose: 2, - cmd: Sub::Add {} - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-vv", "add"])) - ); -} - -#[test] -fn test_badinput() { - let result = Opt::clap().get_matches_from_safe(&["test", "badcmd"]); - assert!(result.is_err()); - let result = Opt::clap().get_matches_from_safe(&["test", "add", "--verbose"]); - assert!(result.is_err()); - let result = Opt::clap().get_matches_from_safe(&["test", "--badopt", "add"]); - assert!(result.is_err()); - let result = Opt::clap().get_matches_from_safe(&["test", "add", "--badopt"]); - assert!(result.is_err()); -} - -#[derive(StructOpt, PartialEq, Debug)] -struct Opt3 { - #[structopt(short, long)] - all: bool, - #[structopt(subcommand)] - cmd: Sub2, -} - -#[derive(StructOpt, PartialEq, Debug)] -enum Sub2 { - Foo { - file: String, - #[structopt(subcommand)] - cmd: Sub3, - }, - Bar {}, -} - -#[derive(StructOpt, PartialEq, Debug)] -enum Sub3 { - Baz {}, - Quux {}, -} - -#[test] -fn test_subsubcommand() { - assert_eq!( - Opt3 { - all: true, - cmd: Sub2::Foo { - file: "lib.rs".to_string(), - cmd: Sub3::Quux {} - } - }, - Opt3::from_clap( - &Opt3::clap().get_matches_from(&["test", "--all", "foo", "lib.rs", "quux"]) - ) - ); -} - -#[derive(StructOpt, PartialEq, Debug)] -enum SubSubCmdWithOption { - Remote { - #[structopt(subcommand)] - cmd: Option<Remote>, - }, - Stash { - #[structopt(subcommand)] - cmd: Stash, - }, -} -#[derive(StructOpt, PartialEq, Debug)] -enum Remote { - Add { name: String, url: String }, - Remove { name: String }, -} - -#[derive(StructOpt, PartialEq, Debug)] -enum Stash { - Save, - Pop, -} - -#[test] -fn sub_sub_cmd_with_option() { - fn make(args: &[&str]) -> Option<SubSubCmdWithOption> { - SubSubCmdWithOption::clap() - .get_matches_from_safe(args) - .ok() - .map(|m| SubSubCmdWithOption::from_clap(&m)) - } - assert_eq!( - Some(SubSubCmdWithOption::Remote { cmd: None }), - make(&["", "remote"]) - ); - assert_eq!( - Some(SubSubCmdWithOption::Remote { - cmd: Some(Remote::Add { - name: "origin".into(), - url: "http".into() - }) - }), - make(&["", "remote", "add", "origin", "http"]) - ); - assert_eq!( - Some(SubSubCmdWithOption::Stash { cmd: Stash::Save }), - make(&["", "stash", "save"]) - ); - assert_eq!(None, make(&["", "stash"])); -} diff --git a/structopt/tests/non_literal_attributes.rs b/structopt/tests/non_literal_attributes.rs deleted file mode 100644 index 75b6b71..0000000 --- a/structopt/tests/non_literal_attributes.rs +++ /dev/null @@ -1,147 +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. - -use structopt::clap::AppSettings; -use structopt::StructOpt; - -pub const DISPLAY_ORDER: usize = 2; - -// Check if the global settings compile -#[derive(StructOpt, Debug, PartialEq, Eq)] -#[structopt(global_settings = &[AppSettings::ColoredHelp])] -struct Opt { - #[structopt( - long = "x", - display_order = DISPLAY_ORDER, - next_line_help = true, - default_value = "0", - require_equals = true - )] - x: i32, - - #[structopt(short = "l", long = "level", aliases = &["set-level", "lvl"])] - level: String, - - #[structopt(long("values"))] - values: Vec<i32>, - - #[structopt(name = "FILE", requires_if("FILE", "values"))] - files: Vec<String>, -} - -#[test] -fn test_slice() { - assert_eq!( - Opt { - x: 0, - level: "1".to_string(), - files: Vec::new(), - values: vec![], - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-l", "1"])) - ); - assert_eq!( - Opt { - x: 0, - level: "1".to_string(), - files: Vec::new(), - values: vec![], - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "--level", "1"])) - ); - assert_eq!( - Opt { - x: 0, - level: "1".to_string(), - files: Vec::new(), - values: vec![], - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "--set-level", "1"])) - ); - assert_eq!( - Opt { - x: 0, - level: "1".to_string(), - files: Vec::new(), - values: vec![], - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "--lvl", "1"])) - ); -} - -#[test] -fn test_multi_args() { - assert_eq!( - Opt { - x: 0, - level: "1".to_string(), - files: vec!["file".to_string()], - values: vec![], - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-l", "1", "file"])) - ); - assert_eq!( - Opt { - x: 0, - level: "1".to_string(), - files: vec!["FILE".to_string()], - values: vec![1], - }, - Opt::from_clap( - &Opt::clap().get_matches_from(&["test", "-l", "1", "--values", "1", "--", "FILE"]), - ) - ); -} - -#[test] -fn test_multi_args_fail() { - let result = Opt::clap().get_matches_from_safe(&["test", "-l", "1", "--", "FILE"]); - assert!(result.is_err()); -} - -#[test] -fn test_bool() { - assert_eq!( - Opt { - x: 1, - level: "1".to_string(), - files: vec![], - values: vec![], - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-l", "1", "--x=1"])) - ); - let result = Opt::clap().get_matches_from_safe(&["test", "-l", "1", "--x", "1"]); - assert!(result.is_err()); -} - -fn parse_hex(input: &str) -> Result<u64, std::num::ParseIntError> { - u64::from_str_radix(input, 16) -} - -#[derive(StructOpt, PartialEq, Debug)] -struct HexOpt { - #[structopt(short = "n", parse(try_from_str = parse_hex))] - number: u64, -} - -#[test] -fn test_parse_hex_function_path() { - assert_eq!( - HexOpt { number: 5 }, - HexOpt::from_clap(&HexOpt::clap().get_matches_from(&["test", "-n", "5"])) - ); - assert_eq!( - HexOpt { number: 0xabcdef }, - HexOpt::from_clap(&HexOpt::clap().get_matches_from(&["test", "-n", "abcdef"])) - ); - - let err = HexOpt::clap() - .get_matches_from_safe(&["test", "-n", "gg"]) - .unwrap_err(); - assert!(err.message.contains("invalid digit found in string"), err); -} diff --git a/structopt/tests/options.rs b/structopt/tests/options.rs deleted file mode 100644 index 803abb4..0000000 --- a/structopt/tests/options.rs +++ /dev/null @@ -1,336 +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. - -use structopt::StructOpt; - -#[test] -fn required_option() { - #[derive(StructOpt, PartialEq, Debug)] - struct Opt { - #[structopt(short, long)] - arg: i32, - } - assert_eq!( - Opt { arg: 42 }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a42"])) - ); - assert_eq!( - Opt { arg: 42 }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a", "42"])) - ); - assert_eq!( - Opt { arg: 42 }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "--arg", "42"])) - ); - assert!(Opt::clap().get_matches_from_safe(&["test"]).is_err()); - assert!(Opt::clap() - .get_matches_from_safe(&["test", "-a42", "-a24"]) - .is_err()); -} - -#[test] -fn optional_option() { - #[derive(StructOpt, PartialEq, Debug)] - struct Opt { - #[structopt(short)] - arg: Option<i32>, - } - assert_eq!( - Opt { arg: Some(42) }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a42"])) - ); - assert_eq!( - Opt { arg: None }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test"])) - ); - assert!(Opt::clap() - .get_matches_from_safe(&["test", "-a42", "-a24"]) - .is_err()); -} - -#[test] -fn option_with_default() { - #[derive(StructOpt, PartialEq, Debug)] - struct Opt { - #[structopt(short, default_value = "42")] - arg: i32, - } - assert_eq!( - Opt { arg: 24 }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a24"])) - ); - assert_eq!( - Opt { arg: 42 }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test"])) - ); - assert!(Opt::clap() - .get_matches_from_safe(&["test", "-a42", "-a24"]) - .is_err()); -} - -#[test] -fn option_with_raw_default() { - #[derive(StructOpt, PartialEq, Debug)] - struct Opt { - #[structopt(short, default_value = "42")] - arg: i32, - } - assert_eq!( - Opt { arg: 24 }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a24"])) - ); - assert_eq!( - Opt { arg: 42 }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test"])) - ); - assert!(Opt::clap() - .get_matches_from_safe(&["test", "-a42", "-a24"]) - .is_err()); -} - -#[test] -fn options() { - #[derive(StructOpt, PartialEq, Debug)] - struct Opt { - #[structopt(short, long)] - arg: Vec<i32>, - } - assert_eq!( - Opt { arg: vec![24] }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a24"])) - ); - assert_eq!( - Opt { arg: vec![] }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test"])) - ); - assert_eq!( - Opt { arg: vec![24, 42] }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a24", "--arg", "42"])) - ); -} - -#[test] -fn empy_default_value() { - #[derive(StructOpt, PartialEq, Debug)] - struct Opt { - #[structopt(short, default_value = "")] - arg: String, - } - assert_eq!(Opt { arg: "".into() }, Opt::from_iter(&["test"])); - assert_eq!( - Opt { arg: "foo".into() }, - Opt::from_iter(&["test", "-afoo"]) - ); -} - -#[test] -fn option_from_str() { - #[derive(Debug, PartialEq)] - struct A; - - impl<'a> From<&'a str> for A { - fn from(_: &str) -> A { - A - } - } - - #[derive(Debug, StructOpt, PartialEq)] - struct Opt { - #[structopt(parse(from_str))] - a: Option<A>, - } - - assert_eq!(Opt { a: None }, Opt::from_iter(&["test"])); - assert_eq!(Opt { a: Some(A) }, Opt::from_iter(&["test", "foo"])); -} - -#[test] -fn optional_argument_for_optional_option() { - #[derive(StructOpt, PartialEq, Debug)] - struct Opt { - #[structopt(short)] - #[allow(clippy::option_option)] - arg: Option<Option<i32>>, - } - assert_eq!( - Opt { - arg: Some(Some(42)) - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a42"])) - ); - assert_eq!( - Opt { arg: Some(None) }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a"])) - ); - assert_eq!( - Opt { arg: None }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test"])) - ); - assert!(Opt::clap() - .get_matches_from_safe(&["test", "-a42", "-a24"]) - .is_err()); -} - -#[test] -fn two_option_options() { - #[derive(StructOpt, PartialEq, Debug)] - #[allow(clippy::option_option)] - struct Opt { - #[structopt(short)] - arg: Option<Option<i32>>, - - #[structopt(long)] - field: Option<Option<String>>, - } - assert_eq!( - Opt { - arg: Some(Some(42)), - field: Some(Some("f".into())) - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a42", "--field", "f"])) - ); - assert_eq!( - Opt { - arg: Some(Some(42)), - field: Some(None) - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a42", "--field"])) - ); - assert_eq!( - Opt { - arg: Some(None), - field: Some(None) - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a", "--field"])) - ); - assert_eq!( - Opt { - arg: Some(None), - field: Some(Some("f".into())) - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a", "--field", "f"])) - ); - assert_eq!( - Opt { - arg: None, - field: Some(None) - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "--field"])) - ); - assert_eq!( - Opt { - arg: None, - field: None - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test"])) - ); -} - -#[test] -fn optional_vec() { - #[derive(StructOpt, PartialEq, Debug)] - struct Opt { - #[structopt(short)] - arg: Option<Vec<i32>>, - } - assert_eq!( - Opt { arg: Some(vec![1]) }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a", "1"])) - ); - - assert_eq!( - Opt { - arg: Some(vec![1, 2]) - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a1", "-a2"])) - ); - - assert_eq!( - Opt { - arg: Some(vec![1, 2]) - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a1", "-a2", "-a"])) - ); - - assert_eq!( - Opt { - arg: Some(vec![1, 2]) - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a1", "-a", "-a2"])) - ); - - assert_eq!( - Opt { - arg: Some(vec![1, 2]) - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a", "1", "2"])) - ); - - assert_eq!( - Opt { - arg: Some(vec![1, 2, 3]) - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a", "1", "2", "-a", "3"])) - ); - - assert_eq!( - Opt { arg: Some(vec![]) }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a"])) - ); - - assert_eq!( - Opt { arg: Some(vec![]) }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a", "-a"])) - ); - - assert_eq!( - Opt { arg: None }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test"])) - ); -} - -#[test] -fn two_optional_vecs() { - #[derive(StructOpt, PartialEq, Debug)] - struct Opt { - #[structopt(short)] - arg: Option<Vec<i32>>, - - #[structopt(short)] - b: Option<Vec<i32>>, - } - - assert_eq!( - Opt { - arg: Some(vec![1]), - b: Some(vec![]) - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a", "1", "-b"])) - ); - - assert_eq!( - Opt { - arg: Some(vec![1]), - b: Some(vec![]) - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a", "-b", "-a1"])) - ); - - assert_eq!( - Opt { - arg: Some(vec![1, 2]), - b: Some(vec![1, 2]) - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "-a1", "-a2", "-b1", "-b2"])) - ); - - assert_eq!( - Opt { arg: None, b: None }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test"])) - ); -} diff --git a/structopt/tests/privacy.rs b/structopt/tests/privacy.rs deleted file mode 100644 index 730bbce..0000000 --- a/structopt/tests/privacy.rs +++ /dev/null @@ -1,32 +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. - -use structopt::StructOpt; - -mod options { - use super::StructOpt; - - #[derive(Debug, StructOpt)] - pub struct Options { - #[structopt(subcommand)] - pub subcommand: super::subcommands::SubCommand, - } -} - -mod subcommands { - use super::StructOpt; - - #[derive(Debug, StructOpt)] - pub enum SubCommand { - /// foo - Foo { - /// foo - bars: Vec<String>, - }, - } -} diff --git a/structopt/tests/raw_bool_literal.rs b/structopt/tests/raw_bool_literal.rs deleted file mode 100644 index faf8628..0000000 --- a/structopt/tests/raw_bool_literal.rs +++ /dev/null @@ -1,29 +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. - -use structopt::StructOpt; - -#[test] -fn raw_bool_literal() { - #[derive(StructOpt, Debug, PartialEq)] - #[structopt(no_version, name = "raw_bool")] - struct Opt { - #[structopt(raw(false))] - a: String, - #[structopt(raw(true))] - b: String, - } - - assert_eq!( - Opt { - a: "one".into(), - b: "--help".into() - }, - Opt::from_iter(&["test", "one", "--", "--help"]) - ); -} diff --git a/structopt/tests/raw_idents.rs b/structopt/tests/raw_idents.rs deleted file mode 100644 index c00ff66..0000000 --- a/structopt/tests/raw_idents.rs +++ /dev/null @@ -1,17 +0,0 @@ -use structopt::StructOpt; - -#[test] -fn raw_idents() { - #[derive(StructOpt, Debug, PartialEq)] - struct Opt { - #[structopt(short, long)] - r#type: Vec<String>, - } - - assert_eq!( - Opt { - r#type: vec!["long".into(), "short".into()] - }, - Opt::from_iter(&["test", "--type", "long", "-t", "short"]) - ); -} diff --git a/structopt/tests/rename_all_env.rs b/structopt/tests/rename_all_env.rs deleted file mode 100644 index 1979e84..0000000 --- a/structopt/tests/rename_all_env.rs +++ /dev/null @@ -1,46 +0,0 @@ -mod utils; - -use structopt::StructOpt; -use utils::*; - -#[test] -fn it_works() { - #[derive(Debug, PartialEq, StructOpt)] - #[structopt(rename_all_env = "kebab")] - struct BehaviorModel { - #[structopt(env)] - be_nice: String, - } - - let help = get_help::<BehaviorModel>(); - assert!(help.contains("[env: be-nice=]")); -} - -#[test] -fn default_is_screaming() { - #[derive(Debug, PartialEq, StructOpt)] - struct BehaviorModel { - #[structopt(env)] - be_nice: String, - } - - let help = get_help::<BehaviorModel>(); - assert!(help.contains("[env: BE_NICE=]")); -} - -#[test] -fn overridable() { - #[derive(Debug, PartialEq, StructOpt)] - #[structopt(rename_all_env = "kebab")] - struct BehaviorModel { - #[structopt(env)] - be_nice: String, - - #[structopt(rename_all_env = "pascal", env)] - be_agressive: String, - } - - let help = get_help::<BehaviorModel>(); - assert!(help.contains("[env: be-nice=]")); - assert!(help.contains("[env: BeAgressive=]")); -} diff --git a/structopt/tests/skip.rs b/structopt/tests/skip.rs deleted file mode 100644 index 47682d8..0000000 --- a/structopt/tests/skip.rs +++ /dev/null @@ -1,148 +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. - -use structopt::StructOpt; - -#[test] -fn skip_1() { - #[derive(StructOpt, Debug, PartialEq)] - struct Opt { - #[structopt(short)] - x: u32, - #[structopt(skip)] - s: u32, - } - - assert!(Opt::from_iter_safe(&["test", "-x", "10", "20"]).is_err()); - assert_eq!( - Opt::from_iter(&["test", "-x", "10"]), - Opt { - x: 10, - s: 0, // default - } - ); -} - -#[test] -fn skip_2() { - #[derive(StructOpt, Debug, PartialEq)] - struct Opt { - #[structopt(short)] - x: u32, - #[structopt(skip)] - ss: String, - #[structopt(skip)] - sn: u8, - y: u32, - #[structopt(skip)] - sz: u16, - t: u32, - } - - assert_eq!( - Opt::from_iter(&["test", "-x", "10", "20", "30"]), - Opt { - x: 10, - ss: String::from(""), - sn: 0, - y: 20, - sz: 0, - t: 30, - } - ); -} - -#[test] -fn skip_enum() { - #[derive(Debug, PartialEq)] - #[allow(unused)] - enum Kind { - A, - B, - } - - impl Default for Kind { - fn default() -> Self { - return Kind::B; - } - } - - #[derive(StructOpt, Debug, PartialEq)] - pub struct Opt { - #[structopt(long, short)] - number: u32, - #[structopt(skip)] - k: Kind, - #[structopt(skip)] - v: Vec<u32>, - } - - assert_eq!( - Opt::from_iter(&["test", "-n", "10"]), - Opt { - number: 10, - k: Kind::B, - v: vec![], - } - ); -} - -#[test] -fn skip_help_doc_comments() { - #[derive(StructOpt, Debug, PartialEq)] - pub struct Opt { - #[structopt(skip, help = "internal_stuff")] - a: u32, - - #[structopt(skip, long_help = "internal_stuff\ndo not touch")] - b: u32, - - /// Not meant to be used by clap. - /// - /// I want a default here. - #[structopt(skip)] - c: u32, - - #[structopt(short, parse(try_from_str))] - n: u32, - } - - assert_eq!( - Opt::from_iter(&["test", "-n", "10"]), - Opt { - n: 10, - a: 0, - b: 0, - c: 0, - } - ); -} - -#[test] -fn skip_val() { - #[derive(StructOpt, Debug, PartialEq)] - pub struct Opt { - #[structopt(long, short)] - number: u32, - - #[structopt(skip = "key")] - k: String, - - #[structopt(skip = vec![1, 2, 3])] - v: Vec<u32>, - } - - assert_eq!( - Opt::from_iter(&["test", "-n", "10"]), - Opt { - number: 10, - k: "key".into(), - v: vec![1, 2, 3] - } - ); -} diff --git a/structopt/tests/special_types.rs b/structopt/tests/special_types.rs deleted file mode 100644 index ffed5e2..0000000 --- a/structopt/tests/special_types.rs +++ /dev/null @@ -1,73 +0,0 @@ -//! Checks that types like `::std::option::Option` are not special - -use structopt::StructOpt; - -#[rustversion::since(1.37)] -#[test] -fn special_types_bool() { - mod inner { - #[allow(non_camel_case_types)] - #[derive(PartialEq, Debug)] - pub struct bool(pub String); - - impl std::str::FromStr for self::bool { - type Err = String; - - fn from_str(s: &str) -> Result<Self, Self::Err> { - Ok(self::bool(s.into())) - } - } - }; - - #[derive(StructOpt, PartialEq, Debug)] - struct Opt { - arg: inner::bool, - } - - assert_eq!( - Opt { - arg: inner::bool("success".into()) - }, - Opt::from_iter(&["test", "success"]) - ); -} - -#[test] -fn special_types_option() { - fn parser(s: &str) -> Option<String> { - Some(s.to_string()) - } - - #[derive(StructOpt, PartialEq, Debug)] - struct Opt { - #[structopt(parse(from_str = parser))] - arg: ::std::option::Option<String>, - } - - assert_eq!( - Opt { - arg: Some("success".into()) - }, - Opt::from_iter(&["test", "success"]) - ); -} - -#[test] -fn special_types_vec() { - fn parser(s: &str) -> Vec<String> { - vec![s.to_string()] - } - - #[derive(StructOpt, PartialEq, Debug)] - struct Opt { - #[structopt(parse(from_str = parser))] - arg: ::std::vec::Vec<String>, - } - - assert_eq!( - Opt { - arg: vec!["success".into()] - }, - Opt::from_iter(&["test", "success"]) - ); -} diff --git a/structopt/tests/subcommands.rs b/structopt/tests/subcommands.rs deleted file mode 100644 index 170c0da..0000000 --- a/structopt/tests/subcommands.rs +++ /dev/null @@ -1,213 +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. - -mod utils; - -use structopt::StructOpt; -use utils::*; - -#[derive(StructOpt, PartialEq, Debug)] -enum Opt { - /// Fetch stuff from GitHub - Fetch { - #[structopt(long)] - all: bool, - #[structopt(short, long)] - /// Overwrite local branches. - force: bool, - repo: String, - }, - - Add { - #[structopt(short, long)] - interactive: bool, - #[structopt(short, long)] - verbose: bool, - }, -} - -#[test] -fn test_fetch() { - assert_eq!( - Opt::Fetch { - all: true, - force: false, - repo: "origin".to_string() - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "fetch", "--all", "origin"])) - ); - assert_eq!( - Opt::Fetch { - all: false, - force: true, - repo: "origin".to_string() - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "fetch", "-f", "origin"])) - ); -} - -#[test] -fn test_add() { - assert_eq!( - Opt::Add { - interactive: false, - verbose: false - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "add"])) - ); - assert_eq!( - Opt::Add { - interactive: true, - verbose: true - }, - Opt::from_clap(&Opt::clap().get_matches_from(&["test", "add", "-i", "-v"])) - ); -} - -#[test] -fn test_no_parse() { - let result = Opt::clap().get_matches_from_safe(&["test", "badcmd", "-i", "-v"]); - assert!(result.is_err()); - - let result = Opt::clap().get_matches_from_safe(&["test", "add", "--badoption"]); - assert!(result.is_err()); - - let result = Opt::clap().get_matches_from_safe(&["test"]); - assert!(result.is_err()); -} - -#[derive(StructOpt, PartialEq, Debug)] -enum Opt2 { - DoSomething { arg: String }, -} - -#[test] -/// This test is specifically to make sure that hyphenated subcommands get -/// processed correctly. -fn test_hyphenated_subcommands() { - assert_eq!( - Opt2::DoSomething { - arg: "blah".to_string() - }, - Opt2::from_clap(&Opt2::clap().get_matches_from(&["test", "do-something", "blah"])) - ); -} - -#[derive(StructOpt, PartialEq, Debug)] -enum Opt3 { - Add, - Init, - Fetch, -} - -#[test] -fn test_null_commands() { - assert_eq!( - Opt3::Add, - Opt3::from_clap(&Opt3::clap().get_matches_from(&["test", "add"])) - ); - assert_eq!( - Opt3::Init, - Opt3::from_clap(&Opt3::clap().get_matches_from(&["test", "init"])) - ); - assert_eq!( - Opt3::Fetch, - Opt3::from_clap(&Opt3::clap().get_matches_from(&["test", "fetch"])) - ); -} - -#[derive(StructOpt, PartialEq, Debug)] -#[structopt(about = "Not shown")] -struct Add { - file: String, -} -/// Not shown -#[derive(StructOpt, PartialEq, Debug)] -struct Fetch { - remote: String, -} -#[derive(StructOpt, PartialEq, Debug)] -enum Opt4 { - // Not shown - /// Add a file - Add(Add), - Init, - /// download history from remote - Fetch(Fetch), -} - -#[test] -fn test_tuple_commands() { - assert_eq!( - Opt4::Add(Add { - file: "f".to_string() - }), - Opt4::from_clap(&Opt4::clap().get_matches_from(&["test", "add", "f"])) - ); - assert_eq!( - Opt4::Init, - Opt4::from_clap(&Opt4::clap().get_matches_from(&["test", "init"])) - ); - assert_eq!( - Opt4::Fetch(Fetch { - remote: "origin".to_string() - }), - Opt4::from_clap(&Opt4::clap().get_matches_from(&["test", "fetch", "origin"])) - ); - - let output = get_long_help::<Opt4>(); - - assert!(output.contains("download history from remote")); - assert!(output.contains("Add a file")); - assert!(!output.contains("Not shown")); -} - -#[test] -fn enum_in_enum_subsubcommand() { - #[derive(StructOpt, Debug, PartialEq)] - pub enum Opt { - Daemon(DaemonCommand), - } - - #[derive(StructOpt, Debug, PartialEq)] - pub enum DaemonCommand { - Start, - Stop, - } - - let result = Opt::clap().get_matches_from_safe(&["test"]); - assert!(result.is_err()); - - let result = Opt::clap().get_matches_from_safe(&["test", "daemon"]); - assert!(result.is_err()); - - let result = Opt::from_iter(&["test", "daemon", "start"]); - assert_eq!(Opt::Daemon(DaemonCommand::Start), result); -} - -#[test] -fn flatten_enum() { - #[derive(StructOpt, Debug, PartialEq)] - struct Opt { - #[structopt(flatten)] - sub_cmd: SubCmd, - } - #[derive(StructOpt, Debug, PartialEq)] - enum SubCmd { - Foo, - Bar, - } - - assert!(Opt::from_iter_safe(&["test"]).is_err()); - assert_eq!( - Opt::from_iter(&["test", "foo"]), - Opt { - sub_cmd: SubCmd::Foo - } - ); -} diff --git a/structopt/tests/ui/bool_default_value.rs b/structopt/tests/ui/bool_default_value.rs deleted file mode 100644 index 9bdb0c9..0000000 --- a/structopt/tests/ui/bool_default_value.rs +++ /dev/null @@ -1,21 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -#[structopt(name = "basic")] -struct Opt { - #[structopt(short, default_value = true)] - b: bool, -} - -fn main() { - let opt = Opt::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/bool_default_value.stderr b/structopt/tests/ui/bool_default_value.stderr deleted file mode 100644 index 1e26a2d..0000000 --- a/structopt/tests/ui/bool_default_value.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: default_value is meaningless for bool - --> $DIR/bool_default_value.rs:14:24 - | -14 | #[structopt(short, default_value = true)] - | ^^^^^^^^^^^^^ diff --git a/structopt/tests/ui/bool_required.rs b/structopt/tests/ui/bool_required.rs deleted file mode 100644 index 018223c..0000000 --- a/structopt/tests/ui/bool_required.rs +++ /dev/null @@ -1,21 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -#[structopt(name = "basic")] -struct Opt { - #[structopt(short, required = true)] - b: bool, -} - -fn main() { - let opt = Opt::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/bool_required.stderr b/structopt/tests/ui/bool_required.stderr deleted file mode 100644 index 0b80d48..0000000 --- a/structopt/tests/ui/bool_required.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: required is meaningless for bool - --> $DIR/bool_required.rs:14:24 - | -14 | #[structopt(short, required = true)] - | ^^^^^^^^ diff --git a/structopt/tests/ui/flatten_and_doc.rs b/structopt/tests/ui/flatten_and_doc.rs deleted file mode 100644 index 2dc154d..0000000 --- a/structopt/tests/ui/flatten_and_doc.rs +++ /dev/null @@ -1,30 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -struct DaemonOpts { - #[structopt(short)] - user: String, - #[structopt(short)] - group: String, -} - -#[derive(StructOpt, Debug)] -#[structopt(name = "basic")] -struct Opt { - /// Opts. - #[structopt(flatten)] - opts: DaemonOpts, -} - -fn main() { - let opt = Opt::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/flatten_and_doc.stderr b/structopt/tests/ui/flatten_and_doc.stderr deleted file mode 100644 index 2724dbb..0000000 --- a/structopt/tests/ui/flatten_and_doc.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: methods and doc comments are not allowed for flattened entry - --> $DIR/flatten_and_doc.rs:23:17 - | -23 | #[structopt(flatten)] - | ^^^^^^^ diff --git a/structopt/tests/ui/flatten_and_methods.rs b/structopt/tests/ui/flatten_and_methods.rs deleted file mode 100644 index ff1af2e..0000000 --- a/structopt/tests/ui/flatten_and_methods.rs +++ /dev/null @@ -1,29 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -struct DaemonOpts { - #[structopt(short)] - user: String, - #[structopt(short)] - group: String, -} - -#[derive(StructOpt, Debug)] -#[structopt(name = "basic")] -struct Opt { - #[structopt(short, flatten)] - opts: DaemonOpts, -} - -fn main() { - let opt = Opt::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/flatten_and_methods.stderr b/structopt/tests/ui/flatten_and_methods.stderr deleted file mode 100644 index f058eb3..0000000 --- a/structopt/tests/ui/flatten_and_methods.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: methods and doc comments are not allowed for flattened entry - --> $DIR/flatten_and_methods.rs:22:24 - | -22 | #[structopt(short, flatten)] - | ^^^^^^^ diff --git a/structopt/tests/ui/flatten_and_parse.rs b/structopt/tests/ui/flatten_and_parse.rs deleted file mode 100644 index 3317272..0000000 --- a/structopt/tests/ui/flatten_and_parse.rs +++ /dev/null @@ -1,29 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -struct DaemonOpts { - #[structopt(short)] - user: String, - #[structopt(short)] - group: String, -} - -#[derive(StructOpt, Debug)] -#[structopt(name = "basic")] -struct Opt { - #[structopt(flatten, parse(from_occurrences))] - opts: DaemonOpts, -} - -fn main() { - let opt = Opt::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/flatten_and_parse.stderr b/structopt/tests/ui/flatten_and_parse.stderr deleted file mode 100644 index e217a84..0000000 --- a/structopt/tests/ui/flatten_and_parse.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: parse attribute is not allowed for flattened entry - --> $DIR/flatten_and_parse.rs:22:26 - | -22 | #[structopt(flatten, parse(from_occurrences))] - | ^^^^^ diff --git a/structopt/tests/ui/non_existent_attr.rs b/structopt/tests/ui/non_existent_attr.rs deleted file mode 100644 index 96daf45..0000000 --- a/structopt/tests/ui/non_existent_attr.rs +++ /dev/null @@ -1,21 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -#[structopt(name = "basic")] -struct Opt { - #[structopt(short, non_existing_attribute = 1)] - debug: bool, -} - -fn main() { - let opt = Opt::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/non_existent_attr.stderr b/structopt/tests/ui/non_existent_attr.stderr deleted file mode 100644 index 17bb87f..0000000 --- a/structopt/tests/ui/non_existent_attr.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error[E0599]: no method named `non_existing_attribute` found for type `clap::args::arg::Arg<'_, '_>` in the current scope - --> $DIR/non_existent_attr.rs:14:24 - | -14 | #[structopt(short, non_existing_attribute = 1)] - | ^^^^^^^^^^^^^^^^^^^^^^ method not found in `clap::args::arg::Arg<'_, '_>` diff --git a/structopt/tests/ui/opt_opt_nonpositional.rs b/structopt/tests/ui/opt_opt_nonpositional.rs deleted file mode 100644 index 2a08105..0000000 --- a/structopt/tests/ui/opt_opt_nonpositional.rs +++ /dev/null @@ -1,20 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -#[structopt(name = "basic")] -struct Opt { - n: Option<Option<u32>>, -} - -fn main() { - let opt = Opt::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/opt_opt_nonpositional.stderr b/structopt/tests/ui/opt_opt_nonpositional.stderr deleted file mode 100644 index 586bf7a..0000000 --- a/structopt/tests/ui/opt_opt_nonpositional.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: Option<Option<T>> type is meaningless for positional argument - --> $DIR/opt_opt_nonpositional.rs:14:8 - | -14 | n: Option<Option<u32>>, - | ^^^^^^ diff --git a/structopt/tests/ui/opt_vec_nonpositional.rs b/structopt/tests/ui/opt_vec_nonpositional.rs deleted file mode 100644 index 0f6f078..0000000 --- a/structopt/tests/ui/opt_vec_nonpositional.rs +++ /dev/null @@ -1,20 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -#[structopt(name = "basic")] -struct Opt { - n: Option<Vec<u32>>, -} - -fn main() { - let opt = Opt::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/opt_vec_nonpositional.stderr b/structopt/tests/ui/opt_vec_nonpositional.stderr deleted file mode 100644 index 6f01de5..0000000 --- a/structopt/tests/ui/opt_vec_nonpositional.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: Option<Vec<T>> type is meaningless for positional argument - --> $DIR/opt_vec_nonpositional.rs:14:8 - | -14 | n: Option<Vec<u32>>, - | ^^^^^^ diff --git a/structopt/tests/ui/option_default_value.rs b/structopt/tests/ui/option_default_value.rs deleted file mode 100644 index a86bc0e..0000000 --- a/structopt/tests/ui/option_default_value.rs +++ /dev/null @@ -1,21 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -#[structopt(name = "basic")] -struct Opt { - #[structopt(short, default_value = 1)] - n: Option<u32>, -} - -fn main() { - let opt = Opt::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/option_default_value.stderr b/structopt/tests/ui/option_default_value.stderr deleted file mode 100644 index 2215497..0000000 --- a/structopt/tests/ui/option_default_value.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: default_value is meaningless for Option - --> $DIR/option_default_value.rs:14:24 - | -14 | #[structopt(short, default_value = 1)] - | ^^^^^^^^^^^^^ diff --git a/structopt/tests/ui/option_required.rs b/structopt/tests/ui/option_required.rs deleted file mode 100644 index d91afbf..0000000 --- a/structopt/tests/ui/option_required.rs +++ /dev/null @@ -1,21 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -#[structopt(name = "basic")] -struct Opt { - #[structopt(short, required = true)] - n: Option<u32>, -} - -fn main() { - let opt = Opt::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/option_required.stderr b/structopt/tests/ui/option_required.stderr deleted file mode 100644 index 0230d57..0000000 --- a/structopt/tests/ui/option_required.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: required is meaningless for Option - --> $DIR/option_required.rs:14:24 - | -14 | #[structopt(short, required = true)] - | ^^^^^^^^ diff --git a/structopt/tests/ui/parse_empty_try_from_os.rs b/structopt/tests/ui/parse_empty_try_from_os.rs deleted file mode 100644 index acfef0b..0000000 --- a/structopt/tests/ui/parse_empty_try_from_os.rs +++ /dev/null @@ -1,21 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -#[structopt(name = "basic")] -struct Opt { - #[structopt(parse(try_from_os_str))] - s: String, -} - -fn main() { - let opt = Opt::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/parse_empty_try_from_os.stderr b/structopt/tests/ui/parse_empty_try_from_os.stderr deleted file mode 100644 index 3dc9f24..0000000 --- a/structopt/tests/ui/parse_empty_try_from_os.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: you must set parser for `try_from_os_str` explicitly - --> $DIR/parse_empty_try_from_os.rs:14:23 - | -14 | #[structopt(parse(try_from_os_str))] - | ^^^^^^^^^^^^^^^ diff --git a/structopt/tests/ui/parse_function_is_not_path.rs b/structopt/tests/ui/parse_function_is_not_path.rs deleted file mode 100644 index 5eebc57..0000000 --- a/structopt/tests/ui/parse_function_is_not_path.rs +++ /dev/null @@ -1,21 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -#[structopt(name = "basic")] -struct Opt { - #[structopt(parse(from_str = "2"))] - s: String, -} - -fn main() { - let opt = Opt::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/parse_function_is_not_path.stderr b/structopt/tests/ui/parse_function_is_not_path.stderr deleted file mode 100644 index 7cf7444..0000000 --- a/structopt/tests/ui/parse_function_is_not_path.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: `parse` argument must be a function path - --> $DIR/parse_function_is_not_path.rs:14:34 - | -14 | #[structopt(parse(from_str = "2"))] - | ^^^ diff --git a/structopt/tests/ui/parse_literal_spec.rs b/structopt/tests/ui/parse_literal_spec.rs deleted file mode 100644 index b6f125a..0000000 --- a/structopt/tests/ui/parse_literal_spec.rs +++ /dev/null @@ -1,21 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -#[structopt(name = "basic")] -struct Opt { - #[structopt(parse("from_str"))] - s: String, -} - -fn main() { - let opt = Opt::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/parse_literal_spec.stderr b/structopt/tests/ui/parse_literal_spec.stderr deleted file mode 100644 index 6e99e8b..0000000 --- a/structopt/tests/ui/parse_literal_spec.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: parser specification must start with identifier - --> $DIR/parse_literal_spec.rs:14:23 - | -14 | #[structopt(parse("from_str"))] - | ^^^^^^^^^^ diff --git a/structopt/tests/ui/parse_not_zero_args.rs b/structopt/tests/ui/parse_not_zero_args.rs deleted file mode 100644 index 8729178..0000000 --- a/structopt/tests/ui/parse_not_zero_args.rs +++ /dev/null @@ -1,21 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -#[structopt(name = "basic")] -struct Opt { - #[structopt(parse(from_str, from_str))] - s: String, -} - -fn main() { - let opt = Opt::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/parse_not_zero_args.stderr b/structopt/tests/ui/parse_not_zero_args.stderr deleted file mode 100644 index 11abe06..0000000 --- a/structopt/tests/ui/parse_not_zero_args.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: parse must have exactly one argument - --> $DIR/parse_not_zero_args.rs:14:17 - | -14 | #[structopt(parse(from_str, from_str))] - | ^^^^^ diff --git a/structopt/tests/ui/positional_bool.rs b/structopt/tests/ui/positional_bool.rs deleted file mode 100644 index 4dbf538..0000000 --- a/structopt/tests/ui/positional_bool.rs +++ /dev/null @@ -1,10 +0,0 @@ -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -struct Opt { - verbose: bool, -} - -fn main() { - Opt::from_args(); -}
\ No newline at end of file diff --git a/structopt/tests/ui/positional_bool.stderr b/structopt/tests/ui/positional_bool.stderr deleted file mode 100644 index c3ed1ad..0000000 --- a/structopt/tests/ui/positional_bool.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: `bool` cannot be used as positional parameter with default parser - - = help: if you want to create a flag add `long` or `short` - = help: If you really want a boolean parameter add an explicit parser, for example `parse(try_from_str)` - = note: see also https://github.com/TeXitoi/structopt/tree/master/examples/true_or_false.rs - - --> $DIR/positional_bool.rs:5:14 - | -5 | verbose: bool, - | ^^^^ diff --git a/structopt/tests/ui/raw.rs b/structopt/tests/ui/raw.rs deleted file mode 100644 index b94f783..0000000 --- a/structopt/tests/ui/raw.rs +++ /dev/null @@ -1,25 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -struct Opt { - #[structopt(raw(case_insensitive = "true"))] - s: String, -} - -#[derive(StructOpt, Debug)] -struct Opt2 { - #[structopt(raw(requires_if = r#""one", "two""#))] - s: String, -} -fn main() { - let opt = Opt::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/raw.stderr b/structopt/tests/ui/raw.stderr deleted file mode 100644 index 93b5e38..0000000 --- a/structopt/tests/ui/raw.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error: `#[structopt(raw(...))` attributes are removed in structopt 0.3, they are replaced with raw methods - - = help: if you meant to call `clap::Arg::raw()` method you should use bool literal, like `raw(true)` or `raw(false)` - = note: if you need to call `clap::Arg/App::case_insensitive` method you can do it like this: #[structopt(case_insensitive = true)] - - --> $DIR/raw.rs:13:17 - | -13 | #[structopt(raw(case_insensitive = "true"))] - | ^^^ - -error: `#[structopt(raw(...))` attributes are removed in structopt 0.3, they are replaced with raw methods - - = help: if you meant to call `clap::Arg::raw()` method you should use bool literal, like `raw(true)` or `raw(false)` - = note: if you need to call `clap::Arg/App::requires_if` method you can do it like this: #[structopt(requires_if("one", "two"))] - - --> $DIR/raw.rs:19:17 - | -19 | #[structopt(raw(requires_if = r#""one", "two""#))] - | ^^^ diff --git a/structopt/tests/ui/rename_all_wrong_casing.rs b/structopt/tests/ui/rename_all_wrong_casing.rs deleted file mode 100644 index 4dabe14..0000000 --- a/structopt/tests/ui/rename_all_wrong_casing.rs +++ /dev/null @@ -1,21 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -#[structopt(name = "basic", rename_all = "fail")] -struct Opt { - #[structopt(short)] - s: String, -} - -fn main() { - let opt = Opt::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/rename_all_wrong_casing.stderr b/structopt/tests/ui/rename_all_wrong_casing.stderr deleted file mode 100644 index 2a72080..0000000 --- a/structopt/tests/ui/rename_all_wrong_casing.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: unsupported casing: `fail` - --> $DIR/rename_all_wrong_casing.rs:12:42 - | -12 | #[structopt(name = "basic", rename_all = "fail")] - | ^^^^^^ diff --git a/structopt/tests/ui/skip_flatten.rs b/structopt/tests/ui/skip_flatten.rs deleted file mode 100644 index 8668ec2..0000000 --- a/structopt/tests/ui/skip_flatten.rs +++ /dev/null @@ -1,42 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -#[structopt(name = "make-cookie")] -struct MakeCookie { - #[structopt(short)] - s: String, - - #[structopt(skip, flatten)] - cmd: Command, -} - -#[derive(StructOpt, Debug)] -enum Command { - #[structopt(name = "pound")] - /// Pound acorns into flour for cookie dough. - Pound { acorns: u32 }, - - Sparkle { - #[structopt(short)] - color: String, - }, -} - -impl Default for Command { - fn default() -> Self { - Command::Pound { acorns: 0 } - } -} - -fn main() { - let opt = MakeCookie::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/skip_flatten.stderr b/structopt/tests/ui/skip_flatten.stderr deleted file mode 100644 index 76477a3..0000000 --- a/structopt/tests/ui/skip_flatten.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: subcommand, flatten and skip cannot be used together - --> $DIR/skip_flatten.rs:17:23 - | -17 | #[structopt(skip, flatten)] - | ^^^^^^^ diff --git a/structopt/tests/ui/skip_subcommand.rs b/structopt/tests/ui/skip_subcommand.rs deleted file mode 100644 index 5d21426..0000000 --- a/structopt/tests/ui/skip_subcommand.rs +++ /dev/null @@ -1,42 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -#[structopt(name = "make-cookie")] -struct MakeCookie { - #[structopt(short)] - s: String, - - #[structopt(subcommand, skip)] - cmd: Command, -} - -#[derive(StructOpt, Debug)] -enum Command { - #[structopt(name = "pound")] - /// Pound acorns into flour for cookie dough. - Pound { acorns: u32 }, - - Sparkle { - #[structopt(short)] - color: String, - }, -} - -impl Default for Command { - fn default() -> Self { - Command::Pound { acorns: 0 } - } -} - -fn main() { - let opt = MakeCookie::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/skip_subcommand.stderr b/structopt/tests/ui/skip_subcommand.stderr deleted file mode 100644 index aba2d69..0000000 --- a/structopt/tests/ui/skip_subcommand.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: subcommand, flatten and skip cannot be used together - --> $DIR/skip_subcommand.rs:17:29 - | -17 | #[structopt(subcommand, skip)] - | ^^^^ diff --git a/structopt/tests/ui/skip_with_other_options.rs b/structopt/tests/ui/skip_with_other_options.rs deleted file mode 100644 index 73c5342..0000000 --- a/structopt/tests/ui/skip_with_other_options.rs +++ /dev/null @@ -1,15 +0,0 @@ -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -#[structopt(name = "test")] -pub struct Opt { - #[structopt(long)] - a: u32, - #[structopt(skip, long)] - b: u32, -} - -fn main() { - let opt = Opt::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/skip_with_other_options.stderr b/structopt/tests/ui/skip_with_other_options.stderr deleted file mode 100644 index 3345f92..0000000 --- a/structopt/tests/ui/skip_with_other_options.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: methods are not allowed for skipped fields - --> $DIR/skip_with_other_options.rs:8:17 - | -8 | #[structopt(skip, long)] - | ^^^^ diff --git a/structopt/tests/ui/skip_without_default.rs b/structopt/tests/ui/skip_without_default.rs deleted file mode 100644 index bc47511..0000000 --- a/structopt/tests/ui/skip_without_default.rs +++ /dev/null @@ -1,29 +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. - -use structopt::StructOpt; - -#[derive(Debug)] -enum Kind { - A, - B, -} - -#[derive(StructOpt, Debug)] -#[structopt(name = "test")] -pub struct Opt { - #[structopt(short)] - number: u32, - #[structopt(skip)] - k: Kind, -} - -fn main() { - let opt = Opt::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/skip_without_default.stderr b/structopt/tests/ui/skip_without_default.stderr deleted file mode 100644 index 330898f..0000000 --- a/structopt/tests/ui/skip_without_default.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0277]: the trait bound `Kind: std::default::Default` is not satisfied - --> $DIR/skip_without_default.rs:22:17 - | -22 | #[structopt(skip)] - | ^^^^ the trait `std::default::Default` is not implemented for `Kind` - | - = note: required by `std::default::Default::default` - -For more information about this error, try `rustc --explain E0277`. diff --git a/structopt/tests/ui/struct_flatten.rs b/structopt/tests/ui/struct_flatten.rs deleted file mode 100644 index 2b205f1..0000000 --- a/structopt/tests/ui/struct_flatten.rs +++ /dev/null @@ -1,21 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -#[structopt(name = "basic", flatten)] -struct Opt { - #[structopt(short)] - s: String, -} - -fn main() { - let opt = Opt::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/struct_flatten.stderr b/structopt/tests/ui/struct_flatten.stderr deleted file mode 100644 index 7f0fc6d..0000000 --- a/structopt/tests/ui/struct_flatten.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: flatten is only allowed on fields - --> $DIR/struct_flatten.rs:12:29 - | -12 | #[structopt(name = "basic", flatten)] - | ^^^^^^^ diff --git a/structopt/tests/ui/struct_parse.rs b/structopt/tests/ui/struct_parse.rs deleted file mode 100644 index e428b23..0000000 --- a/structopt/tests/ui/struct_parse.rs +++ /dev/null @@ -1,21 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -#[structopt(name = "basic", parse(from_str))] -struct Opt { - #[structopt(short)] - s: String, -} - -fn main() { - let opt = Opt::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/struct_parse.stderr b/structopt/tests/ui/struct_parse.stderr deleted file mode 100644 index 5518214..0000000 --- a/structopt/tests/ui/struct_parse.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: `parse` attribute is only allowed on fields - --> $DIR/struct_parse.rs:12:29 - | -12 | #[structopt(name = "basic", parse(from_str))] - | ^^^^^ diff --git a/structopt/tests/ui/struct_subcommand.rs b/structopt/tests/ui/struct_subcommand.rs deleted file mode 100644 index ac0b145..0000000 --- a/structopt/tests/ui/struct_subcommand.rs +++ /dev/null @@ -1,21 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -#[structopt(name = "basic", subcommand)] -struct Opt { - #[structopt(short)] - s: String, -} - -fn main() { - let opt = Opt::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/struct_subcommand.stderr b/structopt/tests/ui/struct_subcommand.stderr deleted file mode 100644 index 438f6f8..0000000 --- a/structopt/tests/ui/struct_subcommand.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: subcommand is only allowed on fields - --> $DIR/struct_subcommand.rs:12:29 - | -12 | #[structopt(name = "basic", subcommand)] - | ^^^^^^^^^^ diff --git a/structopt/tests/ui/structopt_empty_attr.rs b/structopt/tests/ui/structopt_empty_attr.rs deleted file mode 100644 index a7fc0b9..0000000 --- a/structopt/tests/ui/structopt_empty_attr.rs +++ /dev/null @@ -1,22 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -#[structopt(name = "basic")] -struct Opt { - #[structopt] - debug: bool, -} - -fn main() { - let opt = Opt::from_args(); - println!("{:?}", opt); -} - diff --git a/structopt/tests/ui/structopt_empty_attr.stderr b/structopt/tests/ui/structopt_empty_attr.stderr deleted file mode 100644 index dde3630..0000000 --- a/structopt/tests/ui/structopt_empty_attr.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: expected parentheses after `structopt` - --> $DIR/structopt_empty_attr.rs:14:7 - | -14 | #[structopt] - | ^^^^^^^^^ diff --git a/structopt/tests/ui/structopt_name_value_attr.rs b/structopt/tests/ui/structopt_name_value_attr.rs deleted file mode 100644 index 3d9388f..0000000 --- a/structopt/tests/ui/structopt_name_value_attr.rs +++ /dev/null @@ -1,22 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -#[structopt(name = "basic")] -struct Opt { - #[structopt = "short"] - debug: bool, -} - -fn main() { - let opt = Opt::from_args(); - println!("{:?}", opt); -} - diff --git a/structopt/tests/ui/structopt_name_value_attr.stderr b/structopt/tests/ui/structopt_name_value_attr.stderr deleted file mode 100644 index f681978..0000000 --- a/structopt/tests/ui/structopt_name_value_attr.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: expected parentheses - --> $DIR/structopt_name_value_attr.rs:14:17 - | -14 | #[structopt = "short"] - | ^ diff --git a/structopt/tests/ui/subcommand_and_flatten.rs b/structopt/tests/ui/subcommand_and_flatten.rs deleted file mode 100644 index 742ee6d..0000000 --- a/structopt/tests/ui/subcommand_and_flatten.rs +++ /dev/null @@ -1,36 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -#[structopt(name = "make-cookie")] -struct MakeCookie { - #[structopt(short)] - s: String, - - #[structopt(subcommand, flatten)] - cmd: Command, -} - -#[derive(StructOpt, Debug)] -enum Command { - #[structopt(name = "pound")] - /// Pound acorns into flour for cookie dough. - Pound { acorns: u32 }, - - Sparkle { - #[structopt(short)] - color: String, - }, -} - -fn main() { - let opt = MakeCookie::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/subcommand_and_flatten.stderr b/structopt/tests/ui/subcommand_and_flatten.stderr deleted file mode 100644 index cacea5e..0000000 --- a/structopt/tests/ui/subcommand_and_flatten.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: subcommand, flatten and skip cannot be used together - --> $DIR/subcommand_and_flatten.rs:17:29 - | -17 | #[structopt(subcommand, flatten)] - | ^^^^^^^ diff --git a/structopt/tests/ui/subcommand_and_methods.rs b/structopt/tests/ui/subcommand_and_methods.rs deleted file mode 100644 index 890f10c..0000000 --- a/structopt/tests/ui/subcommand_and_methods.rs +++ /dev/null @@ -1,36 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -#[structopt(name = "make-cookie")] -struct MakeCookie { - #[structopt(short)] - s: String, - - #[structopt(subcommand, long)] - cmd: Command, -} - -#[derive(StructOpt, Debug)] -enum Command { - #[structopt(name = "pound")] - /// Pound acorns into flour for cookie dough. - Pound { acorns: u32 }, - - Sparkle { - #[structopt(short)] - color: String, - }, -} - -fn main() { - let opt = MakeCookie::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/subcommand_and_methods.stderr b/structopt/tests/ui/subcommand_and_methods.stderr deleted file mode 100644 index ccaf28d..0000000 --- a/structopt/tests/ui/subcommand_and_methods.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: methods in attributes are not allowed for subcommand - --> $DIR/subcommand_and_methods.rs:17:17 - | -17 | #[structopt(subcommand, long)] - | ^^^^^^^^^^ diff --git a/structopt/tests/ui/subcommand_and_parse.rs b/structopt/tests/ui/subcommand_and_parse.rs deleted file mode 100644 index f24e4bc..0000000 --- a/structopt/tests/ui/subcommand_and_parse.rs +++ /dev/null @@ -1,36 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -#[structopt(name = "make-cookie")] -struct MakeCookie { - #[structopt(short)] - s: String, - - #[structopt(subcommand, parse(from_occurrences))] - cmd: Command, -} - -#[derive(StructOpt, Debug)] -enum Command { - #[structopt(name = "pound")] - /// Pound acorns into flour for cookie dough. - Pound { acorns: u32 }, - - Sparkle { - #[structopt(short)] - color: String, - }, -} - -fn main() { - let opt = MakeCookie::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/subcommand_and_parse.stderr b/structopt/tests/ui/subcommand_and_parse.stderr deleted file mode 100644 index 4070056..0000000 --- a/structopt/tests/ui/subcommand_and_parse.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: parse attribute is not allowed for subcommand - --> $DIR/subcommand_and_parse.rs:17:29 - | -17 | #[structopt(subcommand, parse(from_occurrences))] - | ^^^^^ diff --git a/structopt/tests/ui/subcommand_opt_opt.rs b/structopt/tests/ui/subcommand_opt_opt.rs deleted file mode 100644 index 1dd84e5..0000000 --- a/structopt/tests/ui/subcommand_opt_opt.rs +++ /dev/null @@ -1,36 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -#[structopt(name = "make-cookie")] -struct MakeCookie { - #[structopt(short)] - s: String, - - #[structopt(subcommand)] - cmd: Option<Option<Command>>, -} - -#[derive(StructOpt, Debug)] -enum Command { - #[structopt(name = "pound")] - /// Pound acorns into flour for cookie dough. - Pound { acorns: u32 }, - - Sparkle { - #[structopt(short)] - color: String, - }, -} - -fn main() { - let opt = MakeCookie::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/subcommand_opt_opt.stderr b/structopt/tests/ui/subcommand_opt_opt.stderr deleted file mode 100644 index daad02f..0000000 --- a/structopt/tests/ui/subcommand_opt_opt.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: Option<Option<T>> type is not allowed for subcommand - --> $DIR/subcommand_opt_opt.rs:18:10 - | -18 | cmd: Option<Option<Command>>, - | ^^^^^^ diff --git a/structopt/tests/ui/subcommand_opt_vec.rs b/structopt/tests/ui/subcommand_opt_vec.rs deleted file mode 100644 index 17bffbf..0000000 --- a/structopt/tests/ui/subcommand_opt_vec.rs +++ /dev/null @@ -1,36 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -#[structopt(name = "make-cookie")] -struct MakeCookie { - #[structopt(short)] - s: String, - - #[structopt(subcommand)] - cmd: Option<Vec<Command>>, -} - -#[derive(StructOpt, Debug)] -enum Command { - #[structopt(name = "pound")] - /// Pound acorns into flour for cookie dough. - Pound { acorns: u32 }, - - Sparkle { - #[structopt(short)] - color: String, - }, -} - -fn main() { - let opt = MakeCookie::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/subcommand_opt_vec.stderr b/structopt/tests/ui/subcommand_opt_vec.stderr deleted file mode 100644 index a9833a6..0000000 --- a/structopt/tests/ui/subcommand_opt_vec.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: Option<Vec<T>> type is not allowed for subcommand - --> $DIR/subcommand_opt_vec.rs:18:10 - | -18 | cmd: Option<Vec<Command>>, - | ^^^^^^ diff --git a/structopt/tests/ui/tuple_struct.rs b/structopt/tests/ui/tuple_struct.rs deleted file mode 100644 index af9b1d5..0000000 --- a/structopt/tests/ui/tuple_struct.rs +++ /dev/null @@ -1,18 +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. - -use structopt::StructOpt; - -#[derive(StructOpt, Debug)] -#[structopt(name = "basic")] -struct Opt(u32); - -fn main() { - let opt = Opt::from_args(); - println!("{:?}", opt); -} diff --git a/structopt/tests/ui/tuple_struct.stderr b/structopt/tests/ui/tuple_struct.stderr deleted file mode 100644 index 9f2876f..0000000 --- a/structopt/tests/ui/tuple_struct.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: structopt only supports non-tuple structs and enums - --> $DIR/tuple_struct.rs:11:10 - | -11 | #[derive(StructOpt, Debug)] - | ^^^^^^^^^ diff --git a/structopt/tests/utils.rs b/structopt/tests/utils.rs deleted file mode 100644 index c0684a2..0000000 --- a/structopt/tests/utils.rs +++ /dev/null @@ -1,45 +0,0 @@ -#![allow(unused)] - -use structopt::StructOpt; - -pub fn get_help<T: StructOpt>() -> String { - let mut output = Vec::new(); - <T as StructOpt>::clap().write_help(&mut output).unwrap(); - let output = String::from_utf8(output).unwrap(); - - eprintln!("\n%%% HELP %%%:=====\n{}\n=====\n", output); - eprintln!("\n%%% HELP (DEBUG) %%%:=====\n{:?}\n=====\n", output); - - output -} - -pub fn get_long_help<T: StructOpt>() -> String { - let mut output = Vec::new(); - <T as StructOpt>::clap() - .write_long_help(&mut output) - .unwrap(); - let output = String::from_utf8(output).unwrap(); - - eprintln!("\n%%% LONG_HELP %%%:=====\n{}\n=====\n", output); - eprintln!("\n%%% LONG_HELP (DEBUG) %%%:=====\n{:?}\n=====\n", output); - - output -} - -pub fn get_subcommand_long_help<T: StructOpt>(subcmd: &str) -> String { - let output = <T as StructOpt>::clap() - .get_matches_from_safe(vec!["test", subcmd, "--help"]) - .expect_err("") - .message; - - eprintln!( - "\n%%% SUBCOMMAND `{}` HELP %%%:=====\n{}\n=====\n", - subcmd, output - ); - eprintln!( - "\n%%% SUBCOMMAND `{}` HELP (DEBUG) %%%:=====\n{:?}\n=====\n", - subcmd, output - ); - - output -} |