Skip to content

Commit

Permalink
Merge branch 'grw/feat/display_option_with' of github.com:georgewhewe…
Browse files Browse the repository at this point in the history
…ll/tabled into patch/display-type
  • Loading branch information
zhiburt committed Jan 31, 2025
2 parents 09ce7ef + 6617927 commit d91f120
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 3 deletions.
5 changes: 5 additions & 0 deletions tabled/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ name = "derive_display_with"
path = "examples/derive/display_with.rs"
required-features = ["derive"]

[[example]]
name = "derive_display_with_option"
path = "examples/derive/display_with_option.rs"
required-features = ["derive"]

[[example]]
name = "derive_crate_override"
path = "examples/derive/crate_override.rs"
Expand Down
51 changes: 51 additions & 0 deletions tabled/examples/derive/display_with_option.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use tabled::Tabled;

#[derive(Debug)]
pub struct Country {
name: String,
capital: Option<String>,
}

fn display_option(opt: &Option<String>) -> String {
match opt {
Some(val) => val.to_uppercase(),
None => "UNKNOWN".to_string(),
}
}

#[derive(Tabled)]
#[tabled(display_option_with = "display_option")]
pub struct CountryDisplay {
name: String,
capital: Option<String>,
}

impl From<Country> for CountryDisplay {
fn from(country: Country) -> Self {
Self {
name: country.name,
capital: country.capital,
}
}
}

fn main() {
let data = vec![
Country {
name: "France".to_string(),
capital: Some("Paris".to_string()),
},
Country {
name: "Germany".to_string(),
capital: Some("Berlin".to_string()),
},
Country {
name: "Unknown".to_string(),
capital: None,
},
];

let table_data: Vec<CountryDisplay> = data.into_iter().map(Into::into).collect();
let table = tabled::Table::new(table_data);
println!("{}", table);
}
4 changes: 4 additions & 0 deletions tabled_derive/src/attributes/type_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub struct TypeAttributes {
pub inline: bool,
pub inline_value: Option<String>,
pub crate_name: Option<String>,
pub display_option_with: Option<String>,
}

impl TypeAttributes {
Expand Down Expand Up @@ -53,6 +54,9 @@ impl TypeAttributes {
TypeAttrKind::RenameAll(lit) => {
self.rename_all = Some(CasingStyle::from_lit(&lit)?);
}
TypeAttrKind::DisplayOptionWith(func) => {
self.display_option_with = Some(func.value());
}
}

Ok(())
Expand Down
27 changes: 26 additions & 1 deletion tabled_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,14 @@ fn info_from_fields(
headers.push(header);

let field_name_result = field_name(i, field);
let value = get_field_fields(&field_name_result, &attributes, fields, field_name);
let value = get_field_fields(
&field_name_result,
&field.ty,
&attributes,
fields,
field_name,
attrs,
);
values.push(value);
}

Expand Down Expand Up @@ -490,9 +497,11 @@ fn get_type_headers(

fn get_field_fields(
field: &TokenStream,
field_type: &Type,
attr: &FieldAttributes,
fields: &Fields,
field_name: FieldNameFn,
type_attrs: &TypeAttributes,
) -> TokenStream {
if attr.inline {
return quote! { #field.fields() };
Expand Down Expand Up @@ -542,9 +551,25 @@ fn get_field_fields(
return quote!(vec![::std::borrow::Cow::Owned(#call)]);
}

if is_option_type(field_type) {
if let Some(func) = &type_attrs.display_option_with {
let func = use_function(&quote!(&#field), func);
return quote!(vec![::std::borrow::Cow::from(format!("{}", #func))]);
}
}

quote!(vec![::std::borrow::Cow::Owned(format!("{}", #field))])
}

fn is_option_type(ty: &Type) -> bool {
if let Type::Path(type_path) = ty {
if let Some(segment) = type_path.path.segments.last() {
return segment.ident == "Option";
}
}
false
}

fn use_function(args: &TokenStream, function: &str) -> TokenStream {
let path: syn::Result<syn::ExprPath> = syn::parse_str(function);
match path {
Expand Down
7 changes: 5 additions & 2 deletions tabled_derive/src/parse/type_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub enum TypeAttrKind {
Inline(LitBool, Option<LitStr>),
RenameAll(LitStr),
Crate(LitStr),
DisplayOptionWith(LitStr),
}

impl Parse for TypeAttr {
Expand All @@ -52,8 +53,10 @@ impl Parse for TypeAttr {
if input.peek(LitStr) {
let lit = input.parse::<LitStr>()?;

if let "rename_all" = name_str.as_str() {
return Ok(Self::new(RenameAll(lit)));
match name_str.as_str() {
"rename_all" => return Ok(Self::new(RenameAll(lit))),
"display_option_with" => return Ok(Self::new(DisplayOptionWith(lit))),
_ => {}
}
}

Expand Down

0 comments on commit d91f120

Please sign in to comment.