pi-pretty-tui 0.3.4 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/extensions/edit-diff.ts +6 -3
- package/extensions/index.ts +51 -6
- package/package.json +1 -1
package/extensions/edit-diff.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getLanguageFromPath, highlightCode } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import { sliceByColumn, visibleWidth } from "@earendil-works/pi-tui";
|
|
2
|
+
import { mixColors, sliceByColumn, visibleWidth } from "@earendil-works/pi-tui";
|
|
3
3
|
|
|
4
4
|
type Range = [number, number];
|
|
5
5
|
type Row = { marker: string; number?: string; text: string; styled: string; changes: Range[] };
|
|
@@ -82,13 +82,16 @@ export function editDiffLayout(theme: any, diff: string, path?: string) {
|
|
|
82
82
|
const color = row.marker === "+" ? "toolDiffAdded" : row.marker === "-" ? "toolDiffRemoved" : "toolDiffContext";
|
|
83
83
|
const background = row.marker === "+" ? "toolSuccessBg" : row.marker === "-" ? "toolErrorBg" : undefined;
|
|
84
84
|
const paint = (text: string) => background && theme.bg ? theme.bg(background, text) : text;
|
|
85
|
+
const changeBackground = background && theme.colors?.[background] && theme.colors?.[color]
|
|
86
|
+
? mixColors(theme.colors[background], theme.colors[color], 0.3) : undefined;
|
|
85
87
|
const width = visibleWidth(row.text);
|
|
86
88
|
let content = "", cursor = 0;
|
|
87
89
|
for (const [start, end] of row.changes) {
|
|
88
90
|
content += sliceByColumn(row.styled, cursor, start - cursor);
|
|
89
91
|
const changed = sliceByColumn(row.styled, start, end - start);
|
|
90
|
-
//
|
|
91
|
-
|
|
92
|
+
// A stronger theme-derived background preserves syntax foregrounds and
|
|
93
|
+
// avoids adding font emphasis to the changed graphemes.
|
|
94
|
+
content += changeBackground && theme.style ? theme.style(changed, { bg: changeBackground }) : paint(changed);
|
|
92
95
|
cursor = end;
|
|
93
96
|
}
|
|
94
97
|
content += sliceByColumn(row.styled, cursor, Math.max(0, width - cursor));
|
package/extensions/index.ts
CHANGED
|
@@ -37,12 +37,15 @@ import {
|
|
|
37
37
|
copyToClipboard,
|
|
38
38
|
getAgentDir,
|
|
39
39
|
getMarkdownTheme,
|
|
40
|
+
getLanguageFromPath,
|
|
41
|
+
highlightCode,
|
|
40
42
|
type ExtensionAPI,
|
|
41
43
|
} from "@earendil-works/pi-coding-agent";
|
|
42
44
|
import {
|
|
43
45
|
type Component,
|
|
44
46
|
Markdown,
|
|
45
47
|
stripTerminalSequences,
|
|
48
|
+
sliceByColumn,
|
|
46
49
|
truncateToWidth,
|
|
47
50
|
TuiAltScreen,
|
|
48
51
|
type TuiMouseEvent,
|
|
@@ -2828,8 +2831,22 @@ export default function prettyTui(pi: ExtensionAPI) {
|
|
|
2828
2831
|
|
|
2829
2832
|
const paint = (line: string) => row.background
|
|
2830
2833
|
? row.background(line + " ".repeat(Math.max(0, contentWidth - visibleWidth(line)))) : line;
|
|
2831
|
-
|
|
2832
|
-
|
|
2834
|
+
const corner = renderMode === "clean" ? stripTerminalSequences(prefix).indexOf("└") : -1;
|
|
2835
|
+
if (corner >= 0 && wrapped.length > 1) {
|
|
2836
|
+
// Close the branch on the final physical row, not the first row of
|
|
2837
|
+
// a logical source line that may wrap or contain explicit newlines.
|
|
2838
|
+
const column = visibleWidth(stripTerminalSequences(prefix).slice(0, corner));
|
|
2839
|
+
const guide = (symbol: string) => sliceByColumn(continuation, 0, column) +
|
|
2840
|
+
defaultActivityTheme().fg("dim", symbol) +
|
|
2841
|
+
sliceByColumn(continuation, column + 1, Math.max(0, visibleWidth(continuation) - column - 1));
|
|
2842
|
+
rendered.push(prefix.replace("└", "│") + paint(wrapped[0] ?? ""));
|
|
2843
|
+
for (let index = 1; index < wrapped.length; index++) {
|
|
2844
|
+
rendered.push(guide(index === wrapped.length - 1 ? "└" : "│") + paint(wrapped[index]));
|
|
2845
|
+
}
|
|
2846
|
+
} else {
|
|
2847
|
+
rendered.push(prefix + paint(wrapped[0] ?? ""));
|
|
2848
|
+
for (const line of wrapped.slice(1)) rendered.push(continuation + paint(line));
|
|
2849
|
+
}
|
|
2833
2850
|
}
|
|
2834
2851
|
|
|
2835
2852
|
return rendered;
|
|
@@ -2850,7 +2867,8 @@ export default function prettyTui(pi: ExtensionAPI) {
|
|
|
2850
2867
|
if (renderMode === "compact") return name === "bash" ? theme.fg("toolTitle", "$ ") : "";
|
|
2851
2868
|
return theme.fg(color, "● ");
|
|
2852
2869
|
},
|
|
2853
|
-
continuation: renderMode === "
|
|
2870
|
+
continuation: renderMode === "clean" && expanded ? theme.fg("dim", "│ ") :
|
|
2871
|
+
renderMode === "compact" && name !== "bash" ? "" : " ",
|
|
2854
2872
|
content: renderMode === "compact" ? theme.fg("muted", detail) :
|
|
2855
2873
|
theme.fg("text", theme.bold(name)) +
|
|
2856
2874
|
theme.fg("dim", "(") +
|
|
@@ -3569,7 +3587,7 @@ export default function prettyTui(pi: ExtensionAPI) {
|
|
|
3569
3587
|
const dimPhase = responseRunStartedAt !== undefined &&
|
|
3570
3588
|
Math.floor(Math.max(0, Date.now() - responseRunStartedAt) / RUNNING_DOT_INTERVAL_MS) % 2 === 1;
|
|
3571
3589
|
const color = currentActivity === "done"
|
|
3572
|
-
? collapsedDone ? "dim" : "
|
|
3590
|
+
? collapsedDone ? "dim" : "text"
|
|
3573
3591
|
: dimPhase ? "dim" : "accent";
|
|
3574
3592
|
return currentActivity !== "done" && !dimPhase
|
|
3575
3593
|
? runningColor(theme, "● ")
|
|
@@ -3580,7 +3598,7 @@ export default function prettyTui(pi: ExtensionAPI) {
|
|
|
3580
3598
|
const currentActivity = typeof activity === "function" ? activity() : activity;
|
|
3581
3599
|
const label = currentActivity === "done" ? "Done" : "Running";
|
|
3582
3600
|
const color = label === "Done"
|
|
3583
|
-
? collapsedDone ? "dim" : "
|
|
3601
|
+
? collapsedDone ? "dim" : "text"
|
|
3584
3602
|
: "accent";
|
|
3585
3603
|
const detailColor = label === "Done" && collapsedDone ? "dim" : "text";
|
|
3586
3604
|
const title = label === "Running"
|
|
@@ -4652,7 +4670,7 @@ export default function prettyTui(pi: ExtensionAPI) {
|
|
|
4652
4670
|
if (hideCleanTool(context.toolCallId, context.expanded, context.executionStarted)) return cleanToolCall(theme, writeLabel, context.toolCallId);
|
|
4653
4671
|
const content = typeof args.content === "string" ? args.content : "";
|
|
4654
4672
|
const path = String(args.path ?? "");
|
|
4655
|
-
if (useCompactToolView(context.toolCallId, context.expanded)) {
|
|
4673
|
+
if (renderMode === "clean" || useCompactToolView(context.toolCallId, context.expanded)) {
|
|
4656
4674
|
const lines = content.replace(/\t/g, " ").split("\n");
|
|
4657
4675
|
while (lines.length > 0 && lines[lines.length - 1] === "") lines.pop();
|
|
4658
4676
|
const total = lines.length;
|
|
@@ -4665,6 +4683,33 @@ export default function prettyTui(pi: ExtensionAPI) {
|
|
|
4665
4683
|
if (hideCleanTool(context.toolCallId, options.expanded, context.executionStarted)) return hiddenToolResult(context, options, output);
|
|
4666
4684
|
if (options.isPartial) return partialResult(context, theme, "Writing…");
|
|
4667
4685
|
const failed = completeStatus(context);
|
|
4686
|
+
if (renderMode === "clean") {
|
|
4687
|
+
if (failed) return result(theme, "Write failed", output, options.expanded, true);
|
|
4688
|
+
const status = output ? `Written · ${output}` : "Written";
|
|
4689
|
+
const rows: DisplayRow[] = [{
|
|
4690
|
+
prefix: theme.fg("dim", "└ "), continuation: " ",
|
|
4691
|
+
content: theme.fg("toolOutput", status),
|
|
4692
|
+
}];
|
|
4693
|
+
if (options.expanded) {
|
|
4694
|
+
const content = typeof context.args?.content === "string" ? context.args.content : "";
|
|
4695
|
+
const source = content.replace(/\r\n|\r/g, "\n").replace(/\t/g, " ").split("\n");
|
|
4696
|
+
// A final newline terminates the last line; additional blank lines
|
|
4697
|
+
// are actual file content and retain their own line numbers.
|
|
4698
|
+
if (source.at(-1) === "") source.pop();
|
|
4699
|
+
let highlighted: string[];
|
|
4700
|
+
try { highlighted = highlightCode(source.join("\n"), getLanguageFromPath(String(context.args?.path ?? ""))); }
|
|
4701
|
+
catch { highlighted = source; }
|
|
4702
|
+
const digits = String(source.length).length;
|
|
4703
|
+
for (let index = 0; index < source.length; index++) {
|
|
4704
|
+
rows.push({
|
|
4705
|
+
prefix: theme.fg("dim", index === source.length - 1 ? " └ " : " │ ") + theme.fg("dim", `${String(index + 1).padStart(digits)} `),
|
|
4706
|
+
continuation: (index === source.length - 1 ? " " : theme.fg("dim", " │ ")) + " ".repeat(digits + 1),
|
|
4707
|
+
content: highlighted[index] ?? source[index],
|
|
4708
|
+
});
|
|
4709
|
+
}
|
|
4710
|
+
}
|
|
4711
|
+
return block(rows);
|
|
4712
|
+
}
|
|
4668
4713
|
return result(
|
|
4669
4714
|
theme,
|
|
4670
4715
|
failed ? output.split("\n")[0] || "Write failed" : "Written",
|