I’m experimenting with writing a document in a way that exposes arguments for query. This is per-se not that complicated, but I struggle with doing it cleanly. My ideal result would look something like this:
#import "some-package": declare_args
#let args = declare_args((sender: "Alice", receiver: "Bob"))
Hi #args.receiver, this is #args.sender
where the declare_args
function:
- inserts a
metadata
content block with the args, such that we can query for it from an external program - replaces the values of
sender
andreceiver
by values fromsys.inputs
(if provided) - colors all values of keys that were not provided via
sys.inputs
red to show they need to be provided (but not stopping the compilation)
This is as such not possible, since typst cannot return a value and insert a block at the same time.
I was able to get the following variants of this, but am not happy with them:
#let args =(sender: "Alice",receiver: "Bob")
#declare_args(args) // basically #metadata(args) <args>
#let args = mark_required(args) // Merge sys.inputs and color them
// needs two calls and reassigns the args
.
#let (args, meta) =declare_and_mark((sender: "Alice",receiver: "Bob")) // just the other two functions combined returning an array
#meta
// You need to insert that meta variable and don't really notice if your forget
.
// Using state and a regex rule, collect all occurrences of ARG_*, replace them with sys.inputs.at(*) or text(red, *) and insert a metadata tag of state.final()
#show: regex_spam
Hi ARGS_sender, this is ARGS_receiver
// Using a variable gives better hints and autocompletion. (and regex rules are scary)
.
#let arg_func(key) => [
#metadata(key) <arg>
#sys.inputs.at(key,default: text(red, args.at(key)))
]
Hi arg_func("receiver"), this is arg_func("sender")
// Again, the variable with fields just has better support
What I tried but didn’t get to work:
- A show rule that somehow injects a variable into the document (not possible due to scoping)
- Returning a variable and inserting a content block by the same function (not possible)
Any ideas how I could get closer to my ideal result?