use darling::FromVariant;
use syn::LitInt;
use super::prelude::*;
#[derive(Debug, FromDeriveInput)]
#[darling(attributes(), supports(enum_unit))]
struct Actions {
ident: Ident,
data: ast::Data<Opt, ()>,
}
#[derive(Debug, FromVariant)]
#[darling(attributes())]
struct Opt {
ident: Ident,
}
fn a(p: Actions) -> Result<TokenStream, String> {
let i = &p.ident;
let f: Vec<_> = p.data.take_enum().ok_or(format!("Expected an enum."))?;
let names_base: Vec<_> = f
.iter()
.map(|e| {
let k = LitStr::new(e.ident.to_string().to_case(Case::Snake).as_str(), i.span());
let x = &e.ident;
(k, x)
})
.collect();
let names: Vec<_> = names_base
.iter()
.map(|(k, x)| {
quote! { #i::#x => #k }
})
.collect();
let str_names: Vec<_> = names_base
.iter()
.map(|(k, _)| {
quote! { #k }
})
.collect();
let str2names: Vec<_> = names_base
.iter()
.map(|(k, x)| {
quote! { #k => Some(#i::#x) }
})
.collect();
let c = LitInt::new(format!("{}", names.len()).as_str(), i.span());
let names2: Vec<_> = f
.iter()
.map(|e| {
let x = &e.ident;
quote! { #i::#x }
})
.collect();
Ok(quote! {
impl Actions for #i {
fn get(prompt: &str, starting_input: Option<&str>) -> Result<Self, MyErr>{
const V: [#i; #c] = [ #( #names2, )* ];
Ok(V[select_line(prompt, &V, |e| [e.to_string()]).with_starting_filter_input(starting_input.unwrap_or("")).prompt()?.index].to_owned())
}
fn list() -> &'static [&'static str] {
const V: [&str; #c] = [ #( #str_names, )* ];
&V
}
fn parse(s: &str) -> Option<Self> {
match s {
#( #str2names, )*
_ => None,
}
}
}
impl ToString for #i {
fn to_string(&self) -> String {
format!("{}", match &self {
#( #names, )*
})
}
}
}
.into())
}
pub fn f(i: TokenStream) -> TokenStream {
let p = match Actions::from_derive_input(&parse_macro_input!(i as DeriveInput)) {
Ok(p) => p,
Err(e) => return e.write_errors().into(),
};
match a(p) {
Ok(p) => p,
Err(e) => Error::custom(e).write_errors().into(),
}
}