use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};
#[proc_macro_attribute]
pub fn display(_attr: TokenStream, item: TokenStream) -> TokenStream {
let ast = parse_macro_input!(item as DeriveInput);
let name = &ast.ident;
let fields_names = match ast.data {
syn::Data::Struct(ref data_struct) => match data_struct.fields {
syn::Fields::Named(ref fields) => fields
.named
.iter()
.map(|f| f.ident.as_ref().unwrap())
.collect::<Vec<_>>(),
_ => panic!("Only named fields are supported"),
},
_ => panic!("Only structs are supported"),
};
let mut struct_def = quote! {
#ast
};
let mut dbg_impl = quote! {
impl std::fmt::Debug for #name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut s = String::new();
s.push_str(&format!("{}╭─{} {}{}{} ─────────\n", termo::GRAY, termo::RESET, termo::MAGENTA, stringify!(#name), termo::GRAY));
#(s.push_str(&format!("| {}{}{}{}: {}{:?}{}\n", termo::RESET, termo::YELLOW, stringify!(#fields_names), termo::RESET, termo::WHITE, self.#fields_names, termo::GRAY));)*
s.push_str(format!("╰────────────────────────{}\n", termo::RESET).as_str());
write!(f, "{}", s)
}
}
};
let output = quote! {
#struct_def
#dbg_impl
};
output.into()
}