How to set header with a function

i have a long setup for header similar to

#set page(
  numbering: "1",

  header: context [
    HEADER
    #h(1fr)
    #counter(page).display()
  ],
)

= First Chapter

#lorem(200)

which i would move to a function (to better structure the code). I assume i would have to write something like:

#let set-header: it => context [
    HEADER
    #h(1fr)
    #counter(page).display()
  ],
#set page(
  numbering: "1",

  header: set-header()
)

= First Chapter

#lorem(200)

What is the correct approach?

1 Like

Hi, welcome to the forum!

You could define the function with the => syntax (anonymous function) but this is a function with zero argument so you would write: #let set-header = () => context [...]. But it’s a bit weird to define an anonymous function just to store it in a variable set-header. You would rather define a set-header function directly with

#let set-header() = context [ ... ]

But the body of the function is constant so you don’t need a function at all! So the right way to do this here is to define the header content simply as a variable:

#let header = context [ ... ]

and use it as #set page(header: header, ...).

1 Like

@sijo is 100% right that a function is unnecessary here.
Creating a function can have benefits though, such as the ability to easily change the header text when you want.

#let set-header(header-text) = context [
  #header-text
  #h(1fr)
  #counter(page).display()
]

#set page(numbering: "1")

#set page(header: set-header[Header Text 1])
#set page(header: set-header[Header Text 2])

Note, however, that a new page is created every time set page() is called. So you would probably only use this at the start of a new chapter/section.


Something that is not obvious but can have surprising effects on layout is the use of [] here. This even has its own GitHub issue:

A simple change is to use {} instead:

#let set-header(header-text) = context {
  header-text
  h(1fr)
  counter(page).display()
}
3 Likes

I think u want to get rid of the non-content stuff like h(1fr), counter(), SURE u can do it this way

#let Page = (
  num: "1",
  hdr: [HEADER],)

#set page(
  numbering: Page.num,
  header: context {
    Page.hdr
    h(1fr)
    counter(page).display()},)

= First Chapter

#lorem(200)

@Maxwell: Thank you for your suggestion. I gave only an example, my actual header code runs for half a page or more and thus I do not want to include it in the code for the booklayout (frontmatter etc.).

@sijo: thank you. This is what I hoped for. I do not understand what context in the definition of the function does; could you explain a bit? I assume that “…” is not required if I have

#set page(
  numbering: "1",
  header: header1
)

followed by the input text.

@gezepi: Thank you - your warning is well received! I am learning Typst and was wondering why are two seemingly equivalent way of writing things are offered - now I understand what the difference is. (I was learning with help from an LLM, which definitely had seen too many examples of what you describe as dangerous).

Indeed the ... stands for whatever you want to have in your header, for example (using code mode rather than markup as suggested though it might not make a difference in this case):

#let header = context {
  [Hello]
  h(1fr)
  counter(page).display()
}

#set page(numbering: "1", header: header)

The context keyword is used to make a “contextual” value (see documentation). It’s a special value that is evaluated only when the value is actually placed in the document. This is mandatory when using something like counter(page).display() which uses the current location in the document to compute the result.

So with context you store a special kind of value in header, and this value will be inserted on every page of your document (because you do #set page(header: header), and every time it is inserted, it will be computed and give a different result (since the page number changes).

Note that there is no “function definition” here, but it’s true that context values do something a bit similar since they can be evaluated multiple times implicitly.