How can I hide everything before the last occurrence of a label?

Very quick example:

#metadata("something") <thelabel>

A

#metadata("something") <thelabel>

B

I want to hide everything before the last occurance of <thelabel>.

How can I do this? I’ve tried something with query, but I can’t get that to work (I still haven’t wrapped my head around the combination of a show rule and a query).

This is a bit tricky… I don’t think a query can do it. For the case you showed, the following works:

#let last-position(arr, searcher) = {
  let rev-index = arr.rev().position(searcher)
  if rev-index != none {
    arr.len() - rev-index - 1
  }
}

#show: body => {
  let index = last-position(body.children, item => item.fields().at("label", default: none) == <thelabel>)
  body.children.slice(index).join()
}

#metadata("something") <thelabel>

A

#metadata("something") <thelabel>

B

However this depends on inspecting content, and that can be hard to do right. if the label is instead nested in, say, an emphasis element, my solution won’t find it:

#metadata("something") <thelabel>
// ^ now this is the last match!

A

_#metadata("something") <thelabel>_

B

What’s the end goal you’re after? Maybe there’s a different way to achieve it?

Awesome!

Well, my use case is incredibly odd. I’m a teacher, and I don’t use powerpoint or anything. For the last few years I’ve been using iVim on my iPad with custom highlighting for markdown. This allows me to type things that I want displayed and coloring/formatting is handled for me as I go. It’s incredibly fast.

One shortcut I have is to basically insert a bunch of empty lines at the bottom of the document, jump to the bottom, then set the scroll to the top. Effectively it looks like ‘new page’.

So, I’m thinking about trying all of this out with Typst since it’s so fast with rendering, it should be able to render in real time as I type.

Anyway, the only real hurdle is to get some kind of “new, blank page” function. I’m still trying to figure out how I could get it to work well.

I know about touying, etc. My approach is incredibly different. Think of it like “Typst Whiteboard”

I see, so an “I’m done with this, start from scratch” functionality. In this case maybe you can just assume that the command is always top level and use my solution as-is.

If I think of something else, I’ll let you know. The best other avenue would probably be using pagebreaks and trying to hide all but the last page, but that also seems tricky; maybe it inspires someone else.

Yes.
I also thought of ‘just show the last page’, but again I don’t know how to get there. Probably your above code can be modified for that.

This feels more like an editor problem rather than a Typst problem in principle: you should be able to keep your code there but only ask Typst to render a part of it. Still, here are two potential solutions that require minimal editor support:

  1. Commenting out everything above before continuing (Ctrl + A and Ctrl + / on typical editors, or equivalent keybinds for Vim);

  2. Typst-based solution: dividing your document in sections and only displaying the last one by stepping and checking a counter. See an example:

    #let section-counter = counter("doc-section")
    #let section(x) = {
      section-counter.step()
      context {
        // Don't display if this isn't the last section.
        if section-counter.get() == section-counter.final() {
          x
        }
      }
    }
    
    #section[
      AAA
    ]
    
    #section[
      BBB
    ]
    
    #section[
      CCC
    ]
    

    This will display only “CCC”. So, just type #section[ to ignore the previous sections and start a new one.

How about that?

#set page(width: auto, height: auto)
#let doc(body) = {
  let b = body.children.split(metadata("split"))
  return b.last().join("")
}

#show: doc

= Heading 1
#metadata("split")
= Heading 2
ah
$a x + b = y$
= Heading 3
Output

image

I would like to mention Hide Function – Typst Documentation. You can wrap anything with it and it will hide it. But I remembered that it won’t affect the layout, which means if you hide multiple pages with this function, then you will have multiple empty pages.