How to make a codeblock stick to the previous paragraph?

Hi, I would like to write a function that does the following:

  1. for any given paragraph (par)
  2. if this paragraph is followed by a code block (raw)
  3. make this paragraph a block with (sticky: true)

That way I wouldn’t have codeblocks start a page but have the explanatory line above it which makes it much nicer.

I just could not figure out enough of the typst scripting syntax yet :P

WARNING: This may NOT be the intended way to use Typst. The code below may interfere with other parts of your document.

#let stick-par-raw(it) = {
  let func-seq = [].func()
  let func-space = [ ].func()
  let func-styled = [#set text(style: "normal")].func()

  let is-space(e) = (e.func() == func-space or e.func() == parbreak)

  if (it.func() == func-seq) {
    let children = it.children
    let processed = false
    let breaked = true

    for i in range(children.len()) {
      let child = children.at(i)
      if (child.func() == par or (child.func() == text and breaked)) {
        if (i + 2 < children.len()) {
          let next-child = children.at(i + 1)
          let next-next-child = children.at(i + 2)

          if (is-space(next-child) and (next-next-child.func() == raw)) {
            block(sticky: true, child)
            next-child
            block(sticky: true, next-next-child)
            processed = true
            continue
          }
        }
      }

      breaked = false
      if (child.func() == parbreak) {
        breaked = true
      }
      if (child.func() == raw and processed) {
        processed = false
        continue
      }
      if (child.func() == func-seq) {
        stick-par-raw(child)
        continue
      }
      if (child.func() == func-styled) {
        func-styled(stick-par-raw(child.child), child.styles)
        continue
      }
      child
    }
  } else {
    it
  }
}


#show: stick-par-raw

#set page(height: 100pt, width: 300pt)

#lorem(10)

#lorem(10)

```cpp
int main();
```

How it works
The function stick-par-raw processes everything in your document, which is likely a sequence, and retrieves all of its children.

Within its children, the function identifies consecutive elements like par (or text with a preceding parbreak) followed by a space or parbreak, then followed by raw. It wraps the par and raw in a sticky block, and for elements that do not match this pattern, it returns them as they are.

The reason I mentioned that this code might break other parts of your document is due to the simplicity of my test case. In a real document, there may be incomplete cases or unforeseen edge cases. Therefore, you might need to enhance this script further to fully meet your requirements.

1 Like