@zigai/pi-footer 0.1.1 → 0.1.4
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/README.md +12 -4
- package/package.json +11 -3
- package/src/footer-rendering.ts +21 -33
- package/src/types.ts +0 -1
package/README.md
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
# Pi Footer
|
|
2
2
|
|
|
3
|
-
Pi
|
|
3
|
+
This Pi extension replaces Pi's footer with a single compact plain-text status line.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The footer keeps key session information visible without taking much space:
|
|
6
|
+
|
|
7
|
+
- current working directory
|
|
8
|
+
- git branch
|
|
9
|
+
- provider and model
|
|
10
|
+
- thinking level
|
|
11
|
+
- MCP status
|
|
12
|
+
- context usage
|
|
13
|
+
- a short post-run summary with total agent time and output token speed
|
|
6
14
|
|
|
7
|
-
|
|
15
|
+
## Install
|
|
8
16
|
|
|
9
17
|
```sh
|
|
10
|
-
pi install
|
|
18
|
+
pi install git:github.com/zigai/pi-ux-tweaks
|
|
11
19
|
```
|
package/package.json
CHANGED
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zigai/pi-footer",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Pi package for a custom footer and worked-for token speed widget.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"footer",
|
|
7
|
+
"pi",
|
|
8
|
+
"pi-coding-agent",
|
|
7
9
|
"pi-extension",
|
|
8
10
|
"pi-package",
|
|
9
|
-
"pi-
|
|
11
|
+
"pi-ux"
|
|
10
12
|
],
|
|
13
|
+
"homepage": "https://github.com/zigai/pi-ux-tweaks/tree/main/packages/pi-footer#readme",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/zigai/pi-ux-tweaks/issues"
|
|
16
|
+
},
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"author": "zigai",
|
|
11
19
|
"repository": {
|
|
12
20
|
"type": "git",
|
|
13
|
-
"url": "git+https://github.com/zigai/pi-
|
|
21
|
+
"url": "git+https://github.com/zigai/pi-ux-tweaks.git",
|
|
14
22
|
"directory": "packages/pi-footer"
|
|
15
23
|
},
|
|
16
24
|
"files": [
|
package/src/footer-rendering.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
3
|
-
import { pathToFileURL } from "node:url";
|
|
4
3
|
|
|
5
4
|
import {
|
|
6
5
|
ACTIVE_FOOTER_VARIANT,
|
|
@@ -73,31 +72,16 @@ function ansiColor(text: string, options: { fg?: string; bg?: string; bold?: boo
|
|
|
73
72
|
return `\x1b[${codes.join(";")}m${text}\x1b[0m`;
|
|
74
73
|
}
|
|
75
74
|
|
|
76
|
-
function hyperlink(text: string, url: string): string {
|
|
77
|
-
if (!process.stdout.isTTY) {
|
|
78
|
-
return url;
|
|
79
|
-
}
|
|
80
|
-
return `\x1b]8;;${url}\x1b\\${text}\x1b]8;;\x1b\\`;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
75
|
function renderColoredText(text: string, colors: SegmentColors): string {
|
|
84
76
|
return ansiColor(text, { fg: colors.fg, bg: colors.bg });
|
|
85
77
|
}
|
|
86
78
|
|
|
87
79
|
function renderBlockItem(item: FooterItem): string {
|
|
88
|
-
|
|
89
|
-
if (item.url !== undefined && item.url.length > 0) {
|
|
90
|
-
linked = hyperlink(` ${item.text} `, item.url);
|
|
91
|
-
}
|
|
92
|
-
return renderColoredText(linked, item.colors);
|
|
80
|
+
return renderColoredText(` ${item.text} `, item.colors);
|
|
93
81
|
}
|
|
94
82
|
|
|
95
83
|
function renderPlainItem(item: FooterItem): string {
|
|
96
|
-
|
|
97
|
-
if (item.url !== undefined && item.url.length > 0) {
|
|
98
|
-
linked = hyperlink(item.text, item.url);
|
|
99
|
-
}
|
|
100
|
-
return renderColoredText(linked, PLAIN_COLORS);
|
|
84
|
+
return renderColoredText(item.text, PLAIN_COLORS);
|
|
101
85
|
}
|
|
102
86
|
|
|
103
87
|
function getProviderDisplayName(provider: string): string {
|
|
@@ -239,7 +223,6 @@ function buildFooterItems(
|
|
|
239
223
|
): Partial<Record<FooterKey, FooterItem>> {
|
|
240
224
|
const branch = footerData.getGitBranch();
|
|
241
225
|
const pathText = collapseHome(ctx.cwd);
|
|
242
|
-
const pathUrl = pathToFileURL(ctx.cwd).href;
|
|
243
226
|
const providerId = ctx.model?.provider ?? "no-provider";
|
|
244
227
|
const providerLabel = getProviderDisplayName(providerId);
|
|
245
228
|
const modelLabel = ctx.model?.id ?? "no-model";
|
|
@@ -251,7 +234,6 @@ function buildFooterItems(
|
|
|
251
234
|
path: {
|
|
252
235
|
key: "path",
|
|
253
236
|
text: pathText,
|
|
254
|
-
url: pathUrl,
|
|
255
237
|
colors: BLOCK_COLORS.path,
|
|
256
238
|
},
|
|
257
239
|
provider: {
|
|
@@ -307,12 +289,12 @@ export function createFooterComponent(
|
|
|
307
289
|
dispose: unsubscribe,
|
|
308
290
|
invalidate() {},
|
|
309
291
|
render(width: number): string[] {
|
|
310
|
-
// Keep
|
|
311
|
-
// (notably Nerd Font icons like the branch icon)
|
|
312
|
-
//
|
|
313
|
-
//
|
|
314
|
-
|
|
315
|
-
|
|
292
|
+
// Keep spare terminal cells unused as a guard against ambiguous-width
|
|
293
|
+
// glyphs (notably Nerd Font icons like the branch icon). A footer line
|
|
294
|
+
// that reaches the exact terminal width can soft-wrap into an apparent
|
|
295
|
+
// blank line and make the bottom chrome jump during heavy tool output.
|
|
296
|
+
const renderWidth = Math.max(0, width - 2);
|
|
297
|
+
if (renderWidth === 0) return [""];
|
|
316
298
|
const variant: FooterVariant = ACTIVE_FOOTER_VARIANT;
|
|
317
299
|
const itemsByKey = buildFooterItems(ctx, footerData, getThinkingLevel());
|
|
318
300
|
const leftVariants = buildSideVariants(itemsByKey, FOOTER_LAYOUT.left, variant, "left");
|
|
@@ -326,22 +308,28 @@ export function createFooterComponent(
|
|
|
326
308
|
for (const left of leftVariants) {
|
|
327
309
|
for (const right of rightVariants) {
|
|
328
310
|
const rightWidth = visibleWidth(right);
|
|
329
|
-
|
|
311
|
+
const leftWidth = visibleWidth(left);
|
|
312
|
+
const edgePaddingWidth = 2;
|
|
313
|
+
let minimumInnerGap = 0;
|
|
330
314
|
if (right.length > 0) {
|
|
331
|
-
|
|
315
|
+
minimumInnerGap = 1;
|
|
332
316
|
}
|
|
333
|
-
const
|
|
317
|
+
const requiredWidth =
|
|
318
|
+
edgePaddingWidth + leftWidth + minimumInnerGap + rightWidth;
|
|
334
319
|
|
|
335
|
-
if (
|
|
320
|
+
if (requiredWidth > renderWidth) {
|
|
336
321
|
continue;
|
|
337
322
|
}
|
|
338
323
|
|
|
339
|
-
const paddingWidth = Math.max(
|
|
324
|
+
const paddingWidth = Math.max(
|
|
325
|
+
minimumInnerGap,
|
|
326
|
+
renderWidth - edgePaddingWidth - leftWidth - rightWidth,
|
|
327
|
+
);
|
|
340
328
|
const padding = renderPadding(paddingWidth, variant);
|
|
341
329
|
if (right.length > 0) {
|
|
342
|
-
return [` ${left}${padding}${right}
|
|
330
|
+
return [truncateToWidth(` ${left}${padding}${right} `, renderWidth, "")];
|
|
343
331
|
}
|
|
344
|
-
return [` ${left}${padding}
|
|
332
|
+
return [truncateToWidth(` ${left}${padding} `, renderWidth, "")];
|
|
345
333
|
}
|
|
346
334
|
}
|
|
347
335
|
|