typst_macros

Attribute Macro func

source
#[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 be Option<_> or the #[default] attribute must be used. (If it’s both Option<_> and #[default], then the argument can be specified as none in Typst).
  • #[default]: Specifies the default value of the argument as Default::default().
  • #[default(..)]: Specifies the default value of the argument as ...
  • #[variadic]: Parses a variable number of arguments. The argument type must be Vec<_>.
  • #[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.