mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-04-25 01:58:51 +02:00
feat(ahk): add cmd to generate helper lib
Woke up today and thought this would be a cool way to learn more about deriving functionality with proc macros. Hopefully having this wrapper/helper library will make first time configuration for new users easier.
This commit is contained in:
100
derive-ahk/src/lib.rs
Normal file
100
derive-ahk/src/lib.rs
Normal file
@@ -0,0 +1,100 @@
|
||||
#![warn(clippy::all, clippy::nursery, clippy::pedantic)]
|
||||
#![allow(clippy::missing_errors_doc)]
|
||||
|
||||
use std::stringify;
|
||||
|
||||
use quote::quote;
|
||||
use syn::parse_macro_input;
|
||||
use syn::Data;
|
||||
use syn::DataEnum;
|
||||
use syn::DeriveInput;
|
||||
use syn::Fields;
|
||||
use syn::FieldsNamed;
|
||||
use syn::FieldsUnnamed;
|
||||
|
||||
#[proc_macro_derive(Ahk)]
|
||||
pub fn ahk(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let input = parse_macro_input!(input as DeriveInput);
|
||||
let name = input.ident;
|
||||
|
||||
match input.data {
|
||||
Data::Struct(s) => match s.fields {
|
||||
Fields::Named(FieldsNamed { named, .. }) => {
|
||||
let idents = named.iter().map(|f| &f.ident);
|
||||
let arguments = format!("{}", quote! {#(#idents), *});
|
||||
|
||||
let idents = named.iter().map(|f| &f.ident);
|
||||
let called_arguments = format!("{}", quote! {#(%#idents%) *})
|
||||
.replace(" %", "%")
|
||||
.replace("% ", "%")
|
||||
.replace("%%", "% %");
|
||||
|
||||
quote! {
|
||||
impl #name {
|
||||
fn ahk_function() -> String {
|
||||
format!(r#"
|
||||
{}({}) {{
|
||||
Run, komorebic.exe {} {}, , Hide
|
||||
}}"#,
|
||||
stringify!(#name),
|
||||
#arguments,
|
||||
stringify!(#name).to_kebab_case(),
|
||||
#called_arguments
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => unreachable!("only to be used on structs with named fields"),
|
||||
},
|
||||
Data::Enum(DataEnum { variants, .. }) => {
|
||||
let enums = variants.iter().filter(|&v| {
|
||||
matches!(v.fields, Fields::Unit) || matches!(v.fields, Fields::Unnamed(..))
|
||||
});
|
||||
|
||||
let mut stream = proc_macro2::TokenStream::new();
|
||||
|
||||
for variant in enums.clone() {
|
||||
match &variant.fields {
|
||||
Fields::Unnamed(FieldsUnnamed { unnamed, .. }) => {
|
||||
for field in unnamed {
|
||||
stream.extend(quote! {
|
||||
v.push(#field::ahk_function());
|
||||
});
|
||||
}
|
||||
}
|
||||
Fields::Unit => {
|
||||
let name = &variant.ident;
|
||||
stream.extend(quote! {
|
||||
v.push(format!(r#"
|
||||
{}() {{
|
||||
Run, komorebic.exe {}, , Hide
|
||||
}}"#,
|
||||
stringify!(#name),
|
||||
stringify!(#name).to_kebab_case()
|
||||
));
|
||||
});
|
||||
}
|
||||
Fields::Named(_) => {
|
||||
unreachable!("only to be used with unnamed and unit fields");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
quote! {
|
||||
impl #name {
|
||||
fn ahk_functions() -> Vec<String> {
|
||||
let mut v: Vec<String> = vec![];
|
||||
v.push(String::from("; Generated by komorebic.exe ahk-lib"));
|
||||
|
||||
#stream
|
||||
|
||||
v
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Data::Union(_) => unreachable!("only to be used on enums and structs"),
|
||||
}
|
||||
.into()
|
||||
}
|
||||
Reference in New Issue
Block a user