How to reference context?

I have defined a frame environment and want to reference the counter in the title of the frame but it gives me an error as the counter is context. Is there a way to get around this?
My current version is below. Basically everything works but if I enter a label my frame it tells me it cant reference context.


#let frame(content, counter: none, title: none, fill-body: none, fill-header: none, radius: 0.2em, color: default-color,type : none,label:none) = {

  // Automatically increment frame counter
let displayed-counter = none

if type == "Lemma" {
  lemma-counter.step()
  displayed-counter = if counter == none {
    context lemma-counter.display() 
    color = gray
  } else {
    counter
  }

} else if type == "Definition" {
  definition-frame-counter.step()
  displayed-counter = if counter == none {
    context definition-frame-counter.display()

    color= green
  } else {
    counter
  }

} else if type == none {
  displayed-counter = if counter == none {
    context definition-frame-counter.display()
  } else {
    counter
  }
}

  let header = none

  if fill-header == none and fill-body == none {
    fill-header = color.lighten(75%)
    fill-body = color.lighten(85%)
  }
  else if fill-header == none {
    fill-header = fill-body.darken(10%)
  }
  else if fill-body == none {
    fill-body = fill-header.lighten(50%)
  }

  if radius == none {
    radius = 0pt
  }

 
  if title == none {
    header = [*#type #displayed-counter#label*]
  } else {
    header = [*#type #displayed-counter#label
    * #title]
  }
  
  show stack: set block(breakable: false, above: 0.8em, below: 0.5em)

  stack(
    block(
      width: 100%,
      inset: (x: 0.4em, top: 0.35em, bottom: 0.45em),
      fill: fill-header,
      radius: (top: radius, bottom: 0cm),
      header,
    ),
    block(
      width: 100%,
      inset: (x: 0.4em, top: 0.35em, bottom: 1em),
      fill: fill-body,
      radius: (top: 0cm, bottom: radius),
      content,
      
    ),
    v(0.21cm)
  )
}

Welcome to the forum!

Unfortunately, the code you posted is incomplete. There may be more things missing from it, but here’s a start:

  1. frame() is never called - is it important what arguments it has? How are you wanting to use it?
  2. No default-color exists → compilation error
  3. No definition-frame-counter → compilation error

Please see https://www.sscce.org/ for some of the how and the why of posting a good code example.

Theres two options here that I can think of:

  1. Don’t store the displayed counter, and simply use counter.at() to get the value at the label position:
#let my-counter = counter("my-counter")

#let frame(label: none) = {
  my-counter.step()
  context {
    let displayed-counter = my-counter.display()

    rect([Frame #displayed-counter #label])
  }
}

#let ref-frame(label) = {
  context numbering("1", ..my-counter.at(label))
}

#frame()

#frame(label: <foo>)

#frame()

#ref-frame(<foo>)
  1. Write a custom show-rule to be able to reference metadata.

    It is never possible to reference context, but it is possible to reference metadata if you have a custom show ref: rule. You can store the rendered counter inside metadata, and attach the label to the metadata. This will then give the error that you “cant reference metadata”, but that is not completely true. You can write a custom show ref: rule which handles this case and it will be fine.

#let my-counter = counter("my-counter")

#let frame(label: none) = {
  my-counter.step()
  context {
    let displayed-counter = my-counter.display()

    // here, it is important that the `metadata` is inside the `context` block
    [#metadata((frame-counter: displayed-counter))#label]

    rect([Frame #displayed-counter])
  }
}

#show ref: it => {
  if it.element != none and it.element.func() == metadata and "frame-counter" in it.element.value {
    it.element.value.frame-counter
  } else {
    it
  }
}

#frame()

#frame(label: <foo>)

#frame()

@foo

Both of these code examples produce the following output:


The following topics might also have useful info for you:

2 Likes

My apologies, as this was my first time posting, I was unaware - I will be doing better next time. As my question has been solved be the other comment I will just let it be as is for now.

The second way I can’t get to work but the first one works, thankl you =)