Skip to content

v0.6.1

Choose a tag to compare

@github-actions github-actions released this 26 Aug 20:49
· 52 commits to main since this release

Changed

  • Resizing a document full of code is no longer dominated by re-highlighting
    it.
    Syntax highlighting depends on the text, the language and the theme,
    and a resize changes none of them — but it was being done from inside the
    layout emitter, so every width change re-ran syntect over every fenced block
    in the document and threw the result away.

    It was not a small part of the bill. A document of 120 rust fences laid
    out in 199 ms, against 6 ms for the same text with the language taken off:
    about 97% of a re-layout was highlighting, paid again for every step of a
    drag. Six hundred fences took a full second, each time.

    Highlighting is now kept for as long as the parse it belongs to, which is
    exactly how long it stays valid:

    document before after
    this README 8.6 ms 2.0 ms
    120 rust fences 198.8 ms 8.9 ms
    600 rust fences 999.3 ms 49.8 ms
    600 fences, no language 32.4 ms 32.0 ms

    The last row is the control: nothing to highlight, so nothing to save.

    Switching themes does pay again, once, because the theme is one of the three
    things highlighting depends on — the syntax theme it names, the surface
    colour forced onto every span, and the fill used where there is no language.
    A one-shot render keeps nothing, since it lays the document out once and a
    memo could only cost it memory; its peak stays where it was. A reader
    holding a 300 KB code-heavy document pays about 10 MB for this, and about
    0.1 MB for a document the size of this README.

Fixed

  • A document can no longer take the terminal down with it. Nesting deeply
    enough — about 3,000 levels of > - , or 8,000 nested <div>s — overflowed
    the stack while the document was being laid out: layout walks the block tree
    by recursion, so the depth of the call chain was the depth of the document,
    and the document chose it.

    That is the worst way this program can fail. A stack overflow aborts, and
    an abort does not unwind, so neither the RAII terminal guard nor the panic
    hook that exists for exactly this ever ran. The reader died with the
    alternate screen still up, the cursor still hidden and mouse reporting still
    on — a terminal that needed reset before it could be used again. Nor did
    the document have to be your own: https:// and github:// are ordinary
    sources.

    Nesting is now capped at 256 levels, in the markdown tree and the HTML one
    alike. Past the cap a container is not represented and its children are
    spliced into its parent, so the text still renders — at the capped indent
    rather than a deeper one — instead of being truncated or refused. The cap is
    far above anything a terminal can show: each level of quote or list costs two
    cells of lead, so 80 columns is full of decoration by about level 40, and
    from there the content is already pinned to the one cell the lead leaves it.

  • A resize that stops no longer leaves the last frame mangled. Pane
    geometry is recomputed before every draw, which is why the resize event
    itself does nothing — but the recompute asked Terminal::get_frame for the
    area, and ratatui only updates that inside draw. So it was always reading
    the size of the previous frame: the resize event woke the loop, the loop
    laid the document out for the width the terminal used to be, and drew it
    into the width it now is. Ratatui clips widgets to the buffer, so nothing
    overflowed — it just came out wrong, with the contents pane still divided
    where it had been and headings cut off mid-word.

    Dragging a window edge hid this, because each new event redrew from the
    freshly-learned size. A resize that stops — the ordinary case — had
    nothing following it, so the mangled frame stayed up until a key was
    pressed. The terminal is now asked its size before the geometry is decided,
    the same call the loop already makes after handing the screen to an editor,
    and for the same reason.