Other custom type options
Folding
If all of your fields may be omitted (for example), or if you just generally want to be able to combine fields, you could consider adding folding to your custom type with fold: auto
, which will combine each field individually using their own fold methods. You can also use fold: default constructor => (outer, inner) => combine inner with outer, giving priority to inner
for full customization.
Custom constructor and argument parsing
Much like elements, you can use construct: default-constructor => (..args) => value
to override the default constructor for your custom type. You should use construct:
rather than create a wrapper function to ensure that data retrieval functions, such as e.data(func)
, still work.
You can use parse-args: (default arg parser, fields: dictionary, typecheck: bool) => (args, include-required: true) => dictionary with fields
to override the built-in argument parser to the constructor (instead of overriding the entire constructor). include-required
is always true and is simply a remnant from elements' own argument parser (which share code with the one used for custom types).
Argument sink
Here's how you'd use this to implement a positional argument sink:
#let sunk = e.types.declare(
"sunk",
fields: (
field("values", e.types.array(stroke), required: true),
field("color", color, default: red),
field("inner", content, default: [Hello!]),
),
parse-args: (default-parser, fields: none, typecheck: none) => (args, include-required: true) => {
let args = if include-required {
// Convert positional arguments into a single 'values' argument
let values = args.pos()
arguments(values, ..args.named())
} else if args.pos() == () {
// 'include-required' is always true for types, but keeping these here
// just for completeness
args
} else {
assert(false, message: "element 'sunk': unexpected positional arguments\n hint: these can only be passed to the constructor")
}
default-parser(args, include-required: include-required)
},
prefix: ""
)
#assert.eq(
e.fields(sunk(5pt, black, 5pt + black, inner: [Inner])),
(values: (stroke(5pt), stroke(black), 5pt + black), inner: [Inner], color: red)
)