Add settings_ui(group) attribute to macro
Co-authored-by: Ben Kunkle <ben@zed.dev>
This commit is contained in:
parent
15f634f8cc
commit
ba9d109289
4 changed files with 55 additions and 8 deletions
|
@ -5,7 +5,7 @@ use git::GitHostingProviderRegistry;
|
||||||
use gpui::App;
|
use gpui::App;
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use settings::{SettingsUI, Settings, SettingsStore};
|
use settings::{Settings, SettingsStore, SettingsUI};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use util::ResultExt as _;
|
use util::ResultExt as _;
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,13 @@ pub(crate) fn derive_action(input: TokenStream) -> TokenStream {
|
||||||
let mut deprecated = None;
|
let mut deprecated = None;
|
||||||
let mut doc_str: Option<String> = None;
|
let mut doc_str: Option<String> = None;
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* #[action()]
|
||||||
|
* Struct Foo {
|
||||||
|
* bar: bool // is bar considered an attribute
|
||||||
|
}
|
||||||
|
*/
|
||||||
for attr in &input.attrs {
|
for attr in &input.attrs {
|
||||||
if attr.path().is_ident("action") {
|
if attr.path().is_ident("action") {
|
||||||
attr.parse_nested_meta(|meta| {
|
attr.parse_nested_meta(|meta| {
|
||||||
|
|
|
@ -11,14 +11,20 @@ pub trait SettingsUI {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SettingsUIItem {
|
pub struct SettingsUIItem {
|
||||||
// TODO:
|
// TODO: move this back here once there isn't a None variant
|
||||||
// path: SmallVec<[&'static str; 8]>,
|
// pub path: &'static str,
|
||||||
pub item: SettingsUIItemVariant,
|
pub item: SettingsUIItemVariant,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum SettingsUIItemVariant {
|
pub enum SettingsUIItemVariant {
|
||||||
Group(SettingsUIItemGroup),
|
Group {
|
||||||
Item(SettingsUIItemSingle),
|
path: &'static str,
|
||||||
|
group: SettingsUIItemGroup,
|
||||||
|
},
|
||||||
|
Item {
|
||||||
|
path: &'static str,
|
||||||
|
item: SettingsUIItemSingle,
|
||||||
|
},
|
||||||
// TODO: remove
|
// TODO: remove
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::{DeriveInput, parse_macro_input};
|
use syn::{DeriveInput, LitStr, Token, parse_macro_input};
|
||||||
|
|
||||||
/// Derive macro for the `SettingsUI` marker trait.
|
/// Derive macro for the `SettingsUI` marker trait.
|
||||||
///
|
///
|
||||||
|
@ -15,12 +15,13 @@ use syn::{DeriveInput, parse_macro_input};
|
||||||
/// use settings_ui_macros::SettingsUI;
|
/// use settings_ui_macros::SettingsUI;
|
||||||
///
|
///
|
||||||
/// #[derive(SettingsUI)]
|
/// #[derive(SettingsUI)]
|
||||||
|
/// #[settings_ui(group = "Standard")]
|
||||||
/// struct MySettings {
|
/// struct MySettings {
|
||||||
/// enabled: bool,
|
/// enabled: bool,
|
||||||
/// count: usize,
|
/// count: usize,
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[proc_macro_derive(SettingsUI)]
|
#[proc_macro_derive(SettingsUI, attributes(settings_ui))]
|
||||||
pub fn derive_settings_ui(input: TokenStream) -> TokenStream {
|
pub fn derive_settings_ui(input: TokenStream) -> TokenStream {
|
||||||
let input = parse_macro_input!(input as DeriveInput);
|
let input = parse_macro_input!(input as DeriveInput);
|
||||||
let name = &input.ident;
|
let name = &input.ident;
|
||||||
|
@ -28,8 +29,41 @@ pub fn derive_settings_ui(input: TokenStream) -> TokenStream {
|
||||||
// Handle generic parameters if present
|
// Handle generic parameters if present
|
||||||
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
|
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
|
||||||
|
|
||||||
|
let mut group_name = Option::<String>::None;
|
||||||
|
|
||||||
|
for attr in &input.attrs {
|
||||||
|
if attr.path().is_ident("settings_ui") {
|
||||||
|
attr.parse_nested_meta(|meta| {
|
||||||
|
if meta.path.is_ident("group") {
|
||||||
|
if group_name.is_some() {
|
||||||
|
return Err(meta.error("Only one 'group' path can be specified"));
|
||||||
|
}
|
||||||
|
meta.input.parse::<Token![=]>()?;
|
||||||
|
let lit: LitStr = meta.input.parse()?;
|
||||||
|
group_name = Some(lit.value());
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|e| panic!("in #[settings_ui] attribute: {}", e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let ui_item_fn_body = if let Some(group_name) = group_name {
|
||||||
|
quote! {
|
||||||
|
settings::SettingsUIItem { item: settings::SettingsUIItemVariant::Group{ path: #group_name, group: settings::SettingsUIItemGroup{ items: Default::default() } } }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
settings::SettingsUIItem { item: settings::SettingsUIItemVariant::None }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let expanded = quote! {
|
let expanded = quote! {
|
||||||
impl #impl_generics settings::SettingsUI for #name #ty_generics #where_clause {}
|
impl #impl_generics settings::SettingsUI for #name #ty_generics #where_clause {
|
||||||
|
fn ui_item() -> settings::SettingsUIItem {
|
||||||
|
#ui_item_fn_body
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TokenStream::from(expanded)
|
TokenStream::from(expanded)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue