Fix TUI crash/corruption on code blocks with lines exceeding terminal width (#343)

* Initial plan

* Fix content renderer crash on long lines in code blocks exceeding terminal width

Co-authored-by: glittercowboy <186001655+glittercowboy@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: glittercowboy <186001655+glittercowboy@users.noreply.github.com>
Co-authored-by: TÂCHES <afromanguy@me.com>
This commit is contained in:
Copilot 2026-03-14 06:56:07 -06:00 committed by GitHub
parent 68fa781118
commit 9c1bf837fb
2 changed files with 16 additions and 3 deletions

View file

@ -1,7 +1,7 @@
import { marked, type Token } from "marked";
import { isImageLine } from "../terminal-image.js";
import type { Component } from "../tui.js";
import { applyBackgroundToLine, visibleWidth, wrapTextWithAnsi } from "../utils.js";
import { applyBackgroundToLine, truncateToWidth, visibleWidth, wrapTextWithAnsi } from "../utils.js";
/**
* Default text styling for markdown content.
@ -130,7 +130,16 @@ export class Markdown implements Component {
if (isImageLine(line)) {
wrappedLines.push(line);
} else {
wrappedLines.push(...wrapTextWithAnsi(line, contentWidth));
const wrapped = wrapTextWithAnsi(line, contentWidth);
for (const wl of wrapped) {
// Safety net: silently truncate lines that still exceed contentWidth.
// This handles edge cases like code blocks with very long whitespace
// sequences or tokens that wrapTextWithAnsi cannot split further.
// No ellipsis is used (empty string) to avoid visual noise in code output;
// the truncation is intentional and matches the terminal-width safety
// behavior expected from all TUI components.
wrappedLines.push(visibleWidth(wl) > contentWidth ? truncateToWidth(wl, contentWidth, "") : wl);
}
}
}

View file

@ -903,7 +903,11 @@ export class TUI extends Container {
if (clear) buffer += "\x1b[3J\x1b[2J\x1b[H"; // Clear scrollback, screen, and home
for (let i = 0; i < newLines.length; i++) {
if (i > 0) buffer += "\r\n";
buffer += newLines[i];
let line = newLines[i];
if (!isImageLine(line) && visibleWidth(line) > width) {
line = truncateToWidth(line, width);
}
buffer += line;
}
buffer += "\x1b[?2026l"; // End synchronized output
this.terminal.write(buffer);