diff --git a/cove-config/src/keys.rs b/cove-config/src/keys.rs index 0eed8a7..616aa2e 100644 --- a/cove-config/src/keys.rs +++ b/cove-config/src/keys.rs @@ -132,19 +132,6 @@ pub struct General { pub log: KeyBinding, } -impl Default for General { - fn default() -> Self { - Self { - exit: default::general::exit(), - abort: default::general::abort(), - confirm: default::general::confirm(), - focus: default::general::focus(), - help: default::general::help(), - log: default::general::log(), - } - } -} - #[derive(Debug, Deserialize, Document, KeyGroup)] pub struct Scroll { /// Scroll up one line. @@ -170,20 +157,6 @@ pub struct Scroll { pub center_cursor: KeyBinding, } -impl Default for Scroll { - fn default() -> Self { - Self { - up_line: default::scroll::up_line(), - down_line: default::scroll::down_line(), - up_half: default::scroll::up_half(), - down_half: default::scroll::down_half(), - up_full: default::scroll::up_full(), - down_full: default::scroll::down_full(), - center_cursor: default::scroll::center_cursor(), - } - } -} - #[derive(Debug, Deserialize, Document, KeyGroup)] pub struct Cursor { /// Move up. @@ -200,17 +173,6 @@ pub struct Cursor { pub to_bottom: KeyBinding, } -impl Default for Cursor { - fn default() -> Self { - Self { - up: default::cursor::up(), - down: default::cursor::down(), - to_top: default::cursor::to_top(), - to_bottom: default::cursor::to_bottom(), - } - } -} - #[derive(Debug, Deserialize, Document, KeyGroup)] pub struct EditorCursor { /// Move left. @@ -239,21 +201,6 @@ pub struct EditorCursor { pub down: KeyBinding, } -impl Default for EditorCursor { - fn default() -> Self { - Self { - left: default::editor_cursor::left(), - right: default::editor_cursor::right(), - left_word: default::editor_cursor::left_word(), - right_word: default::editor_cursor::right_word(), - start: default::editor_cursor::start(), - end: default::editor_cursor::end(), - up: default::editor_cursor::up(), - down: default::editor_cursor::down(), - } - } -} - #[derive(Debug, Deserialize, Document, KeyGroup)] pub struct EditorAction { /// Delete before cursor. @@ -270,17 +217,6 @@ pub struct EditorAction { pub external: KeyBinding, } -impl Default for EditorAction { - fn default() -> Self { - Self { - backspace: default::editor_action::backspace(), - delete: default::editor_action::delete(), - clear: default::editor_action::clear(), - external: default::editor_action::external(), - } - } -} - #[derive(Debug, Default, Deserialize, Document)] pub struct Editor { #[serde(default)] @@ -323,22 +259,6 @@ pub struct RoomsAction { pub change_sort_order: KeyBinding, } -impl Default for RoomsAction { - fn default() -> Self { - Self { - connect: default::rooms_action::connect(), - connect_all: default::rooms_action::connect_all(), - disconnect: default::rooms_action::disconnect(), - disconnect_all: default::rooms_action::disconnect_all(), - connect_autojoin: default::rooms_action::connect_autojoin(), - disconnect_non_autojoin: default::rooms_action::disconnect_non_autojoin(), - new: default::rooms_action::new(), - delete: default::rooms_action::delete(), - change_sort_order: default::rooms_action::change_sort_order(), - } - } -} - #[derive(Debug, Default, Deserialize, Document)] pub struct Rooms { #[serde(default)] @@ -365,18 +285,6 @@ pub struct RoomAction { pub present: KeyBinding, } -impl Default for RoomAction { - fn default() -> Self { - Self { - authenticate: default::room_action::authenticate(), - account: default::room_action::account(), - nick: default::room_action::nick(), - more_messages: default::room_action::more_messages(), - present: default::room_action::present(), - } - } -} - #[derive(Debug, Default, Deserialize, Document)] pub struct Room { #[serde(default)] @@ -413,21 +321,6 @@ pub struct TreeCursor { // TODO Bindings inspired by vim's ()/[]/{} bindings? } -impl Default for TreeCursor { - fn default() -> Self { - Self { - to_above_sibling: default::tree_cursor::to_above_sibling(), - to_below_sibling: default::tree_cursor::to_below_sibling(), - to_parent: default::tree_cursor::to_parent(), - to_root: default::tree_cursor::to_root(), - to_older_message: default::tree_cursor::to_older_message(), - to_newer_message: default::tree_cursor::to_newer_message(), - to_older_unseen_message: default::tree_cursor::to_older_unseen_message(), - to_newer_unseen_message: default::tree_cursor::to_newer_unseen_message(), - } - } -} - // TODO Split up in "message", "nicklist", "room"? #[derive(Debug, Deserialize, Document, KeyGroup)] pub struct TreeAction { @@ -460,22 +353,6 @@ pub struct TreeAction { pub links: KeyBinding, } -impl Default for TreeAction { - fn default() -> Self { - Self { - reply: default::tree_action::reply(), - reply_alternate: default::tree_action::reply_alternate(), - new_thread: default::tree_action::new_thread(), - fold_tree: default::tree_action::fold_tree(), - toggle_seen: default::tree_action::toggle_seen(), - mark_visible_seen: default::tree_action::mark_visible_seen(), - mark_older_seen: default::tree_action::mark_older_seen(), - inspect: default::tree_action::info(), - links: default::tree_action::links(), - } - } -} - #[derive(Debug, Default, Deserialize, Document)] pub struct Tree { #[serde(default)] diff --git a/cove-macro/src/document.rs b/cove-macro/src/document.rs index cf75553..ddf13c8 100644 --- a/cove-macro/src/document.rs +++ b/cove-macro/src/document.rs @@ -1,14 +1,9 @@ use proc_macro2::TokenStream; use quote::quote; use syn::spanned::Spanned; -use syn::{Data, DataEnum, DataStruct, DeriveInput, ExprPath, Field, Ident, LitStr, Type}; +use syn::{Data, DataEnum, DataStruct, DeriveInput, Field, Ident, LitStr}; -use crate::util; - -enum SerdeDefault { - Default(Type), - Path(ExprPath), -} +use crate::util::{self, SerdeDefault}; #[derive(Default)] struct FieldInfo { @@ -53,17 +48,7 @@ impl FieldInfo { } // Find `#[serde(default)]` or `#[serde(default = "bla")]`. - for arg in util::attribute_arguments(field, "serde")? { - if arg.path.is_ident("default") { - if let Some(value) = arg.value { - if let Some(path) = util::into_litstr(value) { - self.serde_default = Some(SerdeDefault::Path(path.parse()?)); - } - } else { - self.serde_default = Some(SerdeDefault::Default(field.ty.clone())); - } - } - } + self.serde_default = util::serde_default(field)?; Ok(()) } @@ -102,13 +87,9 @@ fn from_struct(ident: Ident, data: DataStruct) -> syn::Result { doc.value_info.default = Some(#default.to_string()); }); } else if let Some(serde_default) = info.serde_default { - setters.push(match serde_default { - SerdeDefault::Default(ty) => quote! { - doc.value_info.default = Some(crate::doc::toml_value_as_markdown(&<#ty as Default>::default())); - }, - SerdeDefault::Path(path) => quote! { - doc.value_info.default = Some(crate::doc::toml_value_as_markdown(&#path())); - }, + let value = serde_default.value(); + setters.push(quote! { + doc.value_info.default = Some(crate::doc::toml_value_as_markdown(&#value)); }); } diff --git a/cove-macro/src/key_group.rs b/cove-macro/src/key_group.rs index 757e3f0..254f660 100644 --- a/cove-macro/src/key_group.rs +++ b/cove-macro/src/key_group.rs @@ -3,7 +3,7 @@ use quote::quote; use syn::spanned::Spanned; use syn::{Data, DeriveInput}; -use crate::util; +use crate::util::{self, bail}; fn decapitalize(s: &str) -> String { let mut chars = s.chars(); @@ -20,15 +20,26 @@ pub fn derive_impl(input: DeriveInput) -> syn::Result { }; let mut bindings = vec![]; + let mut defaults = vec![]; for field in &data.fields { if let Some(field_ident) = &field.ident { let docstring = util::docstring(field)?; let description = decapitalize(&docstring); let description = description.strip_suffix('.').unwrap_or(&description); + let default = util::serde_default(field)?; + let Some(default) = default else { + return bail(field_ident.span(), "must have serde default"); + }; + let default_value = default.value(); + bindings.push(quote! { (&self.#field_ident, #description) }); + + defaults.push(quote! { + #field_ident: #default_value, + }); } } @@ -41,5 +52,13 @@ pub fn derive_impl(input: DeriveInput) -> syn::Result { ] } } + + impl Default for #ident { + fn default() -> Self { + Self { + #( #defaults )* + } + } + } }) } diff --git a/cove-macro/src/util.rs b/cove-macro/src/util.rs index cf21159..e56174a 100644 --- a/cove-macro/src/util.rs +++ b/cove-macro/src/util.rs @@ -1,7 +1,8 @@ -use proc_macro2::Span; +use proc_macro2::{Span, TokenStream}; +use quote::quote; use syn::parse::Parse; use syn::punctuated::Punctuated; -use syn::{Expr, ExprLit, Field, Lit, LitStr, Path, Token}; +use syn::{Expr, ExprLit, ExprPath, Field, Lit, LitStr, Path, Token, Type}; pub fn bail(span: Span, message: &str) -> syn::Result { Err(syn::Error::new(span, message)) @@ -80,3 +81,37 @@ pub fn attribute_arguments(field: &Field, path: &str) -> syn::Result TokenStream { + match self { + Self::Default(ty) => quote! { + <#ty as Default>::default() + }, + Self::Path(path) => quote! { + #path() + }, + } + } +} + +/// Find `#[serde(default)]` or `#[serde(default = "bla")]`. +pub fn serde_default(field: &Field) -> syn::Result> { + for arg in attribute_arguments(field, "serde")? { + if arg.path.is_ident("default") { + if let Some(value) = arg.value { + if let Some(path) = into_litstr(value) { + return Ok(Some(SerdeDefault::Path(path.parse()?))); + } + } else { + return Ok(Some(SerdeDefault::Default(field.ty.clone()))); + } + } + } + Ok(None) +}