mirror of
https://github.com/clap-rs/clap
synced 2024-12-14 14:52:33 +00:00
allow for documentation to be placed on subcommands
This commit is contained in:
parent
3772285091
commit
91fb4a40e4
3 changed files with 65 additions and 5 deletions
40
examples/git.rs
Normal file
40
examples/git.rs
Normal file
|
@ -0,0 +1,40 @@
|
|||
//! `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 the
|
||||
//! `about` attribute.
|
||||
|
||||
extern crate structopt;
|
||||
#[macro_use] extern crate structopt_derive;
|
||||
|
||||
use structopt::StructOpt;
|
||||
|
||||
#[derive(StructOpt, Debug)]
|
||||
#[structopt(name = "git")]
|
||||
/// the stupid content tracker
|
||||
enum Opt {
|
||||
#[structopt(name = "fetch")]
|
||||
/// fetch branches from remote repository
|
||||
Fetch {
|
||||
#[structopt(long = "dry-run")]
|
||||
dry_run: bool,
|
||||
#[structopt(long = "all")]
|
||||
all: bool,
|
||||
#[structopt(default_value = "origin")]
|
||||
repository: String
|
||||
},
|
||||
#[structopt(name = "add")]
|
||||
/// add files to the staging area
|
||||
Add {
|
||||
#[structopt(short = "i")]
|
||||
interactive: bool,
|
||||
#[structopt(short = "a")]
|
||||
all: bool,
|
||||
files: Vec<String>
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let matches = Opt::from_args();
|
||||
|
||||
println!("{:?}", matches);
|
||||
}
|
|
@ -537,10 +537,14 @@ fn gen_augment_clap_enum(variants: &[Variant]) -> quote::Tokens {
|
|||
VariantData::Struct(ref fields) => gen_augmentation(fields, &app_var),
|
||||
_ => unreachable!()
|
||||
};
|
||||
let from_attr = extract_attrs(&variant.attrs, AttrSource::Struct)
|
||||
.filter(|&(ref i, _)| i != "name")
|
||||
.map(|(i, l)| quote!( .#i(#l) ));
|
||||
|
||||
quote! {
|
||||
.subcommand({
|
||||
let #app_var = _structopt::clap::SubCommand::with_name( #name );
|
||||
let #app_var = _structopt::clap::SubCommand::with_name( #name )
|
||||
#( #from_attr )* ;
|
||||
#arg_block
|
||||
})
|
||||
}
|
||||
|
@ -567,11 +571,11 @@ fn gen_from_subcommand(name: &Ident, variants: &[Variant]) -> quote::Tokens {
|
|||
let sub_name = extract_attrs(&variant.attrs, AttrSource::Struct)
|
||||
.filter_map(|attr| match attr {
|
||||
(ref i, Lit::Str(ref s, ..)) if i == "name" =>
|
||||
Some(Ident::new(s as &str)),
|
||||
Some(s.to_string()),
|
||||
_ => None
|
||||
})
|
||||
.next()
|
||||
.unwrap_or_else(|| variant.ident.clone());
|
||||
.unwrap_or_else(|| variant.ident.as_ref().to_string());
|
||||
let variant_name = &variant.ident;
|
||||
let constructor_block = match variant.data {
|
||||
VariantData::Struct(ref fields) => gen_constructor(fields),
|
||||
|
@ -579,7 +583,7 @@ fn gen_from_subcommand(name: &Ident, variants: &[Variant]) -> quote::Tokens {
|
|||
};
|
||||
|
||||
quote! {
|
||||
(stringify!(#sub_name), Some(matches)) =>
|
||||
(#sub_name, Some(matches)) =>
|
||||
Some(#name :: #variant_name #constructor_block)
|
||||
}
|
||||
});
|
||||
|
|
|
@ -12,7 +12,7 @@ use structopt::StructOpt;
|
|||
|
||||
#[derive(StructOpt, PartialEq, Debug)]
|
||||
enum Opt {
|
||||
#[structopt(name = "fetch")]
|
||||
#[structopt(name = "fetch", about = "Fetch stuff from GitHub.")]
|
||||
Fetch {
|
||||
#[structopt(long = "all")]
|
||||
all: bool,
|
||||
|
@ -55,3 +55,19 @@ fn test_no_parse() {
|
|||
let result = Opt::clap().get_matches_from_safe(&["test", "add", "--badoption"]);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[derive(StructOpt, PartialEq, Debug)]
|
||||
enum Opt2 {
|
||||
#[structopt(name = "do-something")]
|
||||
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"])));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue