@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 CHANGED
@@ -1,11 +1,19 @@
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
+ 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
- Local subpackage path:
15
+ ## Install
8
16
 
9
17
  ```sh
10
- pi install @zigai/pi-footer
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.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-ui"
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-ui-tweaks.git",
21
+ "url": "git+https://github.com/zigai/pi-ux-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
  };