Skip to content

Commit e83b0fc

Browse files
author
Guillaume Pinot
committed
Merge branch 'master' of github.com:TeXitoi/structopt
2 parents 6dc2963 + ddb51cb commit e83b0fc

File tree

4 files changed

+91
-49
lines changed

4 files changed

+91
-49
lines changed

src/lib.rs

Lines changed: 49 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
//!
6161
//! First, let's look at the example:
6262
//!
63-
//! ```should_panic
63+
//! ```
6464
//! use std::path::PathBuf;
6565
//! use structopt::StructOpt;
6666
//!
@@ -95,7 +95,10 @@
9595
//! }
9696
//!
9797
//! fn main() {
98+
//! # /*
9899
//! let opt = Opt::from_args();
100+
//! # */
101+
//! # let opt = Opt::from_iter(&["binary", "-o", "stdout", "input"]);
99102
//! println!("{:?}", opt);
100103
//! }
101104
//! ```
@@ -134,13 +137,17 @@
134137
//! They are what used to be explicit `#[structopt(raw(...))]` attrs in pre-0.3 `structopt`
135138
//!
136139
//! Every `structopt attribute` looks like comma-separated sequence of methods:
137-
//! ```rust,ignore
140+
//! ```
141+
//! # #[derive(structopt::StructOpt)] struct S {
142+
//! #
138143
//! #[structopt(
139144
//! short, // method with no arguments - always magical
140145
//! long = "--long-option", // method with one argument
141146
//! required_if("out", "file"), // method with one and more args
142147
//! parse(from_os_str = path::to::parser) // some magical methods have their own syntax
143148
//! )]
149+
//! #
150+
//! # s: () } mod path { pub(crate) mod to { pub(crate) fn parser(_: &std::ffi::OsStr) {} }}
144151
//! ```
145152
//!
146153
//! `#[structopt(...)]` attributes can be placed on top of `struct`, `enum`,
@@ -174,11 +181,15 @@
174181
//! They are the reason why `structopt` is so flexible. **Every and each method from
175182
//! `clap::App/Arg` can be used this way!**
176183
//!
177-
//! ```ignore
184+
//! ```
185+
//! # #[derive(structopt::StructOpt)] struct S {
186+
//! #
178187
//! #[structopt(
179188
//! global = true, // name = arg form, neat for one-arg methods
180189
//! required_if("out", "file") // name(arg1, arg2, ...) form.
181190
//! )]
191+
//! #
192+
//! # s: String }
182193
//! ```
183194
//!
184195
//! The first form can only be used for methods which take only one argument.
@@ -435,7 +446,6 @@
435446
//! /// for its type (in this case 0).
436447
//! #[structopt(skip)]
437448
//! skipped: u32,
438-
//!
439449
//! }
440450
//!
441451
//! # Opt::from_iter(
@@ -452,7 +462,7 @@
452462
//! #[derive(StructOpt)]
453463
//! struct Opt {
454464
//! #[structopt(default_value = "", long)]
455-
//! prefix: String
465+
//! prefix: String,
456466
//! }
457467
//! ```
458468
//!
@@ -474,7 +484,7 @@
474484
//! struct Opt {
475485
//! // just leave the `= "..."` part and structopt will figure it for you
476486
//! #[structopt(default_value, long)]
477-
//! prefix: String // `String` implements both `Default` and `ToString`
487+
//! prefix: String, // `String` implements both `Default` and `ToString`
478488
//! }
479489
//! ```
480490
//!
@@ -499,8 +509,8 @@
499509
//! #[derive(StructOpt)]
500510
//! #[structopt(about = "I am a program and I work, just pass `-h`")]
501511
//! struct Foo {
502-
//! #[structopt(short, help = "Pass `-h` and you'll see me!")]
503-
//! bar: String
512+
//! #[structopt(short, help = "Pass `-h` and you'll see me!")]
513+
//! bar: String,
504514
//! }
505515
//! ```
506516
//!
@@ -513,8 +523,8 @@
513523
//! #[derive(StructOpt)]
514524
//! /// I am a program and I work, just pass `-h`
515525
//! struct Foo {
516-
//! /// Pass `-h` and you'll see me!
517-
//! bar: String
526+
//! /// Pass `-h` and you'll see me!
527+
//! bar: String,
518528
//! }
519529
//! ```
520530
//!
@@ -555,7 +565,7 @@
555565
//! /// until I'll have destroyed humanity. Enjoy your
556566
//! /// pathetic existence, you mere mortals.
557567
//! #[structopt(long)]
558-
//! kill_all_humans: bool
568+
//! kill_all_humans: bool,
559569
//! }
560570
//! ```
561571
//!
@@ -632,7 +642,7 @@
632642
//! Also, `structopt` will *still* remove leading and trailing blank lines so
633643
//! these formats are equivalent:
634644
//!
635-
//! ```ignore
645+
//! ```
636646
//! /** This is a doc comment
637647
//!
638648
//! Hello! */
@@ -646,6 +656,8 @@
646656
//! /// This is a doc comment
647657
//! ///
648658
//! /// Hello!
659+
//! #
660+
//! # mod m {}
649661
//! ```
650662
//! ______________
651663
//!
@@ -665,8 +677,8 @@
665677
//!
666678
//! #[derive(StructOpt)]
667679
//! struct Foo {
668-
//! #[structopt(short, long, env = "PARAMETER_VALUE")]
669-
//! parameter_value: String
680+
//! #[structopt(short, long, env = "PARAMETER_VALUE")]
681+
//! parameter_value: String,
670682
//! }
671683
//! ```
672684
//!
@@ -688,8 +700,8 @@
688700
//!
689701
//! #[derive(StructOpt)]
690702
//! struct Foo {
691-
//! #[structopt(long = "secret", env = "SECRET_VALUE", hide_env_values = true)]
692-
//! secret_value: String
703+
//! #[structopt(long = "secret", env = "SECRET_VALUE", hide_env_values = true)]
704+
//! secret_value: String,
693705
//! }
694706
//! ```
695707
//!
@@ -707,8 +719,8 @@
707719
//!
708720
//! #[derive(StructOpt)]
709721
//! struct Foo {
710-
//! #[structopt(long = "secret", env)]
711-
//! secret_value: String
722+
//! #[structopt(long = "secret", env)]
723+
//! secret_value: String,
712724
//! }
713725
//! ```
714726
//!
@@ -774,21 +786,21 @@
774786
//! #[structopt(short)]
775787
//! patch: bool,
776788
//! #[structopt(parse(from_os_str))]
777-
//! files: Vec<PathBuf>
789+
//! files: Vec<PathBuf>,
778790
//! },
779791
//! Fetch {
780792
//! #[structopt(long)]
781793
//! dry_run: bool,
782794
//! #[structopt(long)]
783795
//! all: bool,
784-
//! repository: Option<String>
796+
//! repository: Option<String>,
785797
//! },
786798
//! Commit {
787799
//! #[structopt(short)]
788800
//! message: Option<String>,
789801
//! #[structopt(short)]
790-
//! all: bool
791-
//! }
802+
//! all: bool,
803+
//! },
792804
//! }
793805
//! ```
794806
//!
@@ -807,22 +819,22 @@
807819
//! supervising_faerie: String,
808820
//! /// The faerie tree this cookie is being made in.
809821
//! tree: Option<String>,
810-
//! #[structopt(subcommand)] // Note that we mark a field as a subcommand
811-
//! cmd: Command
822+
//! #[structopt(subcommand)] // Note that we mark a field as a subcommand
823+
//! cmd: Command,
812824
//! }
813825
//!
814826
//! #[derive(StructOpt)]
815827
//! enum Command {
816828
//! /// Pound acorns into flour for cookie dough.
817829
//! Pound {
818-
//! acorns: u32
830+
//! acorns: u32,
819831
//! },
820832
//! /// Add magical sparkles -- the secret ingredient!
821833
//! Sparkle {
822834
//! #[structopt(short, parse(from_occurrences))]
823835
//! magicality: u64,
824836
//! #[structopt(short)]
825-
//! color: String
837+
//! color: String,
826838
//! },
827839
//! Finish(Finish),
828840
//! }
@@ -832,19 +844,19 @@
832844
//! struct Finish {
833845
//! #[structopt(short)]
834846
//! time: u32,
835-
//! #[structopt(subcommand)] // Note that we mark a field as a subcommand
836-
//! finish_type: FinishType
847+
//! #[structopt(subcommand)] // Note that we mark a field as a subcommand
848+
//! finish_type: FinishType,
837849
//! }
838850
//!
839851
//! // subsubcommand!
840852
//! #[derive(StructOpt)]
841853
//! enum FinishType {
842854
//! Glaze {
843-
//! applications: u32
855+
//! applications: u32,
844856
//! },
845857
//! Powder {
846858
//! flavor: String,
847-
//! dips: u32
859+
//! dips: u32,
848860
//! }
849861
//! }
850862
//! ```
@@ -868,14 +880,14 @@
868880
//! struct Foo {
869881
//! file: String,
870882
//! #[structopt(subcommand)]
871-
//! cmd: Option<Command>
883+
//! cmd: Option<Command>,
872884
//! }
873885
//!
874886
//! #[derive(StructOpt)]
875887
//! enum Command {
876888
//! Bar,
877889
//! Baz,
878-
//! Quux
890+
//! Quux,
879891
//! }
880892
//! ```
881893
//!
@@ -953,7 +965,7 @@
953965
//! BaseCli(BaseCli),
954966
//! Dex {
955967
//! arg2: i32,
956-
//! }
968+
//! },
957969
//! }
958970
//! ```
959971
//!
@@ -1068,10 +1080,10 @@
10681080
//!
10691081
//! // a struct with single custom argument
10701082
//! #[derive(StructOpt)]
1071-
//! struct GenericArgs<T:FromStr> where <T as FromStr>::Err: fmt::Display + fmt::Debug {
1083+
//! struct GenericArgs<T: FromStr> where <T as FromStr>::Err: fmt::Display + fmt::Debug {
10721084
//! generic_arg_1: String,
10731085
//! generic_arg_2: String,
1074-
//! custom_arg_1: T
1086+
//! custom_arg_1: T,
10751087
//! }
10761088
//! ```
10771089
//!
@@ -1081,11 +1093,11 @@
10811093
//! # use structopt::StructOpt;
10821094
//! // a struct with multiple custom arguments in a substructure
10831095
//! #[derive(StructOpt)]
1084-
//! struct GenericArgs<T:StructOpt> {
1096+
//! struct GenericArgs<T: StructOpt> {
10851097
//! generic_arg_1: String,
10861098
//! generic_arg_2: String,
10871099
//! #[structopt(flatten)]
1088-
//! custom_args: T
1100+
//! custom_args: T,
10891101
//! }
10901102
//! ```
10911103

structopt-derive/src/lib.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -520,9 +520,14 @@ fn gen_augment_clap_enum(
520520

521521
_ => {
522522
let app_var = Ident::new("subcommand", Span::call_site());
523+
let from_attrs = attrs.top_level_methods();
524+
let version = attrs.version();
525+
523526
let arg_block = match variant.fields {
527+
// If the variant is named, then gen_augmentation already generates the
528+
// top level methods (#from_attrs) and version.
524529
Named(ref fields) => gen_augmentation(&fields.named, &app_var, &attrs),
525-
Unit => quote!( #app_var ),
530+
Unit => quote!( #app_var#from_attrs#version ),
526531
Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => {
527532
let ty = &unnamed[0];
528533
quote_spanned! { ty.span()=>
@@ -536,21 +541,18 @@ fn gen_augment_clap_enum(
536541
)
537542
} else {
538543
#app_var
539-
}
544+
}#from_attrs#version
540545
}
541546
}
542547
}
543548
Unnamed(..) => abort!(variant, "non single-typed tuple enums are not supported"),
544549
};
545550

546551
let name = attrs.cased_name();
547-
let from_attrs = attrs.top_level_methods();
548-
let version = attrs.version();
549552
Some(quote! {
550553
let app = app.subcommand({
551554
let #app_var = ::structopt::clap::SubCommand::with_name(#name);
552-
let #app_var = #arg_block;
553-
#app_var#from_attrs#version
555+
#arg_block
554556
});
555557
})
556558
},

tests/issues.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,34 @@ fn issue_359() {
116116
);
117117
}
118118

119+
#[test]
120+
fn issue_418() {
121+
use structopt::StructOpt;
122+
123+
#[derive(Debug, StructOpt)]
124+
struct Opts {
125+
#[structopt(subcommand)]
126+
/// The command to run
127+
command: Command,
128+
}
129+
130+
#[derive(Debug, StructOpt)]
131+
enum Command {
132+
/// Reticulate the splines
133+
#[structopt(visible_alias = "ret")]
134+
Reticulate {
135+
/// How many splines
136+
num_splines: u8,
137+
},
138+
/// Frobnicate the rest
139+
#[structopt(visible_alias = "frob")]
140+
Frobnicate,
141+
}
142+
143+
let help = get_long_help::<Opts>();
144+
assert!(help.contains("Reticulate the splines [aliases: ret]"));
145+
}
146+
119147
#[test]
120148
fn issue_490() {
121149
use std::iter::FromIterator;
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
error[E0277]: the trait bound `Kind: Default` is not satisfied
2-
--> $DIR/skip_without_default.rs:22:17
3-
|
4-
22 | #[structopt(skip)]
5-
| ^^^^ the trait `Default` is not implemented for `Kind`
6-
|
7-
= note: required by `std::default::Default::default`
2+
--> $DIR/skip_without_default.rs:22:17
3+
|
4+
22 | #[structopt(skip)]
5+
| ^^^^ the trait `Default` is not implemented for `Kind`
6+
|
7+
note: required by `std::default::Default::default`

0 commit comments

Comments
 (0)