@heyhuynhgiabuu/pi-pretty 0.5.1 → 0.5.2
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/package.json +1 -1
- package/src/index.ts +170 -39
- package/test/bash-rendering.test.ts +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@heyhuynhgiabuu/pi-pretty",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "Pretty terminal output for pi — syntax-highlighted file reads, colored bash output, tree-view directory listings, and more.",
|
|
5
5
|
"author": "huynhgiabuu",
|
|
6
6
|
"license": "MIT",
|
package/src/index.ts
CHANGED
|
@@ -185,8 +185,8 @@ function preserveToolBackground(ansi: string, bg: string): string {
|
|
|
185
185
|
});
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
-
function fillToolBackground(text: string, bg = BG_BASE): string {
|
|
189
|
-
|
|
188
|
+
function fillToolBackground(text: string, bg = BG_BASE, width?: number): string {
|
|
189
|
+
if (width === undefined) width = termW();
|
|
190
190
|
return text
|
|
191
191
|
.split("\n")
|
|
192
192
|
.map((line) => {
|
|
@@ -199,9 +199,16 @@ function fillToolBackground(text: string, bg = BG_BASE): string {
|
|
|
199
199
|
}
|
|
200
200
|
|
|
201
201
|
function termW(): number {
|
|
202
|
-
|
|
202
|
+
// When process.stdout.columns is available (real terminal or compositor override),
|
|
203
|
+
// use it directly — the TUI/compositor already provides the exact content width.
|
|
204
|
+
// The -4 safety margin only applies to fallback values (stderr.columns, env.COLUMNS, default).
|
|
205
|
+
if (process.stdout.columns) {
|
|
206
|
+
return Math.max(1, Math.min(process.stdout.columns, 210));
|
|
207
|
+
}
|
|
203
208
|
const raw =
|
|
204
|
-
process.
|
|
209
|
+
(process.stderr as NodeJS.WriteStream & { columns?: number }).columns ||
|
|
210
|
+
Number.parseInt(process.env.COLUMNS ?? "", 10) ||
|
|
211
|
+
200;
|
|
205
212
|
return Math.max(1, Math.min(raw - 4, 210));
|
|
206
213
|
}
|
|
207
214
|
|
|
@@ -605,6 +612,7 @@ async function renderFileContent(
|
|
|
605
612
|
filePath: string,
|
|
606
613
|
offset = 1,
|
|
607
614
|
maxLines = MAX_PREVIEW_LINES,
|
|
615
|
+
width?: number,
|
|
608
616
|
): Promise<string> {
|
|
609
617
|
const normalizedContent = normalizeLineEndings(content);
|
|
610
618
|
const lines = normalizedContent.split("\n");
|
|
@@ -613,7 +621,7 @@ async function renderFileContent(
|
|
|
613
621
|
const lg = lang(filePath);
|
|
614
622
|
const hl = await hlBlock(show.join("\n"), lg);
|
|
615
623
|
|
|
616
|
-
const tw = termW();
|
|
624
|
+
const tw = width ?? termW();
|
|
617
625
|
const startLine = offset;
|
|
618
626
|
const endLine = startLine + show.length - 1;
|
|
619
627
|
const nw = Math.max(3, String(endLine).length);
|
|
@@ -780,6 +788,77 @@ async function renderGrepResults(text: string, pattern: string): Promise<string>
|
|
|
780
788
|
return out.join("\n");
|
|
781
789
|
}
|
|
782
790
|
|
|
791
|
+
// ---------------------------------------------------------------------------
|
|
792
|
+
// Tool metrics — elapsed time + output size
|
|
793
|
+
// pi-droid-styling-inspired: wrap execute to record performance, display in footer.
|
|
794
|
+
// ---------------------------------------------------------------------------
|
|
795
|
+
|
|
796
|
+
const ELAPSED_KEY = "__prettyElapsedMs";
|
|
797
|
+
const CHARS_KEY = "__prettyOutputChars";
|
|
798
|
+
|
|
799
|
+
/** Format milliseconds for display. */
|
|
800
|
+
function formatElapsedMs(ms: number | undefined): string {
|
|
801
|
+
if (typeof ms !== "number" || !Number.isFinite(ms)) return "";
|
|
802
|
+
if (ms < 1000) return `${Math.round(ms)}ms`;
|
|
803
|
+
const s = ms / 1000;
|
|
804
|
+
return s < 10 ? `${s.toFixed(1)}s` : `${Math.round(s)}s`;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
/** Format character count for display. */
|
|
808
|
+
function formatCharCount(chars: number | undefined): string {
|
|
809
|
+
if (typeof chars !== "number" || !Number.isFinite(chars) || chars <= 0) return "";
|
|
810
|
+
if (chars < 1000) return `${chars} chars`;
|
|
811
|
+
if (chars < 10_000) return `${(chars / 1000).toFixed(1)}k chars`;
|
|
812
|
+
return `${Math.round(chars / 1000)}k chars`;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
/** Compute text output length from a tool result. */
|
|
816
|
+
function getOutputCharCount(result: ToolResultLike): number {
|
|
817
|
+
const content = result.content;
|
|
818
|
+
if (!Array.isArray(content)) return 0;
|
|
819
|
+
let length = 0;
|
|
820
|
+
for (const block of content) {
|
|
821
|
+
if (block.type !== "text") continue;
|
|
822
|
+
length += String(block.text ?? "").replace(/\r/g, "").length;
|
|
823
|
+
}
|
|
824
|
+
return length;
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
/**
|
|
828
|
+
* Wrap a tool's execute function to measure elapsed time and output size.
|
|
829
|
+
* Annotates result.details with __prettyElapsedMs and __prettyOutputChars.
|
|
830
|
+
*/
|
|
831
|
+
function wrapExecuteWithMetrics<TParams, TDetails>(
|
|
832
|
+
execute: (...args: any[]) => Promise<ToolResultLike<TDetails>>,
|
|
833
|
+
): ToolExecutor<TParams, TDetails> {
|
|
834
|
+
return async (
|
|
835
|
+
tid: string,
|
|
836
|
+
params: TParams,
|
|
837
|
+
sig?: AbortSignal,
|
|
838
|
+
onUpdate?: AgentToolUpdateCallback<TDetails | undefined>,
|
|
839
|
+
ctx?: ExtensionContext,
|
|
840
|
+
) => {
|
|
841
|
+
const start = performance.now();
|
|
842
|
+
const result = await execute(tid, params, sig, onUpdate, ctx);
|
|
843
|
+
const elapsedMs = performance.now() - start;
|
|
844
|
+
const details = (result.details ?? {}) as Record<string, unknown>;
|
|
845
|
+
details[ELAPSED_KEY] = elapsedMs;
|
|
846
|
+
details[CHARS_KEY] = getOutputCharCount(result);
|
|
847
|
+
(result as { details: Record<string, unknown> }).details = details;
|
|
848
|
+
return result;
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
/** Render a tool metrics line: "3.2s · 14.2k chars" */
|
|
853
|
+
function renderToolMetrics(result: ToolResultLike): string {
|
|
854
|
+
const details = result.details as Record<string, unknown> | undefined;
|
|
855
|
+
if (!details) return "";
|
|
856
|
+
const elapsed = formatElapsedMs(details[ELAPSED_KEY] as number | undefined);
|
|
857
|
+
const chars = formatCharCount(details[CHARS_KEY] as number | undefined);
|
|
858
|
+
if (!elapsed && !chars) return "";
|
|
859
|
+
return `${FG_DIM}· ${[elapsed, chars].filter(Boolean).join(" · ")}${RST}`;
|
|
860
|
+
}
|
|
861
|
+
|
|
783
862
|
// ---------------------------------------------------------------------------
|
|
784
863
|
// FFF integration (optional) — Fast File Finder with frecency & SIMD search
|
|
785
864
|
//
|
|
@@ -1046,6 +1125,53 @@ export default function piPrettyExtension(pi: PiPrettyApi, deps?: PiPrettyDeps):
|
|
|
1046
1125
|
return !disabledTools.has(name.toLowerCase());
|
|
1047
1126
|
}
|
|
1048
1127
|
|
|
1128
|
+
// ===================================================================
|
|
1129
|
+
// Generic renderResult for custom tools (no custom renderer)
|
|
1130
|
+
// ===================================================================
|
|
1131
|
+
|
|
1132
|
+
const origRegisterTool = pi.registerTool.bind(pi);
|
|
1133
|
+
pi.registerTool = (tool: any) => {
|
|
1134
|
+
if (!tool.renderResult && !tool.renderCall) {
|
|
1135
|
+
const toolName = tool.label ?? tool.name ?? "tool";
|
|
1136
|
+
tool.renderResult = (result: any, _opt: unknown, theme: ThemeLike, ctx: RenderContextLike) => {
|
|
1137
|
+
resolveBaseBackground(theme);
|
|
1138
|
+
const text = ctx.lastComponent ?? new TextComponent("", 0, 0);
|
|
1139
|
+
|
|
1140
|
+
if (ctx.isError) {
|
|
1141
|
+
text.setText(renderToolError(getTextContent(result) || "Error", theme));
|
|
1142
|
+
return text;
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
const content = getTextContent(result);
|
|
1146
|
+
if (content) {
|
|
1147
|
+
const renderWidth = termW();
|
|
1148
|
+
const lines = content.split("\n");
|
|
1149
|
+
const maxShow = ctx.expanded ? lines.length : Math.min(lines.length, MAX_PREVIEW_LINES);
|
|
1150
|
+
const preview = lines.slice(0, maxShow).join("\n");
|
|
1151
|
+
const more = lines.length > maxShow ? `\n${FG_DIM}... ${lines.length - maxShow} more lines${RST}` : "";
|
|
1152
|
+
const metrics = renderToolMetrics(result);
|
|
1153
|
+
text.setText(
|
|
1154
|
+
fillToolBackground(` ${preview}${more}${metrics ? `\n ${metrics}` : ""}`, undefined, renderWidth),
|
|
1155
|
+
);
|
|
1156
|
+
} else {
|
|
1157
|
+
text.setText(fillToolBackground(` ${theme.fg("dim", "(no text output)")}`));
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
return text;
|
|
1161
|
+
};
|
|
1162
|
+
|
|
1163
|
+
tool.renderCall = (args: any, theme: ThemeLike, ctx: RenderContextLike) => {
|
|
1164
|
+
resolveBaseBackground(theme);
|
|
1165
|
+
const text = ctx.lastComponent ?? new TextComponent("", 0, 0);
|
|
1166
|
+
text.setText(
|
|
1167
|
+
fillToolBackground(`${theme.fg("toolTitle", theme.bold(toolName))}`),
|
|
1168
|
+
);
|
|
1169
|
+
return text;
|
|
1170
|
+
};
|
|
1171
|
+
}
|
|
1172
|
+
origRegisterTool(tool);
|
|
1173
|
+
};
|
|
1174
|
+
|
|
1049
1175
|
// ===================================================================
|
|
1050
1176
|
// FFF initialization (optional — graceful fallback to SDK)
|
|
1051
1177
|
// ===================================================================
|
|
@@ -1127,13 +1253,13 @@ export default function piPrettyExtension(pi: PiPrettyApi, deps?: PiPrettyDeps):
|
|
|
1127
1253
|
...origRead,
|
|
1128
1254
|
name: "read",
|
|
1129
1255
|
|
|
1130
|
-
async
|
|
1256
|
+
execute: wrapExecuteWithMetrics(async (
|
|
1131
1257
|
tid: string,
|
|
1132
1258
|
params: ReadParams,
|
|
1133
1259
|
sig: AbortSignal | undefined,
|
|
1134
1260
|
upd: AgentToolUpdateCallback<unknown> | undefined,
|
|
1135
1261
|
ctx: ExtensionContext,
|
|
1136
|
-
) {
|
|
1262
|
+
) => {
|
|
1137
1263
|
const result = (await origRead.execute(tid, params, sig, upd, ctx)) as ToolResultLike;
|
|
1138
1264
|
|
|
1139
1265
|
const fp = params.path ?? "";
|
|
@@ -1164,7 +1290,7 @@ export default function piPrettyExtension(pi: PiPrettyApi, deps?: PiPrettyDeps):
|
|
|
1164
1290
|
}
|
|
1165
1291
|
|
|
1166
1292
|
return result;
|
|
1167
|
-
},
|
|
1293
|
+
}),
|
|
1168
1294
|
|
|
1169
1295
|
renderCall(args: ReadParams, theme: ThemeLike, ctx: RenderContextLike) {
|
|
1170
1296
|
resolveBaseBackground(theme);
|
|
@@ -1204,22 +1330,24 @@ export default function piPrettyExtension(pi: PiPrettyApi, deps?: PiPrettyDeps):
|
|
|
1204
1330
|
}
|
|
1205
1331
|
|
|
1206
1332
|
if (d?._type === "readFile" && d.content) {
|
|
1207
|
-
const
|
|
1333
|
+
const renderWidth = termW();
|
|
1334
|
+
const key = `read:${d.filePath}:${d.offset}:${d.lineCount}:${renderWidth}`;
|
|
1208
1335
|
if (ctx.state._rk !== key) {
|
|
1209
1336
|
ctx.state._rk = key;
|
|
1210
|
-
const
|
|
1211
|
-
|
|
1337
|
+
const metrics = renderToolMetrics(result);
|
|
1338
|
+
const info = `${FG_DIM}${d.lineCount} lines${RST}${metrics}`;
|
|
1339
|
+
ctx.state._rt = fillToolBackground(` ${info}`, undefined, renderWidth);
|
|
1212
1340
|
|
|
1213
1341
|
const maxShow = ctx.expanded ? d.lineCount : MAX_PREVIEW_LINES;
|
|
1214
|
-
renderFileContent(d.content, d.filePath, d.offset, maxShow)
|
|
1342
|
+
renderFileContent(d.content, d.filePath, d.offset, maxShow, renderWidth)
|
|
1215
1343
|
.then((rendered: string) => {
|
|
1216
1344
|
if (ctx.state._rk !== key) return;
|
|
1217
|
-
ctx.state._rt = fillToolBackground(` ${info}\n${rendered}
|
|
1345
|
+
ctx.state._rt = fillToolBackground(` ${info}\n${rendered}`, undefined, renderWidth);
|
|
1218
1346
|
ctx.invalidate();
|
|
1219
1347
|
})
|
|
1220
1348
|
.catch(() => {});
|
|
1221
1349
|
}
|
|
1222
|
-
text.setText(ctx.state._rt ?? fillToolBackground(` ${FG_DIM}${d.lineCount} lines${RST}
|
|
1350
|
+
text.setText(ctx.state._rt ?? fillToolBackground(` ${FG_DIM}${d.lineCount} lines${RST}${renderToolMetrics(result)}`, undefined, renderWidth));
|
|
1223
1351
|
return text;
|
|
1224
1352
|
}
|
|
1225
1353
|
|
|
@@ -1243,13 +1371,13 @@ export default function piPrettyExtension(pi: PiPrettyApi, deps?: PiPrettyDeps):
|
|
|
1243
1371
|
...origBash,
|
|
1244
1372
|
name: "bash",
|
|
1245
1373
|
|
|
1246
|
-
async
|
|
1374
|
+
execute: wrapExecuteWithMetrics(async (
|
|
1247
1375
|
tid: string,
|
|
1248
1376
|
params: BashParams,
|
|
1249
1377
|
sig: AbortSignal | undefined,
|
|
1250
1378
|
upd: AgentToolUpdateCallback<unknown> | undefined,
|
|
1251
1379
|
ctx: ExtensionContext,
|
|
1252
|
-
) {
|
|
1380
|
+
) => {
|
|
1253
1381
|
const result = (await origBash.execute(tid, params, sig, upd, ctx)) as ToolResultLike;
|
|
1254
1382
|
const textContent = getTextContent(result);
|
|
1255
1383
|
|
|
@@ -1270,7 +1398,7 @@ export default function piPrettyExtension(pi: PiPrettyApi, deps?: PiPrettyDeps):
|
|
|
1270
1398
|
});
|
|
1271
1399
|
|
|
1272
1400
|
return result;
|
|
1273
|
-
},
|
|
1401
|
+
}),
|
|
1274
1402
|
|
|
1275
1403
|
renderCall(args: BashParams, theme: ThemeLike, ctx: RenderContextLike) {
|
|
1276
1404
|
resolveBaseBackground(theme);
|
|
@@ -1300,7 +1428,7 @@ export default function piPrettyExtension(pi: PiPrettyApi, deps?: PiPrettyDeps):
|
|
|
1300
1428
|
const { summary } = renderBashOutput(d.text, d.exitCode);
|
|
1301
1429
|
const lines = d.text.split("\n");
|
|
1302
1430
|
const lineCount = lines.length;
|
|
1303
|
-
const lineInfo = lineCount > 1 ? ` ${FG_DIM}(${lineCount} lines)${RST}` :
|
|
1431
|
+
const lineInfo = lineCount > 1 ? ` ${FG_DIM}(${lineCount} lines)${RST} ${renderToolMetrics(result)}` : ` ${renderToolMetrics(result)}`;
|
|
1304
1432
|
const header = ` ${summary}${lineInfo}`;
|
|
1305
1433
|
|
|
1306
1434
|
if (d.text.trim()) {
|
|
@@ -1341,13 +1469,13 @@ export default function piPrettyExtension(pi: PiPrettyApi, deps?: PiPrettyDeps):
|
|
|
1341
1469
|
...origLs,
|
|
1342
1470
|
name: "ls",
|
|
1343
1471
|
|
|
1344
|
-
async
|
|
1472
|
+
execute: wrapExecuteWithMetrics(async (
|
|
1345
1473
|
tid: string,
|
|
1346
1474
|
params: LsParams,
|
|
1347
1475
|
sig: AbortSignal | undefined,
|
|
1348
1476
|
upd: AgentToolUpdateCallback<unknown> | undefined,
|
|
1349
1477
|
ctx: ExtensionContext,
|
|
1350
|
-
) {
|
|
1478
|
+
) => {
|
|
1351
1479
|
const result = (await origLs.execute(tid, params, sig, upd, ctx)) as ToolResultLike;
|
|
1352
1480
|
const textContent = getTextContent(result);
|
|
1353
1481
|
const fp = params.path ?? cwd;
|
|
@@ -1361,7 +1489,7 @@ export default function piPrettyExtension(pi: PiPrettyApi, deps?: PiPrettyDeps):
|
|
|
1361
1489
|
});
|
|
1362
1490
|
|
|
1363
1491
|
return result;
|
|
1364
|
-
},
|
|
1492
|
+
}),
|
|
1365
1493
|
|
|
1366
1494
|
renderCall(args: LsParams, theme: ThemeLike, ctx: RenderContextLike) {
|
|
1367
1495
|
resolveBaseBackground(theme);
|
|
@@ -1383,7 +1511,7 @@ export default function piPrettyExtension(pi: PiPrettyApi, deps?: PiPrettyDeps):
|
|
|
1383
1511
|
const d = result.details as RenderDetails | undefined;
|
|
1384
1512
|
if (d?._type === "lsResult" && d.text) {
|
|
1385
1513
|
const tree = renderTree(d.text, d.path);
|
|
1386
|
-
const info = `${FG_DIM}${d.entryCount} entries${RST}`;
|
|
1514
|
+
const info = `${FG_DIM}${d.entryCount} entries${RST}${renderToolMetrics(result)}`;
|
|
1387
1515
|
text.setText(fillToolBackground(` ${info}\n${tree}`));
|
|
1388
1516
|
return text;
|
|
1389
1517
|
}
|
|
@@ -1407,13 +1535,13 @@ export default function piPrettyExtension(pi: PiPrettyApi, deps?: PiPrettyDeps):
|
|
|
1407
1535
|
...origFind,
|
|
1408
1536
|
name: "find",
|
|
1409
1537
|
|
|
1410
|
-
async
|
|
1538
|
+
execute: wrapExecuteWithMetrics(async (
|
|
1411
1539
|
tid: string,
|
|
1412
1540
|
params: FindParams,
|
|
1413
1541
|
sig: AbortSignal | undefined,
|
|
1414
1542
|
upd: unknown,
|
|
1415
1543
|
ctx: ExtensionContext,
|
|
1416
|
-
) {
|
|
1544
|
+
) => {
|
|
1417
1545
|
// Try FFF first (frecency-ranked, SIMD-accelerated)
|
|
1418
1546
|
if (_fffFinder && !_fffFinder.isDestroyed) {
|
|
1419
1547
|
try {
|
|
@@ -1456,7 +1584,7 @@ export default function piPrettyExtension(pi: PiPrettyApi, deps?: PiPrettyDeps):
|
|
|
1456
1584
|
});
|
|
1457
1585
|
|
|
1458
1586
|
return result;
|
|
1459
|
-
},
|
|
1587
|
+
}),
|
|
1460
1588
|
|
|
1461
1589
|
renderCall(args: FindParams, theme: ThemeLike, ctx: RenderContextLike) {
|
|
1462
1590
|
resolveBaseBackground(theme);
|
|
@@ -1486,7 +1614,7 @@ export default function piPrettyExtension(pi: PiPrettyApi, deps?: PiPrettyDeps):
|
|
|
1486
1614
|
const d = result.details;
|
|
1487
1615
|
if (d?._type === "findResult" && d.text) {
|
|
1488
1616
|
const rendered = renderFindResults(d.text);
|
|
1489
|
-
const info = `${FG_DIM}${d.matchCount} files${RST}`;
|
|
1617
|
+
const info = `${FG_DIM}${d.matchCount} files${RST}${renderToolMetrics(result)}`;
|
|
1490
1618
|
text.setText(fillToolBackground(` ${info}\n${rendered}`));
|
|
1491
1619
|
return text;
|
|
1492
1620
|
}
|
|
@@ -1510,13 +1638,13 @@ export default function piPrettyExtension(pi: PiPrettyApi, deps?: PiPrettyDeps):
|
|
|
1510
1638
|
...origGrep,
|
|
1511
1639
|
name: "grep",
|
|
1512
1640
|
|
|
1513
|
-
async
|
|
1641
|
+
execute: wrapExecuteWithMetrics(async (
|
|
1514
1642
|
tid: string,
|
|
1515
1643
|
params: GrepParams,
|
|
1516
1644
|
sig: AbortSignal | undefined,
|
|
1517
1645
|
upd: unknown,
|
|
1518
1646
|
ctx: ExtensionContext,
|
|
1519
|
-
) {
|
|
1647
|
+
) => {
|
|
1520
1648
|
// Try FFF first (SIMD-accelerated, frecency-ranked).
|
|
1521
1649
|
// FFF 0.5.2 can abort the process when path/glob constraints meet
|
|
1522
1650
|
// Unicode filenames, so constrained searches use the SDK fallback.
|
|
@@ -1576,7 +1704,7 @@ export default function piPrettyExtension(pi: PiPrettyApi, deps?: PiPrettyDeps):
|
|
|
1576
1704
|
});
|
|
1577
1705
|
|
|
1578
1706
|
return result;
|
|
1579
|
-
},
|
|
1707
|
+
}),
|
|
1580
1708
|
|
|
1581
1709
|
renderCall(args: GrepParams, theme: ThemeLike, ctx: RenderContextLike) {
|
|
1582
1710
|
resolveBaseBackground(theme);
|
|
@@ -1608,21 +1736,23 @@ export default function piPrettyExtension(pi: PiPrettyApi, deps?: PiPrettyDeps):
|
|
|
1608
1736
|
|
|
1609
1737
|
const d = result.details;
|
|
1610
1738
|
if (d?._type === "grepResult" && d.text) {
|
|
1611
|
-
const
|
|
1739
|
+
const renderWidth = termW();
|
|
1740
|
+
const key = `grep:${d.pattern}:${d.matchCount}:${renderWidth}`;
|
|
1612
1741
|
if (ctx.state._gk !== key) {
|
|
1613
1742
|
ctx.state._gk = key;
|
|
1614
|
-
const
|
|
1615
|
-
|
|
1743
|
+
const metrics = renderToolMetrics(result);
|
|
1744
|
+
const info = `${FG_DIM}${d.matchCount} matches${RST}${metrics}`;
|
|
1745
|
+
ctx.state._gt = fillToolBackground(` ${info}`, undefined, renderWidth);
|
|
1616
1746
|
|
|
1617
1747
|
renderGrepResults(d.text, d.pattern)
|
|
1618
1748
|
.then((rendered: string) => {
|
|
1619
1749
|
if (ctx.state._gk !== key) return;
|
|
1620
|
-
ctx.state._gt = fillToolBackground(` ${info}\n${rendered}
|
|
1750
|
+
ctx.state._gt = fillToolBackground(` ${info}\n${rendered}`, undefined, renderWidth);
|
|
1621
1751
|
ctx.invalidate();
|
|
1622
1752
|
})
|
|
1623
1753
|
.catch(() => {});
|
|
1624
1754
|
}
|
|
1625
|
-
text.setText(ctx.state._gt ?? fillToolBackground(` ${FG_DIM}${d.matchCount} matches${RST}
|
|
1755
|
+
text.setText(ctx.state._gt ?? fillToolBackground(` ${FG_DIM}${d.matchCount} matches${RST}${renderToolMetrics(result)}`, undefined, renderWidth));
|
|
1626
1756
|
return text;
|
|
1627
1757
|
}
|
|
1628
1758
|
|
|
@@ -1689,13 +1819,13 @@ export default function piPrettyExtension(pi: PiPrettyApi, deps?: PiPrettyDeps):
|
|
|
1689
1819
|
required: ["patterns"],
|
|
1690
1820
|
},
|
|
1691
1821
|
|
|
1692
|
-
async
|
|
1822
|
+
execute: wrapExecuteWithMetrics(async (
|
|
1693
1823
|
tid: string,
|
|
1694
1824
|
params: MultiGrepParams,
|
|
1695
1825
|
sig: AbortSignal | undefined,
|
|
1696
1826
|
upd: unknown,
|
|
1697
1827
|
ctx: ExtensionContext,
|
|
1698
|
-
) {
|
|
1828
|
+
) => {
|
|
1699
1829
|
if (sig?.aborted) return makeTextResult("Aborted", {});
|
|
1700
1830
|
|
|
1701
1831
|
if (!params.patterns || params.patterns.length === 0) {
|
|
@@ -1813,7 +1943,7 @@ export default function piPrettyExtension(pi: PiPrettyApi, deps?: PiPrettyDeps):
|
|
|
1813
1943
|
const message = getErrorMessage(error);
|
|
1814
1944
|
return makeTextResult(`multi_grep error: ${message}`, { error: message });
|
|
1815
1945
|
}
|
|
1816
|
-
},
|
|
1946
|
+
}),
|
|
1817
1947
|
|
|
1818
1948
|
renderCall(args: MultiGrepParams, theme: ThemeLike, ctx: RenderContextLike) {
|
|
1819
1949
|
resolveBaseBackground(theme);
|
|
@@ -1850,7 +1980,8 @@ export default function piPrettyExtension(pi: PiPrettyApi, deps?: PiPrettyDeps):
|
|
|
1850
1980
|
const key = `mgrep:${d.pattern}:${d.matchCount}:${termW()}`;
|
|
1851
1981
|
if (ctx.state._mgk !== key) {
|
|
1852
1982
|
ctx.state._mgk = key;
|
|
1853
|
-
const
|
|
1983
|
+
const metrics = renderToolMetrics(result);
|
|
1984
|
+
const info = `${FG_DIM}${d.matchCount} matches${RST}${metrics}`;
|
|
1854
1985
|
ctx.state._mgt = ` ${info}`;
|
|
1855
1986
|
|
|
1856
1987
|
renderGrepResults(d.text, d.pattern)
|
|
@@ -1861,7 +1992,7 @@ export default function piPrettyExtension(pi: PiPrettyApi, deps?: PiPrettyDeps):
|
|
|
1861
1992
|
})
|
|
1862
1993
|
.catch(() => {});
|
|
1863
1994
|
}
|
|
1864
|
-
text.setText(ctx.state._mgt ?? ` ${FG_DIM}${d.matchCount} matches${RST}`);
|
|
1995
|
+
text.setText(ctx.state._mgt ?? ` ${FG_DIM}${d.matchCount} matches${RST}${renderToolMetrics(result)}`);
|
|
1865
1996
|
return text;
|
|
1866
1997
|
}
|
|
1867
1998
|
|
|
@@ -141,7 +141,7 @@ describe("bash renderCall expansion", () => {
|
|
|
141
141
|
});
|
|
142
142
|
|
|
143
143
|
for (const line of rendered.getText().split("\n")) {
|
|
144
|
-
expect(visibleWidth(line)).toBeLessThanOrEqual(
|
|
144
|
+
expect(visibleWidth(line)).toBeLessThanOrEqual(84);
|
|
145
145
|
}
|
|
146
146
|
});
|
|
147
147
|
});
|
|
@@ -160,7 +160,7 @@ describe("bash renderCall expansion", () => {
|
|
|
160
160
|
});
|
|
161
161
|
|
|
162
162
|
for (const line of rendered.getText().split("\n")) {
|
|
163
|
-
expect(visibleWidth(line)).toBeLessThanOrEqual(
|
|
163
|
+
expect(visibleWidth(line)).toBeLessThanOrEqual(24);
|
|
164
164
|
}
|
|
165
165
|
});
|
|
166
166
|
});
|