Custom label for a numbered list

Hello,

I am trying to build a numbered list for k-steps.
The main idea is that the numbering begins at 1, at some points becomes an empty value, then the final value is labels as a k.

I try to use the #enum function with the enum.item, but it does not seem to work with letters or the none value.

My current code looks like this:

 the following $k$ steps are perform:
+ sample $theta_1^{d+1}$ from $"p" ( theta_1|theta_2^d, dots.h.c  , theta_k^d, y )$,
+ sample $theta_2^{d+1}$ from $"p" (theta_2|theta_1^{d+1}, theta_3^{d}, dots.h.c, theta_{k}^d, y)$, 
+ $dots.h.c$ // there should be number in this step
+ sample $theta_k^{d+1}$ from $"p" (theta_k| theta_1^{d+1}, theta_2^{d+1}, dots.h.c, theta_{k-1}^{d},y ).$ // This label should be "k"

Thank you in advance!

Here’s one way of doing it:

#show enum: it => {
  //If this enum has already been processed, don't process it again
  if it.has("label") and it.label == <already-processed> {return it}
  
  //Get the total number of items and only apply this to lists with 3 or more items
  let num-items = it.children.len()
  if num-items < 3 {return it}
  
  //Define the conditions for displaying a "k" and ""
  let fancy-numbering = n => if n == num-items {
    "k"
  } else if n == num-items - 1 {
    ""
  } else {
    n
  }

  //Create a new list and add a label to it that it has been processed
  [#enum(
    tight: it.tight,
    numbering: fancy-numbering,
    full: it.full,
    indent: it.indent,
    body-indent: it.body-indent,
    spacing: it.spacing,
    number-align: it.number-align,
    
    ..it.children.map(child => enum.item(none, child.body))
  )<already-processed>]
}

the following $k$ steps are perform:
+ #lorem(5)
+ #lorem(5)
+ $dots.h.c$
+ #lorem(5)

It seems to me though, that adding the ellipsis between the 2 and k would also be nice. For that, change the second conditional line to this:

  } else if n == num-items - 1 {
    sym.dots.v //was ""
  }

2 Likes

Hello,
Is there now an easier way to do this? the current solution does not seem to work in the latest version of typst (or at least not for me)

What’s your version?

Try

#sys.version

Hello,
It is 0.14.2

For the future, some more details about how it isn’t working would be nice.

The error is here:

Fixing it is simple, simply remove the none, so that child.body is the only argument:

..it.children.map(child => enum.item(child.body))

It seems the enum.item documentation is out of date because it lists two parameters.

Edit: Full code that works with `0.14.2`
#show enum: it => {
  //If this enum has already been processed, don't process it again
  if it.has("label") and it.label == <already-processed> {return it}
  
  //Get the total number of items and only apply this to lists with 3 or more items
  let num-items = it.children.len()
  if num-items < 3 {return it}
  
  //Define the conditions for displaying a "k" and ""
  let fancy-numbering = n => if n == num-items {
    "k"
  } else if n == num-items - 1 {
    sym.dots.v
  } else {
    n
  }

  //Create a new list and add a label to it that it has been processed
  [#enum(
    tight: it.tight,
    numbering: fancy-numbering,
    full: it.full,
    indent: it.indent,
    body-indent: it.body-indent,
    spacing: it.spacing,
    number-align: it.number-align,
    
    ..it.children.map(child => enum.item(child.body))
  )<already-processed>]
}

the following $k$ steps are perform:
+ #lorem(5)
+ #lorem(5)
+ #none
+ #lorem(5)
1 Like

The first argument of type auto/int is optional, it does not allow none anymore. 0.14.0 – Typst Documentation

2 Likes