Search keywords

This commit is contained in:
Laurenz 2023-05-17 14:39:47 +02:00
parent 42afa410ae
commit 46aace78ac
6 changed files with 33 additions and 4 deletions

View File

@ -359,6 +359,7 @@ fn category_outline(kind: &str) -> Vec<OutlineItem> {
pub struct FuncModel {
pub path: Vec<&'static str>,
pub display: &'static str,
pub keywords: Option<&'static str>,
pub oneliner: &'static str,
pub element: bool,
pub details: Html,
@ -431,6 +432,7 @@ fn func_model(
FuncModel {
path,
display: info.display,
keywords: info.keywords,
oneliner: oneliner(docs),
element: func.element().is_some(),
details: Html::markdown_with_id_base(resolver, docs, id_base),

View File

@ -49,6 +49,7 @@ use crate::text::{LinebreakElem, SpaceElem, TextElem};
///
/// Display: Outline
/// Category: meta
/// Keywords: Table of Contents
#[element(Show, Finalize, LocalName)]
pub struct OutlineElem {
/// The title of the outline.

View File

@ -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"],

View File

@ -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),*],

View File

@ -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 }
}
}

View File

@ -249,6 +249,8 @@ pub struct FuncInfo {
pub name: &'static str,
/// The display name of the function.
pub display: &'static str,
/// A string of keywords.
pub keywords: Option<&'static str>,
/// Documentation for the function.
pub docs: &'static str,
/// Details about the function's parameters.