How to display the value of a counter at a given location?
Note that the numbering
may have changed or depend on the context
. Therefore, it looks like that I need the remote context or to time travel. I know I can achieve it for counters and states, but is it possible for context?
To be specific, how to get the original figure.numbering
at <fig>
in the following example?
#set figure(numbering: "1")
= First
#figure(rect(), caption: [A]) <fig>
#figure(rect(), caption: [B])
- @fig
// β β
Figure 1
- #context numbering(figure.numbering, ..counter(figure).at(<fig>))
// β β
1
= Second
#set figure(numbering: "A") // π The numbering has changed
- @fig
// β β
Figure 1
- #context numbering(figure.numbering, ..counter(figure).at(<fig>))
// β β A
My attempt
I have tried various approaches, and the only two working solutions (in typst 0.13.1) are:
-
Use the canonical
ref
and avoid reconstructing it byshow ref: it => β¦
. -
Alternatively, create a metadata in that context and save the result of
counter.display()
in it.#figure(rect(), caption: [A]) <fig> #context [#metadata(counter(figure).display()) <meta>] // β¦ #context query(<meta>).first().value // β β 1
Is it safe to use metadata
here?
Full code
#set page(height: auto, width: auto, margin: 2em)
= Setup
#set heading(numbering: "1")
#set figure(numbering: n => raw(
repr((
figure: n,
heading: counter(heading).get(),
)),
lang: "typc",
))
#let please-display() = counter(figure).display()
#let please-number(at: none) = {
assert.ne(at, none)
numbering(figure.numbering, ..counter(figure).at(at))
}
#let meta-save(label, value) = [#metadata(value) #std.label(label)]
#let reconstruct-ref(body) = {
show ref: it => {
let el = it.element
assert.eq(el.func(), figure)
numbering(el.numbering, ..counter(figure).at(el.location()))
}
body
}
#let show-ref-eq(body) = {
// https://typst.app/docs/reference/model/ref/#customization
show ref: it => {
let eq = math.equation
let el = it.element
if el != none and el.func() == eq {
// Override equation references.
link(el.location(), numbering(el.numbering, ..counter(eq).at(el.location())))
} else {
// Other references as usual.
it
}
}
body
}
= First
#figure(rect(), caption: [A]) <fig>
#let numbered = context please-number(at: here())
#let displayed = context please-display()
#context meta-save("numbered", please-number(at: here()))
#context meta-save("displayed", please-display())
#figure(rect(), caption: [B])
- @fig --- β
Ref
- #reconstruct-ref[@fig] --- β
Customized and reconstructed ref
- #show-ref-eq[@fig] --- β
Customized but canonical ref
- #context please-number(at: <fig>) --- β
Please number there
- #context please-number(at: here()) --- β Please number here
- #numbered --- β Numbered
- #context query(<numbered>).first().value --- β
Numbered in metadata
- #context please-display() --- β Please display
- #displayed --- β Displayed
- #context query(<displayed>).first().value --- β
Displayed in metadata
= Second
#set figure(numbering: "A")
#counter(figure).update(26)
```typ
#set figure(numbering: "A")
#counter(figure).update(26)
```
- @fig --- β
Ref
- #reconstruct-ref[@fig] --- β Customized and reconstructed ref
- #show-ref-eq[@fig] --- β
Customized but canonical ref
- #context please-number(at: <fig>) --- β Please number there
- #context please-number(at: here()) --- β Please number here
- #numbered --- β Numbered
- #context query(<numbered>).first().value --- β
Numbered in metadata
- #context please-display() --- β Please display
- #displayed --- β Displayed
- #context query(<displayed>).first().value --- β
Displayed in metadata
Besides, I notice the function Counter::display_at_loc
in rust. Could I access it in typst?
Previous discussions on Discord
laurmaedje β 2023/6/4 17:47
counter(page).display-at(loc)
would be useful
Discord
PgSuperβ:fire: β 2023/12/30 02:58
there has been a proposal to add something likecounter(page).display(at: loc)
Discord
Background
The full code of headcount 0.1.0 β Typst Universe is as the following. Here the numbering
depends on the context.
headcount 0.1.0 lib.typ (~10 lines)
#let reset-counter(counter, levels: 1) = it => {
if it.level <= levels { counter.update((0,)) }
it
}
#let normalize-length(array, length) = {
if array.len() > length {
array = array.slice(0, length)
} else if array.len() < length {
array += (length - array.len()) * (0,)
}
return array
}
#let dependent-numbering(style, levels: 1) = n => {
numbering(style, ..normalize-length(counter(heading).get(), levels), n)
}
More minimal working examplesβ¦
#import "@preview/headcount:0.1.0": dependent-numbering, reset-counter
#set figure(numbering: dependent-numbering("1-1"))
#show heading: reset-counter(counter(figure.where(kind: image)))
#import "@preview/great-theorems:0.1.2": great-theorems-init, mathblock
#show: great-theorems-init
#let theorem = mathblock(blocktitle: [Theorem], counter: counter("theorem"), numbering: dependent-numbering("1-1"))
#show heading: reset-counter(counter("theorem"))