From 31d7f1951a558fd98e9ca2184d3b5e45aff2cfd9 Mon Sep 17 00:00:00 2001 From: Brooklyn Nicholson Date: Sat, 25 Apr 2026 15:32:45 -0500 Subject: [PATCH] fix(tui): clamp copied selection bounds Clamp copied selection columns to the screen width before scanning rendered cells. --- ui-tui/packages/hermes-ink/src/ink/selection.test.ts | 10 ++++++++++ ui-tui/packages/hermes-ink/src/ink/selection.ts | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/ui-tui/packages/hermes-ink/src/ink/selection.test.ts b/ui-tui/packages/hermes-ink/src/ink/selection.test.ts index 0e0fba6573..83d77bf35d 100644 --- a/ui-tui/packages/hermes-ink/src/ink/selection.test.ts +++ b/ui-tui/packages/hermes-ink/src/ink/selection.test.ts @@ -55,6 +55,16 @@ describe('selection whitespace handling', () => { expect(getSelectedText(selection, screen)).toBe(' x') }) + it('clamps copied selection bounds to screen width', () => { + const { screen } = screenWithText() + const selection = createSelectionState() + + startSelection(selection, 0, 1) + updateSelection(selection, 99, 1) + + expect(getSelectedText(selection, screen)).toBe('hi') + }) + it('does not paint selection background on leading/trailing empty cells or empty rows', () => { const { screen, styles } = screenWithText() const selection = createSelectionState() diff --git a/ui-tui/packages/hermes-ink/src/ink/selection.ts b/ui-tui/packages/hermes-ink/src/ink/selection.ts index 7c7505540b..76e776c22e 100644 --- a/ui-tui/packages/hermes-ink/src/ink/selection.ts +++ b/ui-tui/packages/hermes-ink/src/ink/selection.ts @@ -969,8 +969,8 @@ export function getSelectedText(s: SelectionState, screen: Screen): string { } for (let row = start.row; row <= end.row; row++) { - const rowStart = row === start.row ? start.col : 0 - const rowEnd = row === end.row ? end.col : screen.width - 1 + const rowStart = Math.max(0, row === start.row ? start.col : 0) + const rowEnd = Math.min(row === end.row ? end.col : screen.width - 1, screen.width - 1) const bounds = selectionContentBounds(screen, row, rowStart, rowEnd) joinRows(lines, bounds ? extractRowText(screen, row, bounds.first, bounds.last) : '', sw[row]! > 0)