I want to be able to define themes that the user can select to use in a document. On the assumption that doing so will expand compilation time, I am trying to avoid using states/context as most functions will require some config data from a theme (although if I am wrong here please let me know).
I wonder if there is a more efficient approach to this problem then what I have come up with below, where functions, from a package, need to take some parameters from a theme and the user elects this the theme at the start of their document (after they include the package).
I have included an alternative with states below as a comparison.
To be clear, I should never need to change the theme throughout the document (or set it after a function is used). I am very happy for it to be set initially if this makes anything easier.
I am pretty new to Typst, so this might be very simple (e.g. maybe some show rule that remaps an arg in the function can solve all this really fast…)
Really look forward to feedback!
Here is a MWE:
Functions.typ:
// Theme configurations
#let themes = (
first: (
theme_colour: blue
),
second: (
theme_colour: red
),
)
// Function that creates themed functions
#let with-theme(theme-name) = {
let colour = themes.at(theme-name).theme_colour
// Return the themed functions
(
myrect: (width: 2cm, height: 1cm) => rect(fill: colour, width: width, height: height),
mycircle: (width: 2cm, height: 1cm) => circle(fill: colour, width: width, height: height)
)
}
// Helper to extract functions cleanly
#let use-theme(theme-name) = {
let theme-funcs = with-theme(theme-name)
(theme-funcs.myrect, theme-funcs.mycircle)
}
#let mytheme = state("mytheme", themes.at("first"))
#let myrect_state(width: 2cm, height: 1cm) = {
context {
rect(fill: mytheme.at(here()).theme_colour, width: width, height: height)
}
}
doc.typ
#import "functions.typ": *
// Without states:
#let (myrect, mycircle) = use-theme("second")
#myrect()
// With states:
#myrect_state(width: 2cm, height: 1cm)
#mytheme.update(themes.at("second"))
#myrect_state(width: 2cm, height: 1cm)