@narumitw/pi-statusline 0.7.0 → 0.8.0
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 +4 -2
- package/package.json +1 -1
- package/src/statusline.ts +11 -14
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ Use it to monitor model selection, thinking level, git branch, working directory
|
|
|
14
14
|
- Owns extension status icons through optional JSON config, including per-extension icon suppression with `""`.
|
|
15
15
|
- Warns when the same extension package is installed from multiple sources.
|
|
16
16
|
- Uses emoji-labeled segments for readability in both classic and Tokyo Night presets.
|
|
17
|
-
- Adapts to terminal width and
|
|
17
|
+
- Adapts to terminal width and wraps long extension status lines safely.
|
|
18
18
|
- Requires no configuration, with optional preset selection through `PI_STATUSLINE_PRESET`.
|
|
19
19
|
|
|
20
20
|
## 📦 Install
|
|
@@ -59,6 +59,7 @@ Extension statuses use built-in icons by status key. Override or suppress them i
|
|
|
59
59
|
{
|
|
60
60
|
"extensionStatusIcons": {
|
|
61
61
|
"caffeinate": "☕",
|
|
62
|
+
"github-pr": "🔎",
|
|
62
63
|
"goal": "🎯",
|
|
63
64
|
"pisync": "☁️",
|
|
64
65
|
"unknown-error-retry": "",
|
|
@@ -90,13 +91,14 @@ The default `tokyo-night` statusline uses a Starship-inspired `░▒▓` / `
|
|
|
90
91
|
- 💸 estimated cost.
|
|
91
92
|
- 🕒 clock.
|
|
92
93
|
|
|
93
|
-
Statuses from other extensions appear
|
|
94
|
+
Statuses from other extensions appear below the main statusline, use each preset's separator, and wrap onto additional footer lines when they exceed the terminal width.
|
|
94
95
|
|
|
95
96
|
`pi-statusline` is extension-agnostic: it consumes Pi's generic extension status API and does not import or depend on status-producing extensions.
|
|
96
97
|
|
|
97
98
|
Examples:
|
|
98
99
|
|
|
99
100
|
- `🎯 active` for `goal: active` using the built-in `goal` icon.
|
|
101
|
+
- `🔎 PR #123 checks passing` for `github-pr: PR #123 checks passing` using the built-in `github-pr` icon.
|
|
100
102
|
- `☕ display` when JSON config sets `"caffeinate": "☕"`.
|
|
101
103
|
- `receiving` when JSON config sets `"unknown-error-retry": ""`.
|
|
102
104
|
- `🔌 running` for an unknown extension status key with no configured icon.
|
package/package.json
CHANGED
package/src/statusline.ts
CHANGED
|
@@ -9,7 +9,7 @@ import type {
|
|
|
9
9
|
Theme,
|
|
10
10
|
ThemeColor,
|
|
11
11
|
} from "@earendil-works/pi-coding-agent";
|
|
12
|
-
import { truncateToWidth } from "@earendil-works/pi-tui";
|
|
12
|
+
import { truncateToWidth, wrapTextWithAnsi } from "@earendil-works/pi-tui";
|
|
13
13
|
import { classicExtensionSeparator, renderClassicStatusline } from "../presets/classic.js";
|
|
14
14
|
import { renderTokyoNightStatusline, tokyoNightExtensionSeparator } from "../presets/tokyo-night.js";
|
|
15
15
|
import type {
|
|
@@ -49,6 +49,7 @@ const DEFAULT_EXTENSION_STATUS_ICONS: Record<string, string> = {
|
|
|
49
49
|
"codex-usage": "📊",
|
|
50
50
|
caffeinate: "💊",
|
|
51
51
|
firecrawl: "🔥",
|
|
52
|
+
"github-pr": "🔎",
|
|
52
53
|
goal: "🎯",
|
|
53
54
|
lsp: "🧰",
|
|
54
55
|
"plan-mode": "📝",
|
|
@@ -112,14 +113,7 @@ export default function statusline(pi: ExtensionAPI) {
|
|
|
112
113
|
invalidate() {},
|
|
113
114
|
render(width: number): string[] {
|
|
114
115
|
const lines = [renderStatusline(width, ctx, footerData, theme, config, runtime)];
|
|
115
|
-
|
|
116
|
-
width,
|
|
117
|
-
footerData,
|
|
118
|
-
theme,
|
|
119
|
-
config,
|
|
120
|
-
runtime,
|
|
121
|
-
);
|
|
122
|
-
if (extensionStatusLine) lines.push(extensionStatusLine);
|
|
116
|
+
lines.push(...renderExtensionStatusline(width, footerData, theme, config, runtime));
|
|
123
117
|
return lines;
|
|
124
118
|
},
|
|
125
119
|
};
|
|
@@ -255,11 +249,9 @@ function renderExtensionStatusline(
|
|
|
255
249
|
theme: Theme,
|
|
256
250
|
config: StatuslineConfig,
|
|
257
251
|
runtime: RuntimeState,
|
|
258
|
-
): string
|
|
252
|
+
): string[] {
|
|
259
253
|
const status = formatExtensionStatuses(footerData.getExtensionStatuses(), theme, config, runtime);
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
return truncateToWidth(status, width, "");
|
|
254
|
+
return wrapExtensionStatusline(status, width);
|
|
263
255
|
}
|
|
264
256
|
|
|
265
257
|
function buildSegment(
|
|
@@ -405,7 +397,7 @@ export function formatExtensionStatus(
|
|
|
405
397
|
config: Pick<StatuslineConfig, "extensionStatusIcons">,
|
|
406
398
|
): string {
|
|
407
399
|
const status = splitExtensionStatusIcon(stripExtensionStatusPrefix(key, value));
|
|
408
|
-
const text =
|
|
400
|
+
const text = simplifyExtensionStatusText(status.text);
|
|
409
401
|
const color = extensionColor(key, value);
|
|
410
402
|
const textColor = color === "warning" ? "warning" : "muted";
|
|
411
403
|
const icon = extensionStatusIcon(key, status.icon, config.extensionStatusIcons);
|
|
@@ -422,6 +414,11 @@ function extensionStatusIcon(
|
|
|
422
414
|
return leadingIcon ?? DEFAULT_EXTENSION_STATUS_ICONS[key] ?? "🔌";
|
|
423
415
|
}
|
|
424
416
|
|
|
417
|
+
export function wrapExtensionStatusline(status: string, width: number): string[] {
|
|
418
|
+
if (!status || width <= 0) return [];
|
|
419
|
+
return wrapTextWithAnsi(status, width);
|
|
420
|
+
}
|
|
421
|
+
|
|
425
422
|
function formatDuplicateExtensionStatus(runtime: RuntimeState, theme: Theme): string[] {
|
|
426
423
|
if (runtime.duplicateExtensions.length === 0) return [];
|
|
427
424
|
const names = runtime.duplicateExtensions.slice(0, 2).join(", ");
|