mirror of
https://github.com/anomalyco/opentui.git
synced 2026-04-25 04:55:58 +03:00
[PR #471] [CLOSED] perf(text-buffer-view): stream word wrap for large chunks #559
Labels
No labels
bug
core
documentation
feature
good first issue
help wanted
pull-request
question
react
solid
tmux
windows
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/opentui#559
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/anomalyco/opentui/pull/471
Author: @simonklee
Created: 1/4/2026
Status: ❌ Closed
Base:
main← Head:perf/word-wrap📝 Commits (1)
3341e8fperf(text-buffer-view): stream word wrap for large chunks📊 Changes
3 files changed (+622 additions, -136 deletions)
View changed files
📝
packages/core/src/zig/tests/utf8_test.zig(+160 -0)📝
packages/core/src/zig/text-buffer-view.zig(+311 -115)📝
packages/core/src/zig/utf8.zig(+151 -21)📄 Description
Note: I wasn't sure weather to add this as an issue or a PR, so I went with PR,
but feel free to close if you want to discuss approach first.
The gist of this change is to improve word wrapping performance on large
single-line chunks by switching to a streaming approach instead of
precomputing all word boundaries.
before
https://github.com/user-attachments/assets/6e24a3fe-96ab-4d03-b2e6-ecb2c766cbe2
after
https://github.com/user-attachments/assets/6345cc3a-7af5-4ff7-a040-b9809e49c37c
Word wrapping large single-line files (minified JavaScript, continuous
logs) was slow. The old getWrapOffsets() precomputed all word boundary
positions for the entire chunk before wrapping began. Multi-megabyte
files produced arrays with tens of thousands of entries, most unused
since wrapping only needs boundaries within the current wrap width.
Added a hybrid strategy based on chunk size. Chunks larger than
64KB now use findWordWrapPosition(), which scans only up to wrap_width
columns per line and returns the last word boundary within that
window. This stops early instead of walking the full chunk. Smaller
chunks keep the cached approach where the upfront cost pays off
through cache locality.
Note: wrap-break detection now honors
width_methodin the cachedpath. This changes semantics for
.wcwidthand.no_zwj(per‑codepoint breaks; ZWJ forces a break), while
.unicodebehavioris unchanged. This aligns cached offsets with the streaming path and
cursor movement.
The streaming path uses per-codepoint widths without full grapheme
state, so complex emoji or Indic sequences may wrap differently than
cached, but only in chunks over 64KB containing such sequences at wrap
boundaries.
Benchmarks:
Baseline
31a5cc2(main) -> Currentc688b4a(perf/word-wrap)🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.