LAB-1794: Restore vt soft-wrap APIs for amux - #14
Conversation
(cherry picked from commit fd73236)
(cherry picked from commit 4fe2581)
(cherry picked from commit f6428ab)
(cherry picked from commit c989e2b)
(cherry picked from commit 2a7982e)
(cherry picked from commit 6312109)
(cherry picked from commit d693f29)
(cherry picked from commit 3f9194a)
(cherry picked from commit f094749)
(cherry picked from commit 0a58e91)
|
Claude finished @cweill's task in 3m 47s —— View job PR Review: LAB-1794 Restore vt soft-wrap APIs
Review
|
Greptile SummaryThis PR restores the
Confidence Score: 4/5Safe to merge with one design point worth confirming: whether setLineWrapped clearing the flag on any col-0 write matches amux's expectations for LineWrapped. The core reflow and metadata machinery are well-reasoned and well-tested. The main open question is the 'clear wrap on any col-0 write' semantics in utf8.go — if amux-hosted programs do cursor-positioned writes at col 0 on continuation rows, LineWrapped results could be silently wrong. vt/utf8.go — specifically the setLineWrapped call at lines 90-92 and whether its semantics align with how amux consumes LineWrapped. Important Files Changed
Sequence DiagramsequenceDiagram
participant App
participant Emulator
participant Screen
participant WrappedMeta as wrapped[]bool
App->>Emulator: Write fills row triggering autowrap
Emulator->>Screen: "handleGrapheme(x=0, wrapped=true)"
Screen->>WrappedMeta: setLineWrapped(y, true)
App->>Emulator: LineWrapped(y)
Emulator->>Screen: lineWrapped(y)
Screen->>WrappedMeta: read wrapped[y]
WrappedMeta-->>App: true
App->>Emulator: Resize(narrower, height)
Emulator->>Screen: resizeNarrow(w, h, cursorPhantom)
Screen->>Screen: captureReflowState uses lineWrapped
Screen->>Screen: wrapReflowState returns lineWraps
Screen->>WrappedMeta: replaceLineWraps(lineWraps, start, h)
App->>Emulator: CursorPhantom()
Emulator-->>App: e.atPhantom
Reviews (1): Last reviewed commit: "vt: expose pending autowrap cursor state" | Re-trigger Greptile |
| if x == 0 { | ||
| e.scr.setLineWrapped(y, wrapped) | ||
| } |
There was a problem hiding this comment.
Wrap flag silently cleared by cursor-move-then-write at column 0
setLineWrapped(y, false) fires for every grapheme that lands at x == 0, regardless of whether the cursor arrived there via autowrap or an explicit cursor-positioning sequence. If a program places the cursor at (0, y) using CUP/\r and then writes a character — without triggering autowrap — the soft-wrap flag on that row is erased. A future call to LineWrapped(y) will return false even though the row was originally produced by autowrap, breaking downstream reflow in amux.
A simple reproduction: write 25 characters to a 20-wide terminal (rows 0 and 1 set up with LineWrapped(1)==true), then send \033[2;1H and write a single printable character — LineWrapped(1) flips to false.
Most terminal emulators store the wrap attribute as a line property mutated only by the autowrap mechanism itself; overwriting characters via cursor movement does not touch it.
| copy(s.wrapped[top:bottom-n], s.wrapped[top+n:bottom]) | ||
| for row := bottom - n; row < bottom; row++ { | ||
| s.wrapped[row] = false | ||
| } | ||
| if top < bottom { | ||
| s.wrapped[top] = false | ||
| } |
There was a problem hiding this comment.
Unconditional clear of
wrapped[top] after deleteLineWraps copy
After copy(s.wrapped[top:bottom-n], s.wrapped[top+n:bottom]), s.wrapped[top] holds the old value of s.wrapped[top+n]. The code then unconditionally sets s.wrapped[top] = false, silently discarding the copied value. The intent is correct — the promoted line's original predecessor was deleted so it cannot be a continuation of the new top-1 — but a short comment would clarify why the override is always correct, preventing future readers from mistaking it for a bug.
Motivation
LAB-1794: PR #13 squash-merged the upstream sync and left the fork tip without the
vtsoft-wrap APIs amux needs (LineWrappedandCursorPhantom).Summary
origin/cweill/lab-1750-soft-wrap-reflowonto post-syncorigin/main.Emulator.LineWrapped,SafeEmulator.LineWrapped,Emulator.CursorPhantom, andSafeEmulator.CursorPhantom.Testing
cd vt && go mod tidy && go test ./...cd /home/cweill/github/weill-labs/amux && go test -modfile=<temp modfile replacing x/vt with local checkout> ./internal/mux/... -race -timeout 60sgit diff --check origin/main..HEADReview focus
vt/screen.gosoft-wrap metadata preservation across resize.vtAPIs consumed by amux:LineWrappedandCursorPhantom.Closes LAB-1794