@narumitw/pi-statusline 0.49.2 → 0.49.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 +7 -5
- package/package.json +2 -2
- package/src/command-contract.ts +13 -0
- package/src/commands.ts +38 -42
- package/src/statusline.ts +25 -2
package/README.md
CHANGED
|
@@ -35,11 +35,11 @@ A representative uncolored layout:
|
|
|
35
35
|
pi install npm:@narumitw/pi-statusline
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
Try
|
|
38
|
+
Try the published package without installing, or load it directly from this repository:
|
|
39
39
|
|
|
40
40
|
```bash
|
|
41
41
|
pi -e npm:@narumitw/pi-statusline
|
|
42
|
-
|
|
42
|
+
just try statusline
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
For the best result, use a terminal font that includes Powerline glyphs and emoji.
|
|
@@ -336,8 +336,9 @@ Put transient activity in the value and always clear the same complete key.
|
|
|
336
336
|
```text
|
|
337
337
|
extensions/pi-statusline/
|
|
338
338
|
├── src/
|
|
339
|
-
│ ├── index.ts
|
|
340
|
-
│ ├── statusline.ts
|
|
339
|
+
│ ├── index.ts # thin entrypoint forwarding to the source runtime
|
|
340
|
+
│ ├── statusline.ts # authoritative lifecycle implementation
|
|
341
|
+
│ ├── command-contract.ts
|
|
341
342
|
│ ├── render.ts
|
|
342
343
|
│ ├── directory.ts
|
|
343
344
|
│ ├── usage.ts
|
|
@@ -357,7 +358,8 @@ extensions/pi-statusline/
|
|
|
357
358
|
└── package.json
|
|
358
359
|
```
|
|
359
360
|
|
|
360
|
-
`src
|
|
361
|
+
`src/` is the authoritative published implementation, and `src/index.ts` remains the sole declared
|
|
362
|
+
Pi entrypoint.
|
|
361
363
|
|
|
362
364
|
## 🔎 Keywords
|
|
363
365
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@narumitw/pi-statusline",
|
|
3
|
-
"version": "0.49.
|
|
3
|
+
"version": "0.49.4",
|
|
4
4
|
"description": "Pi extension that replaces the footer with an information-rich statusline.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"@earendil-works/pi-tui": "*"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@biomejs/biome": "2.5.
|
|
35
|
+
"@biomejs/biome": "2.5.7",
|
|
36
36
|
"@earendil-works/pi-coding-agent": "0.83.0",
|
|
37
37
|
"@earendil-works/pi-tui": "0.83.0",
|
|
38
38
|
"@types/node": "26.1.2",
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AutocompleteItem } from "@earendil-works/pi-tui";
|
|
2
|
+
|
|
3
|
+
export const STATUSLINE_SUBCOMMANDS: readonly AutocompleteItem[] = [
|
|
4
|
+
{ value: "settings", label: "settings", description: "Edit pi-statusline.json" },
|
|
5
|
+
{ value: "status", label: "status", description: "Show effective statusline settings" },
|
|
6
|
+
{ value: "help", label: "help", description: "Show configuration help" },
|
|
7
|
+
];
|
|
8
|
+
|
|
9
|
+
export function completeStatuslineArguments(prefix: string): AutocompleteItem[] | null {
|
|
10
|
+
const normalized = prefix.trim().toLowerCase();
|
|
11
|
+
const matches = STATUSLINE_SUBCOMMANDS.filter((item) => item.value.startsWith(normalized));
|
|
12
|
+
return matches.length > 0 ? [...matches] : null;
|
|
13
|
+
}
|
package/src/commands.ts
CHANGED
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
type ExtensionCommandContext,
|
|
5
5
|
} from "@earendil-works/pi-coding-agent";
|
|
6
6
|
import {
|
|
7
|
-
type AutocompleteItem,
|
|
8
7
|
Container,
|
|
9
8
|
Key,
|
|
10
9
|
matchesKey,
|
|
@@ -14,6 +13,7 @@ import {
|
|
|
14
13
|
truncateToWidth,
|
|
15
14
|
wrapTextWithAnsi,
|
|
16
15
|
} from "@earendil-works/pi-tui";
|
|
16
|
+
import { completeStatuslineArguments } from "./command-contract.js";
|
|
17
17
|
import {
|
|
18
18
|
INFORMATION_PROFILE_NAMES,
|
|
19
19
|
INFORMATION_PROFILES,
|
|
@@ -56,12 +56,6 @@ const SEGMENT_DESCRIPTIONS: Record<SegmentName, string> = {
|
|
|
56
56
|
time: "Current local time",
|
|
57
57
|
turn: "Current session turn count",
|
|
58
58
|
};
|
|
59
|
-
const SUBCOMMANDS: AutocompleteItem[] = [
|
|
60
|
-
{ value: "settings", label: "settings", description: "Edit pi-statusline.json" },
|
|
61
|
-
{ value: "status", label: "status", description: "Show effective statusline settings" },
|
|
62
|
-
{ value: "help", label: "help", description: "Show configuration help" },
|
|
63
|
-
];
|
|
64
|
-
|
|
65
59
|
export interface StatuslineCommandOptions {
|
|
66
60
|
settingsPath: string;
|
|
67
61
|
getLoaded(): LoadedStatuslineSettings;
|
|
@@ -74,44 +68,46 @@ export interface StatuslineCommandOptions {
|
|
|
74
68
|
export function registerStatuslineCommand(pi: ExtensionAPI, options: StatuslineCommandOptions) {
|
|
75
69
|
pi.registerCommand("statusline", {
|
|
76
70
|
description: "Open or inspect the statusline settings",
|
|
77
|
-
getArgumentCompletions
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
},
|
|
82
|
-
handler: async (args, ctx) => {
|
|
83
|
-
const normalized = args.trim();
|
|
84
|
-
if (!normalized) {
|
|
85
|
-
await showMainMenu(ctx, options);
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
71
|
+
getArgumentCompletions: completeStatuslineArguments,
|
|
72
|
+
handler: (args, ctx) => handleStatuslineCommand(args, ctx, options),
|
|
73
|
+
});
|
|
74
|
+
}
|
|
88
75
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
76
|
+
export async function handleStatuslineCommand(
|
|
77
|
+
args: string,
|
|
78
|
+
ctx: ExtensionCommandContext,
|
|
79
|
+
options: StatuslineCommandOptions,
|
|
80
|
+
) {
|
|
81
|
+
const normalized = args.trim();
|
|
82
|
+
if (!normalized) {
|
|
83
|
+
await showMainMenu(ctx, options);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
97
86
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
87
|
+
const tokens = normalized.split(/\s+/u);
|
|
88
|
+
const subcommand = tokens[0]?.toLowerCase() ?? "";
|
|
89
|
+
if (tokens.length > 1) {
|
|
90
|
+
if (canNotify(ctx)) {
|
|
91
|
+
ctx.ui.notify(`/statusline ${subcommand} does not accept trailing arguments.`, "warning");
|
|
92
|
+
}
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
switch (subcommand) {
|
|
97
|
+
case "settings":
|
|
98
|
+
await editSettings(ctx, options);
|
|
99
|
+
return;
|
|
100
|
+
case "status":
|
|
101
|
+
showStatus(ctx, options);
|
|
102
|
+
return;
|
|
103
|
+
case "help":
|
|
104
|
+
showHelp(ctx, options.settingsPath);
|
|
105
|
+
return;
|
|
106
|
+
default:
|
|
107
|
+
if (canNotify(ctx)) {
|
|
108
|
+
ctx.ui.notify(`Unknown /statusline subcommand: ${subcommand}`, "warning");
|
|
112
109
|
}
|
|
113
|
-
|
|
114
|
-
});
|
|
110
|
+
}
|
|
115
111
|
}
|
|
116
112
|
|
|
117
113
|
async function showMainMenu(ctx: ExtensionCommandContext, options: StatuslineCommandOptions) {
|
package/src/statusline.ts
CHANGED
|
@@ -4,7 +4,8 @@ import {
|
|
|
4
4
|
type ExtensionContext,
|
|
5
5
|
getAgentDir,
|
|
6
6
|
} from "@earendil-works/pi-coding-agent";
|
|
7
|
-
import {
|
|
7
|
+
import { completeStatuslineArguments } from "./command-contract.js";
|
|
8
|
+
import type { StatuslineCommandOptions } from "./commands.js";
|
|
8
9
|
import {
|
|
9
10
|
buildExtensionStatusIconAliases,
|
|
10
11
|
type ExtensionStatusIconAliasMap,
|
|
@@ -27,6 +28,19 @@ const GIT_STATUS_REFRESH_INTERVAL_MS = 30_000;
|
|
|
27
28
|
const GIT_STATUS_EVENT_DEBOUNCE_MS = 250;
|
|
28
29
|
const EMPTY_EXTENSION_STATUS_ICON_ALIASES: ExtensionStatusIconAliasMap = new Map();
|
|
29
30
|
|
|
31
|
+
type StatuslineCommands = typeof import("./commands.js");
|
|
32
|
+
let statuslineCommandsPromise: Promise<StatuslineCommands> | undefined;
|
|
33
|
+
|
|
34
|
+
function loadStatuslineCommands(): Promise<StatuslineCommands> {
|
|
35
|
+
if (!statuslineCommandsPromise) {
|
|
36
|
+
statuslineCommandsPromise = import("./commands.js").catch((error) => {
|
|
37
|
+
statuslineCommandsPromise = undefined;
|
|
38
|
+
throw error;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return statuslineCommandsPromise;
|
|
42
|
+
}
|
|
43
|
+
|
|
30
44
|
export default function statusline(pi: ExtensionAPI) {
|
|
31
45
|
let loaded: LoadedStatuslineSettings | undefined;
|
|
32
46
|
let previewPalettePreset: PalettePreset | undefined;
|
|
@@ -193,7 +207,7 @@ export default function statusline(pi: ExtensionAPI) {
|
|
|
193
207
|
|
|
194
208
|
const agentDir = getAgentDir();
|
|
195
209
|
const configPath = settingsFilePath(agentDir);
|
|
196
|
-
|
|
210
|
+
const commandOptions: StatuslineCommandOptions = {
|
|
197
211
|
settingsPath: configPath,
|
|
198
212
|
getLoaded: () => loaded ?? loadStatuslineSettings(configPath),
|
|
199
213
|
getMenuOwner: () => {
|
|
@@ -214,6 +228,15 @@ export default function statusline(pi: ExtensionAPI) {
|
|
|
214
228
|
previewPalettePreset = palettePreset;
|
|
215
229
|
refresh();
|
|
216
230
|
},
|
|
231
|
+
};
|
|
232
|
+
pi.registerCommand("statusline", {
|
|
233
|
+
description: "Open or inspect the statusline settings",
|
|
234
|
+
getArgumentCompletions: completeStatuslineArguments,
|
|
235
|
+
handler: async (args, ctx) => {
|
|
236
|
+
const commands = await loadStatuslineCommands();
|
|
237
|
+
if (ctx.sessionManager !== activeSessionManager) return;
|
|
238
|
+
await commands.handleStatuslineCommand(args, ctx, commandOptions);
|
|
239
|
+
},
|
|
217
240
|
});
|
|
218
241
|
|
|
219
242
|
pi.on("session_start", (_event, ctx) => {
|