summaryrefslogtreecommitdiff
path: root/crates/typst-macros
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2024-02-27 11:05:16 +0100
committerGitHub <noreply@github.com>2024-02-27 10:05:16 +0000
commit145723b1ef4fa23f1f6665b8907dfe79d0bf83cf (patch)
tree02a7de661ddd5dafa75dfce3e3c8b45a7333b9dc /crates/typst-macros
parente9ee00a7c0df083663ff5ccca162238b88525e14 (diff)
New context system (#3497)
Diffstat (limited to 'crates/typst-macros')
-rw-r--r--crates/typst-macros/src/elem.rs23
-rw-r--r--crates/typst-macros/src/func.rs15
-rw-r--r--crates/typst-macros/src/lib.rs2
-rw-r--r--crates/typst-macros/src/util.rs1
4 files changed, 38 insertions, 3 deletions
diff --git a/crates/typst-macros/src/elem.rs b/crates/typst-macros/src/elem.rs
index 81548dd7..f14d3350 100644
--- a/crates/typst-macros/src/elem.rs
+++ b/crates/typst-macros/src/elem.rs
@@ -617,6 +617,7 @@ fn create_native_elem_impl(element: &Elem) -> TokenStream {
vtable: <#ident as #foundations::Capable>::vtable,
field_id: |name| name.parse().ok().map(|id: Fields| id as u8),
field_name: |id| id.try_into().ok().map(Fields::to_str),
+ field_from_styles: <#ident as #foundations::Fields>::field_from_styles,
local_name: #local_name,
scope: #foundations::Lazy::new(|| #scope),
params: #foundations::Lazy::new(|| ::std::vec![#(#params),*])
@@ -866,6 +867,20 @@ fn create_fields_impl(element: &Elem) -> TokenStream {
quote! { Fields::#enum_ident => #expr }
});
+ // Fields that can be accessed using the `field_from_styles` method.
+ let field_from_styles_arms = element.visible_fields().map(|field| {
+ let Field { enum_ident, .. } = field;
+
+ let expr = if field.required || field.synthesized {
+ quote! { None }
+ } else {
+ let value = create_style_chain_access(field, false, quote!(None));
+ quote! { Some(#into_value(#value)) }
+ };
+
+ quote! { Fields::#enum_ident => #expr }
+ });
+
// Sets fields from the style chain.
let materializes = visible_non_ghost()
.filter(|field| !field.required && !field.synthesized)
@@ -939,6 +954,14 @@ fn create_fields_impl(element: &Elem) -> TokenStream {
}
}
+ fn field_from_styles(id: u8, styles: #foundations::StyleChain) -> Option<#foundations::Value> {
+ let id = Fields::try_from(id).ok()?;
+ match id {
+ #(#field_from_styles_arms,)*
+ _ => None,
+ }
+ }
+
fn materialize(&mut self, styles: #foundations::StyleChain) {
#(#materializes)*
}
diff --git a/crates/typst-macros/src/func.rs b/crates/typst-macros/src/func.rs
index 953df428..728ab05b 100644
--- a/crates/typst-macros/src/func.rs
+++ b/crates/typst-macros/src/func.rs
@@ -24,6 +24,7 @@ struct Func {
constructor: bool,
keywords: Vec<String>,
parent: Option<syn::Type>,
+ contextual: bool,
docs: String,
vis: syn::Visibility,
ident: Ident,
@@ -37,6 +38,7 @@ struct Func {
struct SpecialParams {
self_: Option<Param>,
engine: bool,
+ context: bool,
args: bool,
span: bool,
}
@@ -67,6 +69,7 @@ enum Binding {
/// The `..` in `#[func(..)]`.
pub struct Meta {
pub scope: bool,
+ pub contextual: bool,
pub name: Option<String>,
pub title: Option<String>,
pub constructor: bool,
@@ -78,6 +81,7 @@ impl Parse for Meta {
fn parse(input: ParseStream) -> Result<Self> {
Ok(Self {
scope: parse_flag::<kw::scope>(input)?,
+ contextual: parse_flag::<kw::contextual>(input)?,
name: parse_string::<kw::name>(input)?,
title: parse_string::<kw::title>(input)?,
constructor: parse_flag::<kw::constructor>(input)?,
@@ -117,6 +121,7 @@ fn parse(stream: TokenStream, item: &syn::ItemFn) -> Result<Func> {
constructor: meta.constructor,
keywords: meta.keywords,
parent: meta.parent,
+ contextual: meta.contextual,
docs,
vis: item.vis.clone(),
ident: item.sig.ident.clone(),
@@ -171,6 +176,7 @@ fn parse_param(
match ident.to_string().as_str() {
"engine" => special.engine = true,
+ "context" => special.context = true,
"args" => special.args = true,
"span" => special.span = true,
_ => {
@@ -247,6 +253,7 @@ fn create_func_data(func: &Func) -> TokenStream {
scope,
parent,
constructor,
+ contextual,
..
} = func;
@@ -272,6 +279,7 @@ fn create_func_data(func: &Func) -> TokenStream {
title: #title,
docs: #docs,
keywords: &[#(#keywords),*],
+ contextual: #contextual,
scope: #foundations::Lazy::new(|| #scope),
params: #foundations::Lazy::new(|| ::std::vec![#(#params),*]),
returns: #foundations::Lazy::new(|| <#returns as #foundations::Reflect>::output()),
@@ -320,12 +328,13 @@ fn create_wrapper_closure(func: &Func) -> TokenStream {
.as_ref()
.map(bind)
.map(|tokens| quote! { #tokens, });
- let vt_ = func.special.engine.then(|| quote! { engine, });
+ let engine_ = func.special.engine.then(|| quote! { engine, });
+ let context_ = func.special.context.then(|| quote! { context, });
let args_ = func.special.args.then(|| quote! { args, });
let span_ = func.special.span.then(|| quote! { args.span, });
let forwarded = func.params.iter().filter(|param| !param.external).map(bind);
quote! {
- __typst_func(#self_ #vt_ #args_ #span_ #(#forwarded,)*)
+ __typst_func(#self_ #engine_ #context_ #args_ #span_ #(#forwarded,)*)
}
};
@@ -333,7 +342,7 @@ fn create_wrapper_closure(func: &Func) -> TokenStream {
let ident = &func.ident;
let parent = func.parent.as_ref().map(|ty| quote! { #ty:: });
quote! {
- |engine, args| {
+ |engine, context, args| {
let __typst_func = #parent #ident;
#handlers
#finish
diff --git a/crates/typst-macros/src/lib.rs b/crates/typst-macros/src/lib.rs
index 5d340473..f92230ef 100644
--- a/crates/typst-macros/src/lib.rs
+++ b/crates/typst-macros/src/lib.rs
@@ -40,6 +40,8 @@ use syn::DeriveInput;
/// You can customize some properties of the resulting function:
/// - `scope`: Indicates that the function has an associated scope defined by
/// the `#[scope]` macro.
+/// - `contextual`: Indicates that the function makes use of context. This has
+/// no effect on the behaviour itself, but is used for the docs.
/// - `name`: The functions's normal name (e.g. `min`). Defaults to the Rust
/// name in kebab-case.
/// - `title`: The functions's title case name (e.g. `Minimum`). Defaults to the
diff --git a/crates/typst-macros/src/util.rs b/crates/typst-macros/src/util.rs
index 89880db1..bfe22285 100644
--- a/crates/typst-macros/src/util.rs
+++ b/crates/typst-macros/src/util.rs
@@ -255,6 +255,7 @@ pub mod kw {
syn::custom_keyword!(span);
syn::custom_keyword!(title);
syn::custom_keyword!(scope);
+ syn::custom_keyword!(contextual);
syn::custom_keyword!(cast);
syn::custom_keyword!(constructor);
syn::custom_keyword!(keywords);