Open
Description
I thought to implement something to make pretty table smarter adding a proc_macro and a macro. Below an initial version of code:
lib.rs
extern crate proc_macro;
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, ItemStruct};
#[proc_macro_derive(TableElem)]
pub fn derive_table_elem(input: TokenStream) -> TokenStream {
let parsed_input = parse_macro_input!(input as ItemStruct);
let struct_name = &parsed_input.ident;
let field = &parsed_input.fields;
// Get struct field name
let f_name_str: Vec<String> = field
.iter()
.map(|f| f.ident.clone().unwrap().to_string())
.collect();
let f_name: Vec<syn::Ident> = field.iter().map(|f| f.ident.clone().unwrap()).collect();
TokenStream::from(quote! {
pub trait TableElem {
fn get_field_name(&self) -> Vec<&'static str>;
fn get_field(self) -> Vec<String>;
}
impl TableElem for #struct_name {
fn get_field_name(&self) -> Vec<&'static str> {
vec![#(#f_name_str),*]
}
fn get_field(self) -> Vec<String> {
vec![#(self.#f_name.into()),*]
}
}
})
}
main.rs
use macros::TableElem;
use prettytable::{format, Cell, Row, Table};
#[derive(TableElem)]
struct NameStruct {
name: String,
surname: String,
}
fn construct_table<T: TableElem>(v: Vec<T>) -> Table {
// Create the table
let mut table = Table::new();
table.set_titles(Row::new(
v.first()
.unwrap()
.get_field_name()
.iter()
.map(|f| Cell::new(f))
.collect(),
));
table.set_format(*format::consts::FORMAT_NO_LINESEP_WITH_TITLE);
v.into_iter().for_each(|r| {
table.add_row(Row::new(
r.get_field().iter().map(|elem| Cell::new(elem)).collect(),
));
});
table
}
macro_rules! print_as_table {
($v: ident) => {
construct_table($v).printstd();
};
}
fn main() {
let t: Vec<NameStruct> = vec![
NameStruct {
name: "name_1".to_string(),
surname: "surname_1".to_string(),
},
NameStruct {
name: "name_2".to_string(),
surname: "surname_2".to_string(),
},
];
print_as_table!(t);
}
Of course the previous code can be improved but I prefer get a feedback before make a pull request.