I have a document that uses roman page numbers for the preface, numeric ones for the main matter and no page number for title pages in between the main matter. I would like to switch between these three states without setting the footer “from scratch” each time, like so:
#set page(width: 50mm, height: 50mm)
#show heading.where(level: 1): it => {
pagebreak(weak: true)
it
}
#let page-number(shown, format: none) = {
context {
if shown {
set page(footer: align(center, counter(page).display(format)))
}
}
}
#page-number(true, format: "I")
= Preface: Roman Page Number
#counter(page).update(1)
#page-number(true, format: "1")
= Main Section: Numeric Page Number
#page-number(false)
= Blank Page: No Page Number
#page-number(true, format: "1")
= Main Section: Numeric Page Number
But this example doesn’t work (this displays no page numbers at all), I suspect because context doesn’t work that way. How could I refactor the code to get it to work?
Simplest version that does the “same thing” (morally) of that code is to use page numbering:
#set page(numbering: "I")
= Preface: Roman Page Number
#counter(page).update(1)
#set page(numbering: "1")
= Main Section: Numeric Page Number
#set page(numbering: none)
= Blank Page: No Page Number
#set page(numbering: "1")
= Main Section: Numeric Page Number
If you want to configure the footer once and for all you can do that, but not necessary for this example.
The set page rule only works the usual way: it works in the scope where it is, for all the following code. So a show rule would be how to refactor it to be closer to the original code (but this is not better for this simple case)
#let page-number(shown, format: none, it) = {
set page(footer: align(center, context counter(page).display(format))) if shown
set page(footer: []) if not shown
it
}
#show: page-number.with(true, format: "I")
As you can see the function has the item it which it expands in the scope where the set rules have been applied.
Generally speaking, working with code in markup mode can play dirty tricks on you, and you have to use # a lot, so it’s better to avoid it. You’re also using an unnecessary {} to wrap the context. You can also apply an early return pattern and get this:
#set page(footer: context {
let page-numbering = here().page-numbering()
if page-numbering == none { return }
align(right, counter(page).display(page-numbering))
})
Although with a formatter the number of lines will be the same, but the syntax and logic is a little easier to read through.