Skip to content
24 changes: 15 additions & 9 deletions extensions/codemode-display/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,14 @@ const ICON_COLOR = {

type Tone = "toolPendingBg" | "toolSuccessBg" | "toolErrorBg";

/** Reapply the block tint after nested foreground styles reset all SGR state. */
function paintBackground(theme: Theme, color: Tone, row: string) {
return row
.split("\u001b[0m")
.map((segment) => theme.bg(color, segment))
.join("\u001b[0m");
}

/** Mirror Pi's default tool shell (padded, tinted block) with a tone derived from all evidence. */
function framed(
theme: Theme,
Expand All @@ -115,15 +123,13 @@ function framed(
if (edges.top) rows.unshift("");
if (edges.bottom()) rows.push("");
const bg = tone();
return rows.map((row) => {
const padded = row + " ".repeat(Math.max(0, width - visibleWidth(row)));
// Pi's truncation/wrapping resets all SGR styles. Reapply the owning
// card background after each reset, including ellipsis and padding.
return padded
.split("\x1b[0m")
.map((segment) => theme.bg(bg, segment))
.join("\x1b[0m");
});
return rows.map((row) =>
paintBackground(
theme,
bg,
row + " ".repeat(Math.max(0, width - visibleWidth(row))),
),
);
},
invalidate() {},
};
Expand Down
18 changes: 18 additions & 0 deletions tests/extensions/codemode-display/render.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,24 @@ test("block tint is green only for a clean ledger, neutral for nested issues and
assert.equal(tone(result("boom"), true), "toolErrorBg");
});

test("truncated rows keep the block background after nested foreground resets", () => {
const ansi = {
fg: (_color: string, text: string) => `\u001b[31m${text}\u001b[0m`,
bg: (_color: string, text: string) => `\u001b[44m${text}\u001b[0m`,
bold: (text: string) => text,
} as Theme;
const rows = codemodeRenderers.renderCall!(
{ code },
ansi,
context(false),
).render(40);
assert.ok(rows.length > 0);
assert.ok(
rows.some((row) => /\u001b\[0m\u001b\[44m/u.test(row)),
"each nested reset must reopen the block background",
);
});

test("compact call rows name their first string argument within the row budget", () => {
const calls = [
{
Expand Down
Loading