diff options
| author | Laurenz <laurmaedje@gmail.com> | 2023-05-17 14:39:47 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2023-05-17 14:39:47 +0200 |
| commit | 46aace78ac4ac1c075b9b1670dbb7372df1a0a82 (patch) | |
| tree | e093f81284ffc6a5150a18bdd338da75c368120c /macros | |
| parent | 42afa410ae561eb5b267080d088bca529a5d0b54 (diff) | |
Search keywords
Diffstat (limited to 'macros')
| -rw-r--r-- | macros/src/element.rs | 7 | ||||
| -rw-r--r-- | macros/src/func.rs | 6 | ||||
| -rw-r--r-- | macros/src/util.rs | 19 |
3 files changed, 28 insertions, 4 deletions
diff --git a/macros/src/element.rs b/macros/src/element.rs index 403af103..61830939 100644 --- a/macros/src/element.rs +++ b/macros/src/element.rs @@ -10,6 +10,7 @@ struct Elem { name: String, display: String, category: String, + keywords: Option<String>, docs: String, vis: syn::Visibility, ident: Ident, @@ -126,6 +127,7 @@ fn prepare(stream: TokenStream, body: &syn::ItemStruct) -> Result<Elem> { let mut attrs = body.attrs.clone(); let docs = documentation(&attrs); let mut lines = docs.split('\n').collect(); + let keywords = meta_line(&mut lines, "Keywords").ok().map(Into::into); let category = meta_line(&mut lines, "Category")?.into(); let display = meta_line(&mut lines, "Display")?.into(); let docs = lines.join("\n").trim().into(); @@ -134,6 +136,7 @@ fn prepare(stream: TokenStream, body: &syn::ItemStruct) -> Result<Elem> { name: body.ident.to_string().trim_end_matches("Elem").to_lowercase(), display, category, + keywords, docs, vis: body.vis.clone(), ident: body.ident.clone(), @@ -332,7 +335,7 @@ fn create_set_field_method(field: &Field) -> TokenStream { /// Create the element's `Pack` implementation. fn create_pack_impl(element: &Elem) -> TokenStream { - let Elem { ident, name, display, category, docs, .. } = element; + let Elem { ident, name, display, keywords, category, docs, .. } = element; let vtable_func = create_vtable_func(element); let infos = element .fields @@ -340,6 +343,7 @@ fn create_pack_impl(element: &Elem) -> TokenStream { .filter(|field| !field.internal && !field.synthesized) .map(create_param_info); let scope = create_scope_builder(element.scope.as_ref()); + let keywords = quote_option(keywords); quote! { impl ::typst::model::Element for #ident { fn pack(self) -> ::typst::model::Content { @@ -362,6 +366,7 @@ fn create_pack_impl(element: &Elem) -> TokenStream { info: ::typst::eval::Lazy::new(|| typst::eval::FuncInfo { name: #name, display: #display, + keywords: #keywords, docs: #docs, params: ::std::vec![#(#infos),*], returns: ::std::vec!["content"], diff --git a/macros/src/func.rs b/macros/src/func.rs index f3de6822..2d38c01a 100644 --- a/macros/src/func.rs +++ b/macros/src/func.rs @@ -12,6 +12,7 @@ struct Func { name: String, display: String, category: String, + keywords: Option<String>, docs: String, vis: syn::Visibility, ident: Ident, @@ -80,6 +81,7 @@ fn prepare(item: &syn::ItemFn) -> Result<Func> { .split(" or ") .map(Into::into) .collect(); + let keywords = meta_line(&mut lines, "Keywords").ok().map(Into::into); let category = meta_line(&mut lines, "Category")?.into(); let display = meta_line(&mut lines, "Display")?.into(); let docs = lines.join("\n").trim().into(); @@ -88,6 +90,7 @@ fn prepare(item: &syn::ItemFn) -> Result<Func> { name: sig.ident.to_string().replace('_', ""), display, category, + keywords, docs, vis: item.vis.clone(), ident: sig.ident.clone(), @@ -105,6 +108,7 @@ fn create(func: &Func) -> TokenStream { let Func { name, display, + keywords, category, docs, vis, @@ -117,6 +121,7 @@ fn create(func: &Func) -> TokenStream { let handlers = params.iter().filter(|param| !param.external).map(create_param_parser); let params = params.iter().map(create_param_info); let scope = create_scope_builder(func.scope.as_ref()); + let keywords = quote_option(keywords); quote! { #[doc = #docs] #vis fn #ident() -> &'static ::typst::eval::NativeFunc { @@ -129,6 +134,7 @@ fn create(func: &Func) -> TokenStream { info: ::typst::eval::Lazy::new(|| typst::eval::FuncInfo { name: #name, display: #display, + keywords: #keywords, docs: #docs, params: ::std::vec![#(#params),*], returns: ::std::vec![#(#returns),*], diff --git a/macros/src/util.rs b/macros/src/util.rs index 6b683e5d..2e12ef17 100644 --- a/macros/src/util.rs +++ b/macros/src/util.rs @@ -1,4 +1,5 @@ use heck::ToKebabCase; +use quote::ToTokens; use super::*; @@ -104,13 +105,16 @@ pub fn documentation(attrs: &[syn::Attribute]) -> String { /// Extract a line of metadata from documentation. pub fn meta_line<'a>(lines: &mut Vec<&'a str>, key: &str) -> Result<&'a str> { - match lines.pop().and_then(|line| line.strip_prefix(&format!("{key}:"))) { - Some(value) => Ok(value.trim()), + match lines.last().and_then(|line| line.strip_prefix(&format!("{key}:"))) { + Some(value) => { + lines.pop(); + Ok(value.trim()) + } None => bail!(callsite, "missing metadata key: {}", key), } } -/// Creates a block responsible for building a Scope. +/// Creates a block responsible for building a `Scope`. pub fn create_scope_builder(scope_block: Option<&BlockWithReturn>) -> TokenStream { if let Some(BlockWithReturn { prefix, expr }) = scope_block { quote! { { @@ -122,3 +126,12 @@ pub fn create_scope_builder(scope_block: Option<&BlockWithReturn>) -> TokenStrea quote! { ::typst::eval::Scope::new() } } } + +/// Quotes an option literally. +pub fn quote_option<T: ToTokens>(option: &Option<T>) -> TokenStream { + if let Some(value) = option { + quote! { Some(#value) } + } else { + quote! { None } + } +} |
