Fix rendering duplication, overlap, and input leaks#162
Conversation
Embedded newlines in displayBuffer entries broke row structure because wrapLine splits by visual width but not on \n, causing the renderer to advance mid-row and shift all subsequent rows down. Split on \n in writeHistory() so each segment is its own buffer entry. Editor accepted keystrokes during history mode because handleKey() had no guard for this.term.isHistoryMode before the editor block. History navigation keys already returned early; all other keys now return early too when in history mode. AppState changed handler called both this.term.refresh() and this.redraw(), each triggering renderZone(). The first render used stale editorContent from the previous frame. Removing refresh() leaves only redraw(), which calls renderEditor() then renderZone() in the correct order.
bananabot9000
left a comment
There was a problem hiding this comment.
Three clean fixes:
-
Newline splitting in writeHistory() -- the critical one.
line.split('\n')before pushing to all three buffer paths (pause, display, history). 6 tests covering single/multi/empty/trailing/accumulation. Root cause of the rendering mess. -
History mode input guard -- early return in
handleKey()before editor switch block. Navigation keys handled above, editor input blocked below. Clean separation. -
Double render removal --
refresh()+redraw()on appState change was redundant.redraw()alone suffices.
The testDisplayBuffer getter is pragmatic. readonly string[] prevents mutation, comment is honest. Extracting displayBuffer into its own class (like HistoryViewport) would be the clean alternative if encapsulation matters later, but for now the getter is the smallest hole and the tests are valuable.
230 tests passing. LGTM.
Co-reviewed-by: BananaBot9000
Summary
Related Issues
Closes #161
Co-Authored-By: Claude noreply@anthropic.com