From 6f85995379286b583daa3bcc8c469b29b8b32f83 Mon Sep 17 00:00:00 2001 From: Joscha Date: Thu, 27 Apr 2023 20:34:46 +0200 Subject: [PATCH] Derive Document for simple enums --- cove-config/src/doc.rs | 2 +- cove-config/src/euph.rs | 18 +++--------------- cove-macro/src/document.rs | 39 +++++++++++++++++++++++++++++++------- 3 files changed, 36 insertions(+), 23 deletions(-) diff --git a/cove-config/src/doc.rs b/cove-config/src/doc.rs index da27b89..2149b77 100644 --- a/cove-config/src/doc.rs +++ b/cove-config/src/doc.rs @@ -7,7 +7,7 @@ use cove_input::KeyBinding; pub use cove_macro::Document; use serde::Serialize; -pub(crate) fn toml_value_as_markdown(value: &T) -> String { +pub fn toml_value_as_markdown(value: &T) -> String { let mut result = String::new(); value .serialize(toml::ser::ValueSerializer::new(&mut result)) diff --git a/cove-config/src/euph.rs b/cove-config/src/euph.rs index d2fa84a..0584933 100644 --- a/cove-config/src/euph.rs +++ b/cove-config/src/euph.rs @@ -1,10 +1,10 @@ use std::collections::HashMap; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; -use crate::doc::{Doc, Document}; +use crate::doc::Document; -#[derive(Debug, Clone, Copy, Default, Deserialize)] +#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, Document)] #[serde(rename_all = "snake_case")] pub enum RoomsSortOrder { #[default] @@ -12,18 +12,6 @@ pub enum RoomsSortOrder { Importance, } -impl Document for RoomsSortOrder { - fn doc() -> Doc { - let mut doc = String::doc(); - doc.value_info.values = Some(vec![ - // TODO Generate by serializing - "`alphabet`".to_string(), - "`importance`".to_string(), - ]); - doc - } -} - // TODO Mark favourite rooms via printable ascii characters #[derive(Debug, Clone, Default, Deserialize, Document)] pub struct EuphRoom { diff --git a/cove-macro/src/document.rs b/cove-macro/src/document.rs index e6845d2..75a0cfc 100644 --- a/cove-macro/src/document.rs +++ b/cove-macro/src/document.rs @@ -1,7 +1,7 @@ use proc_macro2::TokenStream; use quote::quote; use syn::spanned::Spanned; -use syn::{Data, DeriveInput, ExprPath, Field, LitStr, Type}; +use syn::{Data, DataEnum, DataStruct, DeriveInput, ExprPath, Field, Ident, LitStr, Type}; use crate::util::{self, docstring}; @@ -75,11 +75,7 @@ impl FieldInfo { } } -pub fn derive_impl(input: DeriveInput) -> syn::Result { - let Data::Struct(data) = input.data else { - return Err(syn::Error::new(input.span(), "must be a struct")); - }; - +fn from_struct(ident: Ident, data: DataStruct) -> syn::Result { let mut fields = vec![]; for field in data.fields { let Some(ident) = field.ident.as_ref() else { @@ -129,7 +125,6 @@ pub fn derive_impl(input: DeriveInput) -> syn::Result { }); } - let ident = input.ident; let tokens = quote!( impl crate::doc::Document for #ident { fn doc() -> crate::doc::Doc { @@ -145,3 +140,33 @@ pub fn derive_impl(input: DeriveInput) -> syn::Result { Ok(tokens) } + +fn from_enum(ident: Ident, data: DataEnum) -> syn::Result { + let mut values = vec![]; + for variant in data.variants { + let ident = variant.ident; + values.push(quote! { + crate::doc::toml_value_as_markdown(&Self::#ident) + }); + } + + let tokens = quote!( + impl crate::doc::Document for #ident { + fn doc() -> crate::doc::Doc { + let mut doc = ::doc(); + doc.value_info.values = Some(vec![ #( #values ),* ]); + doc + } + } + ); + + Ok(tokens) +} + +pub fn derive_impl(input: DeriveInput) -> syn::Result { + match input.data { + Data::Struct(data) => from_struct(input.ident, data), + Data::Enum(data) => from_enum(input.ident, data), + Data::Union(_) => util::bail(input.span(), "must be an enum or a struct"), + } +}