Skip to content

Fix rendering duplication, overlap, and input leaks#162

Merged
shellicar merged 3 commits intomainfrom
fix/161-rendering-duplication
Mar 29, 2026
Merged

Fix rendering duplication, overlap, and input leaks#162
shellicar merged 3 commits intomainfrom
fix/161-rendering-duplication

Conversation

@shellicar
Copy link
Copy Markdown
Owner

Summary

  • Prevent display overlap from multi-line strings in history output
  • Block editor input during history scroll mode
  • Remove double render on AppState transitions

Related Issues

Closes #161

Co-Authored-By: Claude noreply@anthropic.com

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.
@shellicar shellicar added this to the 1.0 milestone Mar 29, 2026
@shellicar shellicar added the bug Something isn't working label Mar 29, 2026
@shellicar shellicar self-assigned this Mar 29, 2026
@shellicar shellicar requested a review from bananabot9000 March 29, 2026 20:19
@shellicar shellicar enabled auto-merge (squash) March 29, 2026 20:19
Copy link
Copy Markdown
Collaborator

@bananabot9000 bananabot9000 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Three clean fixes:

  1. 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.

  2. History mode input guard -- early return in handleKey() before editor switch block. Navigation keys handled above, editor input blocked below. Clean separation.

  3. 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

@shellicar shellicar merged commit 678a8bf into main Mar 29, 2026
4 checks passed
@shellicar shellicar deleted the fix/161-rendering-duplication branch March 29, 2026 20:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rendering duplication: text appears duplicated/overlapped, 1 frame behind

2 participants