fix(patch): wrapped long diff lines with continuation gutters

- Replaced truncation with line wrapping for diff output in the edit tool renderer.
- Added `wrapEditRendererLine` to preserve gutter markers and line numbers on continuation lines.
Fixes #578
This commit is contained in:
can1357
2026-04-01 04:52:03 +02:00
parent 6645a7a059
commit 77eddf80e9
2 changed files with 26 additions and 3 deletions
+25 -3
View File
@@ -3,7 +3,7 @@
*/
import type { ToolCallContext } from "@oh-my-pi/pi-agent-core";
import type { Component } from "@oh-my-pi/pi-tui";
import { Text } from "@oh-my-pi/pi-tui";
import { Text, visibleWidth, wrapTextWithAnsi } from "@oh-my-pi/pi-tui";
import type { RenderResultOptions } from "../extensibility/custom-tools/types";
import type { FileDiagnosticsResult } from "../lsp";
import { renderDiff as renderDiffColored } from "../modes/components/diff";
@@ -222,6 +222,29 @@ function renderDiffSection(
return text;
}
function wrapEditRendererLine(line: string, width: number): string[] {
if (width <= 0) return [line];
if (line.length === 0) return [""];
const startAnsi = line.match(/^((?:\x1b\[[0-9;]*m)*)/)?.[1] ?? "";
const bodyWithReset = line.slice(startAnsi.length);
const body = bodyWithReset.endsWith("\x1b[39m") ? bodyWithReset.slice(0, -"\x1b[39m".length) : bodyWithReset;
const diffMatch = /^([+\-\s])(\s*\d+)\|(.*)$/s.exec(body);
if (!diffMatch) {
return wrapTextWithAnsi(line, width);
}
const [, marker, lineNum, content] = diffMatch;
const prefix = `${marker}${lineNum}|`;
const prefixWidth = visibleWidth(prefix);
const contentWidth = Math.max(1, width - prefixWidth);
const continuationPrefix = `${" ".repeat(Math.max(0, prefixWidth - 1))}|`;
const wrappedContent = wrapTextWithAnsi(content, contentWidth);
return wrappedContent.map((segment, index) => `${startAnsi}${index === 0 ? prefix : continuationPrefix}${segment}\x1b[39m`);
}
export const editToolRenderer = {
mergeCallAndResult: true,
@@ -356,8 +379,7 @@ export const editToolRenderer = {
);
}
const lines =
width > 0 ? text.split("\n").map(line => truncateToWidth(line, width, Ellipsis.Omit)) : text.split("\n");
const lines = width > 0 ? text.split("\n").flatMap(line => wrapEditRendererLine(line, width)) : text.split("\n");
cached = { key, lines };
return lines;
},