Skip to content

Commit

Permalink
Merge branch 'master' of github.com:TeXitoi/structopt
Browse files Browse the repository at this point in the history
  • Loading branch information
Guillaume Pinot committed Oct 18, 2021
2 parents 6dc2963 + ddb51cb commit e83b0fc
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 49 deletions.
86 changes: 49 additions & 37 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
//!
//! First, let's look at the example:
//!
//! ```should_panic
//! ```
//! use std::path::PathBuf;
//! use structopt::StructOpt;
//!
Expand Down Expand Up @@ -95,7 +95,10 @@
//! }
//!
//! fn main() {
//! # /*
//! let opt = Opt::from_args();
//! # */
//! # let opt = Opt::from_iter(&["binary", "-o", "stdout", "input"]);
//! println!("{:?}", opt);
//! }
//! ```
Expand Down Expand Up @@ -134,13 +137,17 @@
//! 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
//! ```
//! # #[derive(structopt::StructOpt)] struct S {
//! #
//! #[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
//! )]
//! #
//! # s: () } mod path { pub(crate) mod to { pub(crate) fn parser(_: &std::ffi::OsStr) {} }}
//! ```
//!
//! `#[structopt(...)]` attributes can be placed on top of `struct`, `enum`,
Expand Down Expand Up @@ -174,11 +181,15 @@
//! They are the reason why `structopt` is so flexible. **Every and each method from
//! `clap::App/Arg` can be used this way!**
//!
//! ```ignore
//! ```
//! # #[derive(structopt::StructOpt)] struct S {
//! #
//! #[structopt(
//! global = true, // name = arg form, neat for one-arg methods
//! required_if("out", "file") // name(arg1, arg2, ...) form.
//! )]
//! #
//! # s: String }
//! ```
//!
//! The first form can only be used for methods which take only one argument.
Expand Down Expand Up @@ -435,7 +446,6 @@
//! /// for its type (in this case 0).
//! #[structopt(skip)]
//! skipped: u32,
//!
//! }
//!
//! # Opt::from_iter(
Expand All @@ -452,7 +462,7 @@
//! #[derive(StructOpt)]
//! struct Opt {
//! #[structopt(default_value = "", long)]
//! prefix: String
//! prefix: String,
//! }
//! ```
//!
Expand All @@ -474,7 +484,7 @@
//! struct Opt {
//! // just leave the `= "..."` part and structopt will figure it for you
//! #[structopt(default_value, long)]
//! prefix: String // `String` implements both `Default` and `ToString`
//! prefix: String, // `String` implements both `Default` and `ToString`
//! }
//! ```
//!
Expand All @@ -499,8 +509,8 @@
//! #[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
//! #[structopt(short, help = "Pass `-h` and you'll see me!")]
//! bar: String,
//! }
//! ```
//!
Expand All @@ -513,8 +523,8 @@
//! #[derive(StructOpt)]
//! /// I am a program and I work, just pass `-h`
//! struct Foo {
//! /// Pass `-h` and you'll see me!
//! bar: String
//! /// Pass `-h` and you'll see me!
//! bar: String,
//! }
//! ```
//!
Expand Down Expand Up @@ -555,7 +565,7 @@
//! /// until I'll have destroyed humanity. Enjoy your
//! /// pathetic existence, you mere mortals.
//! #[structopt(long)]
//! kill_all_humans: bool
//! kill_all_humans: bool,
//! }
//! ```
//!
Expand Down Expand Up @@ -632,7 +642,7 @@
//! Also, `structopt` will *still* remove leading and trailing blank lines so
//! these formats are equivalent:
//!
//! ```ignore
//! ```
//! /** This is a doc comment
//!
//! Hello! */
Expand All @@ -646,6 +656,8 @@
//! /// This is a doc comment
//! ///
//! /// Hello!
//! #
//! # mod m {}
//! ```
//! ______________
//!
Expand All @@ -665,8 +677,8 @@
//!
//! #[derive(StructOpt)]
//! struct Foo {
//! #[structopt(short, long, env = "PARAMETER_VALUE")]
//! parameter_value: String
//! #[structopt(short, long, env = "PARAMETER_VALUE")]
//! parameter_value: String,
//! }
//! ```
//!
Expand All @@ -688,8 +700,8 @@
//!
//! #[derive(StructOpt)]
//! struct Foo {
//! #[structopt(long = "secret", env = "SECRET_VALUE", hide_env_values = true)]
//! secret_value: String
//! #[structopt(long = "secret", env = "SECRET_VALUE", hide_env_values = true)]
//! secret_value: String,
//! }
//! ```
//!
Expand All @@ -707,8 +719,8 @@
//!
//! #[derive(StructOpt)]
//! struct Foo {
//! #[structopt(long = "secret", env)]
//! secret_value: String
//! #[structopt(long = "secret", env)]
//! secret_value: String,
//! }
//! ```
//!
Expand Down Expand Up @@ -774,21 +786,21 @@
//! #[structopt(short)]
//! patch: bool,
//! #[structopt(parse(from_os_str))]
//! files: Vec<PathBuf>
//! files: Vec<PathBuf>,
//! },
//! Fetch {
//! #[structopt(long)]
//! dry_run: bool,
//! #[structopt(long)]
//! all: bool,
//! repository: Option<String>
//! repository: Option<String>,
//! },
//! Commit {
//! #[structopt(short)]
//! message: Option<String>,
//! #[structopt(short)]
//! all: bool
//! }
//! all: bool,
//! },
//! }
//! ```
//!
Expand All @@ -807,22 +819,22 @@
//! 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
//! #[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
//! acorns: u32,
//! },
//! /// Add magical sparkles -- the secret ingredient!
//! Sparkle {
//! #[structopt(short, parse(from_occurrences))]
//! magicality: u64,
//! #[structopt(short)]
//! color: String
//! color: String,
//! },
//! Finish(Finish),
//! }
Expand All @@ -832,19 +844,19 @@
//! struct Finish {
//! #[structopt(short)]
//! time: u32,
//! #[structopt(subcommand)] // Note that we mark a field as a subcommand
//! finish_type: FinishType
//! #[structopt(subcommand)] // Note that we mark a field as a subcommand
//! finish_type: FinishType,
//! }
//!
//! // subsubcommand!
//! #[derive(StructOpt)]
//! enum FinishType {
//! Glaze {
//! applications: u32
//! applications: u32,
//! },
//! Powder {
//! flavor: String,
//! dips: u32
//! dips: u32,
//! }
//! }
//! ```
Expand All @@ -868,14 +880,14 @@
//! struct Foo {
//! file: String,
//! #[structopt(subcommand)]
//! cmd: Option<Command>
//! cmd: Option<Command>,
//! }
//!
//! #[derive(StructOpt)]
//! enum Command {
//! Bar,
//! Baz,
//! Quux
//! Quux,
//! }
//! ```
//!
Expand Down Expand Up @@ -953,7 +965,7 @@
//! BaseCli(BaseCli),
//! Dex {
//! arg2: i32,
//! }
//! },
//! }
//! ```
//!
Expand Down Expand Up @@ -1068,10 +1080,10 @@
//!
//! // a struct with single custom argument
//! #[derive(StructOpt)]
//! struct GenericArgs<T:FromStr> where <T as FromStr>::Err: fmt::Display + fmt::Debug {
//! struct GenericArgs<T: FromStr> where <T as FromStr>::Err: fmt::Display + fmt::Debug {
//! generic_arg_1: String,
//! generic_arg_2: String,
//! custom_arg_1: T
//! custom_arg_1: T,
//! }
//! ```
//!
Expand All @@ -1081,11 +1093,11 @@
//! # use structopt::StructOpt;
//! // a struct with multiple custom arguments in a substructure
//! #[derive(StructOpt)]
//! struct GenericArgs<T:StructOpt> {
//! struct GenericArgs<T: StructOpt> {
//! generic_arg_1: String,
//! generic_arg_2: String,
//! #[structopt(flatten)]
//! custom_args: T
//! custom_args: T,
//! }
//! ```

Expand Down
14 changes: 8 additions & 6 deletions structopt-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -520,9 +520,14 @@ fn gen_augment_clap_enum(

_ => {
let app_var = Ident::new("subcommand", Span::call_site());
let from_attrs = attrs.top_level_methods();
let version = attrs.version();

let arg_block = match variant.fields {
// If the variant is named, then gen_augmentation already generates the
// top level methods (#from_attrs) and version.
Named(ref fields) => gen_augmentation(&fields.named, &app_var, &attrs),
Unit => quote!( #app_var ),
Unit => quote!( #app_var#from_attrs#version ),
Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => {
let ty = &unnamed[0];
quote_spanned! { ty.span()=>
Expand All @@ -536,21 +541,18 @@ fn gen_augment_clap_enum(
)
} else {
#app_var
}
}#from_attrs#version
}
}
}
Unnamed(..) => abort!(variant, "non single-typed tuple enums are not supported"),
};

let name = attrs.cased_name();
let from_attrs = attrs.top_level_methods();
let version = attrs.version();
Some(quote! {
let app = app.subcommand({
let #app_var = ::structopt::clap::SubCommand::with_name(#name);
let #app_var = #arg_block;
#app_var#from_attrs#version
#arg_block
});
})
},
Expand Down
28 changes: 28 additions & 0 deletions tests/issues.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,34 @@ fn issue_359() {
);
}

#[test]
fn issue_418() {
use structopt::StructOpt;

#[derive(Debug, StructOpt)]
struct Opts {
#[structopt(subcommand)]
/// The command to run
command: Command,
}

#[derive(Debug, StructOpt)]
enum Command {
/// Reticulate the splines
#[structopt(visible_alias = "ret")]
Reticulate {
/// How many splines
num_splines: u8,
},
/// Frobnicate the rest
#[structopt(visible_alias = "frob")]
Frobnicate,
}

let help = get_long_help::<Opts>();
assert!(help.contains("Reticulate the splines [aliases: ret]"));
}

#[test]
fn issue_490() {
use std::iter::FromIterator;
Expand Down
12 changes: 6 additions & 6 deletions tests/ui/skip_without_default.stderr
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
error[E0277]: the trait bound `Kind: Default` is not satisfied
--> $DIR/skip_without_default.rs:22:17
|
22 | #[structopt(skip)]
| ^^^^ the trait `Default` is not implemented for `Kind`
|
= note: required by `std::default::Default::default`
--> $DIR/skip_without_default.rs:22:17
|
22 | #[structopt(skip)]
| ^^^^ the trait `Default` is not implemented for `Kind`
|
note: required by `std::default::Default::default`

0 comments on commit e83b0fc

Please sign in to comment.