diff options
author | Zhenhui Xie <xiezh0831@126.com> | 2019-09-30 20:10:35 +0800 |
---|---|---|
committer | Matan Kushner <hello@matchai.me> | 2019-09-30 21:10:35 +0900 |
commit | dd0b1a1aa2c36bf2df4db9c11a6517a018ffa100 (patch) | |
tree | e2bb1b1bc6b60cb23848af9c625d21575250ecf0 /starship_module_config_derive | |
parent | 9e9eb6a8ef87f7b93dc07e0cf068ccb1a6ce588c (diff) |
refactor: Refactoring config (#383)
This PR refactors config and puts configuration files for all modules in `configs/`.
Diffstat (limited to 'starship_module_config_derive')
-rw-r--r-- | starship_module_config_derive/Cargo.toml | 28 | ||||
-rw-r--r-- | starship_module_config_derive/src/lib.rs | 76 |
2 files changed, 104 insertions, 0 deletions
diff --git a/starship_module_config_derive/Cargo.toml b/starship_module_config_derive/Cargo.toml new file mode 100644 index 000000000..95df616ca --- /dev/null +++ b/starship_module_config_derive/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "starship_module_config_derive" +version = "0.20.0" +edition = "2018" +authors = ["Matan Kushner <hello@matchai.me>"] +homepage = "https://starship.rs" +documentation = "https://starship.rs/guide/" +repository = "https://github.com/starship/starship" +readme = "README.md" +license = "ISC" +keywords = ["prompt", "shell", "bash", "fish", "zsh"] +categories = ["command-line-utilities"] +description = """ +The cross-shell prompt for astronauts. ☄🌌️ +""" +exclude = ["docs/**/*"] + +[lib] +name = "starship_module_config_derive" +proc-macro = true + +[dependencies] +proc-macro2 = "~1" +quote = "~1" +syn = "~1" + +[dev-dependencies] +starship = { version = "0.20.0", path = "../starship" } diff --git a/starship_module_config_derive/src/lib.rs b/starship_module_config_derive/src/lib.rs new file mode 100644 index 000000000..eeddf5a8b --- /dev/null +++ b/starship_module_config_derive/src/lib.rs @@ -0,0 +1,76 @@ +extern crate proc_macro; +extern crate proc_macro2; + +use proc_macro::TokenStream; +use quote::quote; +use syn::{parse_macro_input, DeriveInput}; + +#[proc_macro_derive(ModuleConfig)] +pub fn derive_module_config(input: TokenStream) -> TokenStream { + let dinput = parse_macro_input!(input as DeriveInput); + impl_module_config(dinput) +} + +fn impl_module_config(dinput: DeriveInput) -> proc_macro::TokenStream { + let struct_ident = &dinput.ident; + let (_impl_generics, ty_generics, where_clause) = dinput.generics.split_for_impl(); + + let mut from_config = quote! {}; + let mut load_config = quote! {}; + + if let syn::Data::Struct(data) = dinput.data { + if let syn::Fields::Named(fields_named) = data.fields { + let mut load_tokens = quote! {}; + let mut from_tokens = quote! {}; + + for field in fields_named.named.iter() { + let ident = field.ident.as_ref().unwrap(); + let ty = &field.ty; + + let new_load_tokens = quote! { + if let Some(config_str) = config.get(stringify!(#ident)) { + new_module_config.#ident = new_module_config.#ident.load_config(config_str); + } + }; + let new_from_tokens = quote! { + #ident: <#ty>::from_config(config.get(stringify!(#ident))?)?, + }; + + load_tokens = quote! { + #load_tokens + #new_load_tokens + }; + from_tokens = quote! { + #from_tokens + #new_from_tokens + } + } + + load_config = quote! { + fn load_config(&self, config: &'a toml::Value) -> Self { + let mut new_module_config = self.clone(); + if let toml::Value::Table(config) = config { + #load_tokens + } + new_module_config + } + }; + from_config = quote! { + fn from_config(config: &'a toml::Value) -> Option<Self> { + let config = config.as_table()?; + + Some(#struct_ident { + #from_tokens + }) + } + }; + } + } + + TokenStream::from(quote! { + impl<'a> ModuleConfig<'a> for #struct_ident #ty_generics #where_clause { + #from_config + #load_config + } + }) +} |