#[func]
Expand description
Makes a native Rust function usable as a Typst function.
This implements NativeFunction
for a freshly generated type with the same
name as a function. (In Rust, functions and types live in separate
namespace, so both can coexist.)
If the function is in an impl block annotated with #[scope]
, things work a
bit differently because the no type can be generated within the impl block.
In that case, a function named {name}_data
that returns &'static NativeFuncData
is generated. You typically don’t need to interact with this
function though because the #[scope]
macro hooks everything up for you.
/// Doubles an integer.
#[func]
fn double(x: i64) -> i64 {
2 * x
}
§Properties
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
), as exposed to Typst. Defaults to the Rust name in kebab-case.title
: The functions’s title case name (e.g.Minimum
). Defaults to the normal name in title case.keywords = [..]
: A list of alternate search terms for this function.constructor
: Indicates that the function is a constructor.
§Arguments
By default, function arguments are positional and required. You can use various attributes to configure their parsing behaviour:
#[named]
: Makes the argument named and optional. The argument type must either beOption<_>
or the#[default]
attribute must be used. (If it’s bothOption<_>
and#[default]
, then the argument can be specified asnone
in Typst).#[default]
: Specifies the default value of the argument asDefault::default()
.#[default(..)]
: Specifies the default value of the argument as..
.#[variadic]
: Parses a variable number of arguments. The argument type must beVec<_>
.#[external]
: The argument appears in documentation, but is otherwise ignored. Can be useful if you want to do something manually for more flexibility.
Defaults can be specified for positional and named arguments. This is in contrast to user-defined functions which currently cannot have optional positional arguments (except through argument sinks).
In the example below, we define a min
function that could be called as
min(1, 2, 3, default: 0)
in Typst.
/// Determines the minimum of a sequence of values.
#[func(title = "Minimum")]
fn min(
/// The values to extract the minimum from.
#[variadic]
values: Vec<i64>,
/// A default value to return if there are no values.
#[named]
#[default(0)]
default: i64,
) -> i64 {
self.values.iter().min().unwrap_or(default)
}
As you can see, arguments can also have doc-comments, which will be rendered in the documentation. The first line of documentation should be concise and self-contained as it is the designated short description, which is used in overviews in the documentation (and for autocompletion).
Additionally, some arguments are treated specially by this macro:
engine
: The compilation context (Engine
).context
: The introspection context (Tracked<Context>
).args
: The rest of the arguments passed into this function (&mut Args
).span
: The span of the function call (Span
).
These should always come after self
, in the order specified.