@zigai/pi-footer 0.1.1 → 0.1.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/README.md CHANGED
@@ -1,11 +1,21 @@
1
1
  # Pi Footer
2
2
 
3
- Pi package for a custom footer and worked-for token speed widget.
3
+ This Pi extension replaces Pi's footer with a single compact plain-text status line.
4
4
 
5
- ## Install
5
+ ![Pi Footer screenshot](assets/footer.png)
6
+
7
+ The footer keeps key session information visible without taking much space:
6
8
 
7
- Local subpackage path:
9
+ - current working directory
10
+ - git branch
11
+ - provider and model
12
+ - thinking level
13
+ - MCP status
14
+ - context usage
15
+ - a short post-run summary with total agent time and output token speed
16
+
17
+ ## Install
8
18
 
9
19
  ```sh
10
- pi install @zigai/pi-footer
20
+ pi install git:github.com/zigai/pi-tweaks
11
21
  ```
package/package.json CHANGED
@@ -1,16 +1,24 @@
1
1
  {
2
2
  "name": "@zigai/pi-footer",
3
- "version": "0.1.1",
3
+ "version": "0.1.5",
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-ui"
11
+ "pi-tweaks"
10
12
  ],
13
+ "homepage": "https://github.com/zigai/pi-tweaks/tree/main/packages/pi-footer#readme",
14
+ "bugs": {
15
+ "url": "https://github.com/zigai/pi-tweaks/issues"
16
+ },
17
+ "license": "MIT",
18
+ "author": "zigai",
11
19
  "repository": {
12
20
  "type": "git",
13
- "url": "git+https://github.com/zigai/pi-ui-tweaks.git",
21
+ "url": "git+https://github.com/zigai/pi-tweaks.git",
14
22
  "directory": "packages/pi-footer"
15
23
  },
16
24
  "files": [
@@ -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
- let linked = ` ${item.text} `;
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
- let linked = item.text;
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 one terminal cell unused as a guard against ambiguous-width glyphs
311
- // (notably Nerd Font icons like the branch icon) and OSC/ANSI width
312
- // edge-cases. If the terminal renders one of those glyphs wider than
313
- // pi-tui's visibleWidth() calculation, a full-width footer can soft-wrap
314
- // into an apparent blank line and make the bottom chrome jump.
315
- const renderWidth = Math.max(1, width - 1);
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
- let gap = 0;
311
+ const leftWidth = visibleWidth(left);
312
+ const edgePaddingWidth = 2;
313
+ let minimumInnerGap = 0;
330
314
  if (right.length > 0) {
331
- gap = 1;
315
+ minimumInnerGap = 1;
332
316
  }
333
- const leftWidth = visibleWidth(left);
317
+ const requiredWidth =
318
+ edgePaddingWidth + leftWidth + minimumInnerGap + rightWidth;
334
319
 
335
- if (leftWidth + gap + rightWidth > renderWidth) {
320
+ if (requiredWidth > renderWidth) {
336
321
  continue;
337
322
  }
338
323
 
339
- const paddingWidth = Math.max(0, renderWidth - leftWidth - rightWidth - 2);
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
 
package/src/types.ts CHANGED
@@ -42,6 +42,5 @@ export type FooterData = {
42
42
  export type FooterItem = {
43
43
  key: FooterKey;
44
44
  text: string;
45
- url?: string;
46
45
  colors: SegmentColors;
47
46
  };