use attributes

This commit is contained in:
Guillaume Pinot 2017-02-05 02:06:39 +01:00
parent 36b39727b1
commit 1196571909
2 changed files with 28 additions and 5 deletions

View file

@ -15,10 +15,17 @@ use structopt::StructOpt;
#[derive(StructOpt, Debug)]
struct Opt {
#[structopt(short = "d", long = "debug", help = "Activate debug mode")]
debug: bool,
#[structopt(short = "v", long = "verbose", help = "Verbose mode")]
verbose: u64,
#[structopt(short = "s", long = "speed", help = "Set speed")]
speed: Option<f64>,
#[structopt(short = "o", long = "output", help = "Output file")]
output: String,
#[structopt(short = "l",
long = "level",
help = "admin_level to consider")]
level: Vec<String>,
}

View file

@ -12,7 +12,7 @@ extern crate quote;
use proc_macro::TokenStream;
#[proc_macro_derive(StructOpt)]
#[proc_macro_derive(StructOpt, attributes(structopt))]
pub fn structopt(input: TokenStream) -> TokenStream {
let s = input.to_string();
let ast = syn::parse_derive_input(&s).unwrap();
@ -42,8 +42,8 @@ fn ty(t: &syn::Ty) -> Ty {
}
}
fn impl_structopt(ast: &syn::MacroInput) -> quote::Tokens {
use syn::{Body, VariantData};
fn impl_structopt(ast: &syn::DeriveInput) -> quote::Tokens {
use syn::{Body, VariantData, MetaItem, NestedMetaItem};
let name = &ast.ident;
let s = if let Body::Struct(VariantData::Struct(ref s)) = ast.body {
s
@ -68,6 +68,7 @@ fn impl_structopt(ast: &syn::MacroInput) -> quote::Tokens {
.multiple(false)
},
Ty::Vec => quote! {
.use_delimiter(true)
.takes_value(true)
.multiple(true)
},
@ -77,10 +78,25 @@ fn impl_structopt(ast: &syn::MacroInput) -> quote::Tokens {
.required(true)
},
};
let from_attr = f.attrs.iter()
.filter_map(|attr| {
if let MetaItem::List(ref i, ref v) = attr.value {
if i.as_ref() == "structopt" {
return Some(v)
}
}
None
}).flat_map(|v| v.iter().filter_map(|mi| {
if let NestedMetaItem::MetaItem(MetaItem::NameValue(ref i, ref l)) = *mi {
Some(quote!(.#i(#l)))
} else {
None
}
}));
quote! {
.arg(Arg::with_name(stringify!(#ident))
.long(stringify!(#ident))
#modifier)
#modifier
#(#from_attr)*)
}
});
let fields = s.iter().map(|f| {