mirror of https://github.com/sgoudham/neovide.git
Settings derive macro (#439)
* Added procedural macro crate * Initial derive macro implementation * Compiles for cursor settings * Derive macro working correctly * Derive macro working for all settings structs * Cleanup * Moved the binary back to the project root * remove unused utils file Co-authored-by: Tim Harding <Tim@TimHarding.co>macos-click-through
parent
33f6a4b914
commit
af93c54f3e
@ -0,0 +1,11 @@
|
|||||||
|
[package]
|
||||||
|
name = "neovide-derive"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
syn = "1.0"
|
||||||
|
quote = "1.0"
|
@ -0,0 +1,77 @@
|
|||||||
|
use proc_macro::TokenStream;
|
||||||
|
use quote::quote;
|
||||||
|
use syn::{parse_macro_input, Attribute, Data, DataStruct, DeriveInput, Error, Ident, Lit, Meta};
|
||||||
|
|
||||||
|
#[proc_macro_derive(SettingGroup, attributes(setting_prefix))]
|
||||||
|
pub fn setting_group(item: TokenStream) -> TokenStream {
|
||||||
|
let input = parse_macro_input!(item as DeriveInput);
|
||||||
|
let prefix = setting_prefix(input.attrs.as_ref())
|
||||||
|
.map(|p| format!("{}_", p))
|
||||||
|
.unwrap_or("".to_string());
|
||||||
|
stream(input, prefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stream(input: DeriveInput, prefix: String) -> TokenStream {
|
||||||
|
const ERR_MSG: &'static str = "Derive macro expects a struct";
|
||||||
|
match input.data {
|
||||||
|
Data::Struct(ref data) => struct_stream(input.ident, prefix, data),
|
||||||
|
Data::Enum(data) => Error::new_spanned(data.enum_token, ERR_MSG)
|
||||||
|
.to_compile_error()
|
||||||
|
.into(),
|
||||||
|
Data::Union(data) => Error::new_spanned(data.union_token, ERR_MSG)
|
||||||
|
.to_compile_error()
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn struct_stream(name: Ident, prefix: String, data: &DataStruct) -> TokenStream {
|
||||||
|
let fragments = data.fields.iter().map(|field| match field.ident {
|
||||||
|
Some(ref ident) => {
|
||||||
|
let vim_setting_name = format!("{}{}", prefix, ident);
|
||||||
|
quote! {{
|
||||||
|
fn update_func(value: rmpv::Value) {
|
||||||
|
let mut s = crate::settings::SETTINGS.get::<#name>();
|
||||||
|
s.#ident.from_value(value);
|
||||||
|
crate::settings::SETTINGS.set(&s);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reader_func() -> rmpv::Value {
|
||||||
|
let s = crate::settings::SETTINGS.get::<#name>();
|
||||||
|
s.#ident.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
crate::settings::SETTINGS.set_setting_handlers(
|
||||||
|
#vim_setting_name,
|
||||||
|
update_func,
|
||||||
|
reader_func
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
Error::new_spanned(field.colon_token, "Expected named struct fields").to_compile_error()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let expanded = quote! {
|
||||||
|
impl #name {
|
||||||
|
pub fn register() {
|
||||||
|
let s: Self = Default::default();
|
||||||
|
crate::settings::SETTINGS.set(&s);
|
||||||
|
#(#fragments)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
TokenStream::from(expanded)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setting_prefix(attrs: &[Attribute]) -> Option<String> {
|
||||||
|
for attr in attrs.iter() {
|
||||||
|
if let Ok(Meta::NameValue(name_value)) = attr.parse_meta() {
|
||||||
|
if name_value.path.is_ident("setting_prefix") {
|
||||||
|
if let Lit::Str(literal) = name_value.lit {
|
||||||
|
return Some(literal.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
@ -1,17 +1,16 @@
|
|||||||
use super::KeyboardLayout;
|
use super::KeyboardLayout;
|
||||||
use crate::{
|
use crate::settings::FromValue;
|
||||||
register_nvim_setting,
|
|
||||||
settings::{FromValue, Value, SETTINGS},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[setting_prefix = "keyboard"]
|
||||||
|
#[derive(Clone, SettingGroup)]
|
||||||
pub struct KeyboardSettings {
|
pub struct KeyboardSettings {
|
||||||
pub layout: KeyboardLayout,
|
pub layout: KeyboardLayout,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initialize_settings() {
|
impl Default for KeyboardSettings {
|
||||||
SETTINGS.set(&KeyboardSettings {
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
layout: KeyboardLayout::Qwerty,
|
layout: KeyboardLayout::Qwerty,
|
||||||
});
|
}
|
||||||
register_nvim_setting!("keyboard_layout", KeyboardSettings::layout);
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue