- HighlighterEngine caches spans only for rows near the requested row
and trims the cache around it past 16k entries; per-row end states are
still kept to resume lexing. Jumping to the end of a 78 MB C++ file
cached every row's spans (854 MB RSS, now 197 MB), and the first edit
near the top spent 270 ms freeing them.
- Plain and regex search read lines as views into the materialized
buffer instead of Buffer::Rows(), which built (and kept) a string per
line, O(lines x pieces) after edits. Plain search scans the whole text
once and tracks rows by newline.
- transform_rows() applies a per-row rewrite of a row range as one edit
(replace_rows_text). Indent/unindent region and visual-line insert,
backspace, delete, newline and yank used one piece-table edit per row,
each linear in the buffer: 1.1 s per keystroke with 5,000 rows selected
in a 26 MB file (now 4 ms), and minutes to indent a large region.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015rcVQiiWyTzoNrsvLSaAfB