I want to customise the numbered list function, enum, such that the last item in the list should have the numbering “(C)”, but all the other items should have the numbering “(P1)”. So, it should look like this:
I’ve got a horrid implementation, where I just rebuild the whole list piece by piece and change the numbering for the last entry by just replacing it with the string "(C)". It works but it might not be the best implementation…
#show enum: it => {
stack(dir: ttb,
spacing: if (it.tight) {0.6em} else {1em}, // might have to replace with it.spacing
..for (i,entry) in it.children.enumerate() {
(box(
width: enum.body-indent,
align(right,
if i + 1 == it.children.len() {
"(C)"
} else {
numbering("(P1)",entry.number)
})
) + h(0.5em) + entry.body,)
}
)
}
1. Hello
2. Hello World
3. This is another World
This show rule builds a new enum but passes along all parameters that the original has except for the numbering which follows the rules you defined. I’m not sure what the intended behavior is for a reversed list.
(edit: used @sijo’s suggestion for dealing with parameters and handling when number is auto. Updated the examples to match)
#show enum: it => {
if it.has("label") and it.label == <already-processed> { return it }
let (children, ..parameters) = it.fields()
let content-to-place = enum(
..parameters,
numbering: (..nums) => {
if nums.pos().first() == {
if children.last().has("number") and children.last().number != auto { children.last().number} else { children.len() }
} {
"(C)"
} else {
"(P" + nums.pos().map(str).join(".") + ")"
}
},
..children
)
[#content-to-place<already-processed>]
}
And given these examples:
Normal
1. one
2. two
3. three
Non-Sequential
2. two
4. four
6. six
Reversed
#enum(
reversed: true,
[one],
[two],
[three]
)
No starting number
+ one
+ two
+ last
that is also not entirely right; you can mix + and explicit numbers, and the + will continue counting where the explicit numbers left off:
+ element 1
3. element 3
+ element 4 -- `auto` but not `children.len()`
The following seems to work:
let last-number = if parameters.reversed {
let it = children.first()
// for `reversed` this logic works: the first element can't be preceded by explicit numbers
if it.has("number") and it.number != auto { it.number }
else { children.len() }
} else {
// for regular enums, find the last non-auto element
let numbered = children.enumerate().rev().find(it => it.last().has("number") and it.last().number != auto)
if numbered != none {
let (pos, it) = numbered
// add to the last number the number of elements after it
it.number + (children.len() - pos - 1)
} else {
children.len()
}
}
it fulfills these extra test cases:
Hybrid numbering
+ one
3. two
+ last
#set enum(reversed: true)
Hybrid reversed (kinda nonsensical)
+ one
5. two
+ last