pi-tui-status-beautifier 1.3.2 → 1.4.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/extensions/tui-status-beautifier.ts +106 -26
- package/package.json +1 -1
|
@@ -22,6 +22,7 @@ export interface CustomStyleConfig {
|
|
|
22
22
|
separator?: string;
|
|
23
23
|
brackets?: [string, string];
|
|
24
24
|
inverse?: boolean;
|
|
25
|
+
padName?: boolean;
|
|
25
26
|
glyphs?: {
|
|
26
27
|
success?: string;
|
|
27
28
|
warning?: string;
|
|
@@ -31,21 +32,52 @@ export interface CustomStyleConfig {
|
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
const BUILTIN_PRESETS: Record<string, CustomStyleConfig> = {
|
|
34
|
-
|
|
35
|
+
stream: {
|
|
35
36
|
separator: " ❯ ",
|
|
36
37
|
},
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
powerline: {
|
|
39
|
+
brackets: ["‹", "›"],
|
|
40
|
+
separator: " ",
|
|
41
|
+
glyphs: {
|
|
42
|
+
success: "◆",
|
|
43
|
+
warning: "◌",
|
|
44
|
+
error: "▲",
|
|
45
|
+
accent: "◈",
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
matrix: {
|
|
49
|
+
brackets: ["⦗", "⦘"],
|
|
40
50
|
separator: " ",
|
|
51
|
+
glyphs: {
|
|
52
|
+
success: "✦",
|
|
53
|
+
warning: "◍",
|
|
54
|
+
error: "✖",
|
|
55
|
+
accent: "✧",
|
|
56
|
+
},
|
|
41
57
|
},
|
|
42
58
|
glow: {
|
|
43
59
|
brackets: ["[", "]"],
|
|
44
60
|
inverse: true,
|
|
45
61
|
},
|
|
62
|
+
// Backward-compatible aliases
|
|
63
|
+
minimal: {
|
|
64
|
+
separator: " ❯ ",
|
|
65
|
+
padName: true,
|
|
66
|
+
},
|
|
67
|
+
glass: {
|
|
68
|
+
brackets: ["‹", "›"],
|
|
69
|
+
separator: " ",
|
|
70
|
+
glyphs: {
|
|
71
|
+
success: "◆",
|
|
72
|
+
warning: "◌",
|
|
73
|
+
error: "▲",
|
|
74
|
+
accent: "◈",
|
|
75
|
+
},
|
|
76
|
+
},
|
|
46
77
|
};
|
|
47
78
|
|
|
48
|
-
const VALID_STYLES = ["
|
|
79
|
+
const VALID_STYLES = ["stream", "powerline", "matrix", "glow", "minimal", "glass", "custom", "off"] as const;
|
|
80
|
+
const OFF_STYLES = new Set(["off", "default", "none", "raw", "vanilla", "disable", "disabled"]);
|
|
49
81
|
|
|
50
82
|
// Store original statuses to allow dynamic redrawing on configuration changes.
|
|
51
83
|
const originalStatuses = new Map<string, string | undefined>();
|
|
@@ -92,8 +124,12 @@ export function loadConfig(cwd: string = process.cwd()): {
|
|
|
92
124
|
const data = JSON.parse(fs.readFileSync(globalPath, "utf-8"));
|
|
93
125
|
if (data.beautifier) {
|
|
94
126
|
if (typeof data.beautifier.style === "string") {
|
|
95
|
-
const s = data.beautifier.style;
|
|
96
|
-
if (
|
|
127
|
+
const s = data.beautifier.style.toLowerCase().trim();
|
|
128
|
+
if (OFF_STYLES.has(s)) {
|
|
129
|
+
resolvedStyle = "off";
|
|
130
|
+
} else if ((VALID_STYLES as readonly string[]).includes(s)) {
|
|
131
|
+
resolvedStyle = s;
|
|
132
|
+
}
|
|
97
133
|
}
|
|
98
134
|
if (data.beautifier.custom && typeof data.beautifier.custom === "object") {
|
|
99
135
|
resolvedCustom = data.beautifier.custom;
|
|
@@ -109,8 +145,12 @@ export function loadConfig(cwd: string = process.cwd()): {
|
|
|
109
145
|
if (data.beautifier) {
|
|
110
146
|
hasLocalConfig = true;
|
|
111
147
|
if (typeof data.beautifier.style === "string") {
|
|
112
|
-
const s = data.beautifier.style;
|
|
113
|
-
if (
|
|
148
|
+
const s = data.beautifier.style.toLowerCase().trim();
|
|
149
|
+
if (OFF_STYLES.has(s)) {
|
|
150
|
+
resolvedStyle = "off";
|
|
151
|
+
} else if ((VALID_STYLES as readonly string[]).includes(s)) {
|
|
152
|
+
resolvedStyle = s;
|
|
153
|
+
}
|
|
114
154
|
}
|
|
115
155
|
if (data.beautifier.custom && typeof data.beautifier.custom === "object") {
|
|
116
156
|
resolvedCustom = { ...(resolvedCustom || {}), ...data.beautifier.custom };
|
|
@@ -138,7 +178,7 @@ export function beautifyStatus(
|
|
|
138
178
|
customCfg?: CustomStyleConfig
|
|
139
179
|
): string | undefined {
|
|
140
180
|
if (originalVal === undefined) return undefined;
|
|
141
|
-
if (style === "off") return originalVal;
|
|
181
|
+
if (style === "off" || OFF_STYLES.has((style || "").toLowerCase().trim())) return originalVal;
|
|
142
182
|
|
|
143
183
|
try {
|
|
144
184
|
const hasAnsi = originalVal.includes("\u001B") || originalVal.includes("\u009B");
|
|
@@ -150,7 +190,7 @@ export function beautifyStatus(
|
|
|
150
190
|
return originalVal;
|
|
151
191
|
}
|
|
152
192
|
|
|
153
|
-
// 1. Get display name
|
|
193
|
+
// 1. Get display name (compact natural width by default to save precious terminal columns)
|
|
154
194
|
let name = key.toLowerCase();
|
|
155
195
|
if (COMMON_NAMES[name]) {
|
|
156
196
|
name = COMMON_NAMES[name];
|
|
@@ -164,7 +204,14 @@ export function beautifyStatus(
|
|
|
164
204
|
name = COMMON_NAMES[name];
|
|
165
205
|
}
|
|
166
206
|
}
|
|
167
|
-
const
|
|
207
|
+
const preset =
|
|
208
|
+
style === "custom"
|
|
209
|
+
? (customCfg || customStyleConfig || {})
|
|
210
|
+
: (BUILTIN_PRESETS[style] || BUILTIN_PRESETS.stream);
|
|
211
|
+
|
|
212
|
+
const visualName = preset.padName === true
|
|
213
|
+
? padToVisualWidth(sliceToVisualWidth(name, 10), 10)
|
|
214
|
+
: name;
|
|
168
215
|
|
|
169
216
|
// 2. Extract metrics/progress details safely (e.g. (2) or fraction 2/5 or count)
|
|
170
217
|
let details: string | undefined;
|
|
@@ -234,11 +281,6 @@ export function beautifyStatus(
|
|
|
234
281
|
}
|
|
235
282
|
|
|
236
283
|
// 4. Determine state glyph & indicator
|
|
237
|
-
const preset =
|
|
238
|
-
style === "custom"
|
|
239
|
-
? (customCfg || customStyleConfig || {})
|
|
240
|
-
: (BUILTIN_PRESETS[style] || BUILTIN_PRESETS.minimal);
|
|
241
|
-
|
|
242
284
|
const glyphMap = preset.glyphs || {};
|
|
243
285
|
let glyph =
|
|
244
286
|
glyphMap[state] ||
|
|
@@ -522,11 +564,12 @@ export default function (pi: ExtensionAPI) {
|
|
|
522
564
|
}
|
|
523
565
|
|
|
524
566
|
const styleOptions = [
|
|
525
|
-
"
|
|
526
|
-
"
|
|
527
|
-
"
|
|
528
|
-
"glow
|
|
529
|
-
"
|
|
567
|
+
"stream - Clean chevron stream (e.g. name ❯ ● ready)",
|
|
568
|
+
"powerline - Angled brackets & diamonds (e.g. name ‹◆ ready›)",
|
|
569
|
+
"matrix - Dot-matrix brackets & stars (e.g. name ⦗✦ ready⦘)",
|
|
570
|
+
"glow - High-contrast inverse pill (e.g. name [ ● ready ])",
|
|
571
|
+
"custom - [AI Prompt Recipe] Let your agent tailor your bespoke style",
|
|
572
|
+
"off - Revert to native Pi status bar & clean settings",
|
|
530
573
|
];
|
|
531
574
|
|
|
532
575
|
const choice = await ctx.ui.select(`Choose status style (Current: ${currentStyle}):`, styleOptions);
|
|
@@ -535,24 +578,61 @@ export default function (pi: ExtensionAPI) {
|
|
|
535
578
|
|
|
536
579
|
const styleKey = choice.split(" ")[0].trim();
|
|
537
580
|
|
|
581
|
+
if (styleKey === "off") {
|
|
582
|
+
currentStyle = "off";
|
|
583
|
+
customStyleConfig = undefined;
|
|
584
|
+
lastRenderedStatus.clear();
|
|
585
|
+
|
|
586
|
+
// Restore all raw original statuses immediately
|
|
587
|
+
for (const [key, val] of originalStatuses.entries()) {
|
|
588
|
+
ctx.ui.setStatus(key, val);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
// Zero-trace physical cleanup: completely prune the `beautifier` key from settings.json!
|
|
592
|
+
const { targetSettingsPath } = loadConfig(ctx.cwd || process.cwd());
|
|
593
|
+
try {
|
|
594
|
+
if (fs.existsSync(targetSettingsPath)) {
|
|
595
|
+
const data = fs.readFileSync(targetSettingsPath, "utf-8");
|
|
596
|
+
const config = JSON.parse(data);
|
|
597
|
+
if (config.beautifier) {
|
|
598
|
+
delete config.beautifier;
|
|
599
|
+
const tempSettings = `${targetSettingsPath}.tmp.${process.pid}.${Date.now()}`;
|
|
600
|
+
fs.writeFileSync(tempSettings, JSON.stringify(config, null, 2), "utf-8");
|
|
601
|
+
fs.renameSync(tempSettings, targetSettingsPath);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
} catch (_e) {
|
|
605
|
+
// Silently ignore disk write errors
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
ctx.ui.notify("Reverted to native Pi status bar. Cleaned up settings.json.", "info");
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
|
|
538
612
|
if (styleKey === "custom") {
|
|
539
613
|
const promptRecipe = [
|
|
540
614
|
"You are acting as my Pi TUI Status Bar designer for `pi-tui-status-beautifier`.",
|
|
541
|
-
"1. In my primary language, call `ask_user_question` with ASCII visual preview mockups (e.g.
|
|
542
|
-
"
|
|
615
|
+
"1. In my primary language, call `ask_user_question` with ASCII visual preview mockups showing ONLY realistic extension statuses (e.g. `chrome`, `toolflow`, `plan`):",
|
|
616
|
+
" - Powerline: chrome ‹◆ ready› | toolflow ‹◈ 2/5›",
|
|
617
|
+
" - Matrix: chrome ⦗✦ ready⦘ | toolflow ⦗◍ 2/5⦘",
|
|
618
|
+
" - Stream: chrome ❯ ● ready | toolflow ❯ ◐ 2/5",
|
|
619
|
+
" - Glow: chrome [ ● ready ] | toolflow [ ◐ 2/5 ]",
|
|
620
|
+
" (Do NOT include git branch or model name in mockups).",
|
|
621
|
+
"2. If I describe or pick a style, write the configuration into `./.pi/settings.json` (or `~/.pi/agent/settings.json`) under `beautifier`:",
|
|
543
622
|
" {",
|
|
544
623
|
' "beautifier": {',
|
|
545
624
|
' "style": "custom",',
|
|
546
625
|
' "custom": {',
|
|
547
626
|
' "separator": " » ",',
|
|
548
627
|
' "brackets": ["«", "»"],',
|
|
549
|
-
' "prefix": "
|
|
628
|
+
' "prefix": "",',
|
|
550
629
|
' "suffix": "",',
|
|
551
630
|
' "glyphs": { "success": "✦", "warning": "◇", "error": "✖", "accent": "✧" }',
|
|
552
631
|
" }",
|
|
553
632
|
" }",
|
|
554
633
|
" }",
|
|
555
|
-
"
|
|
634
|
+
"3. If I say revert, restore, default, off, or cancel, DELETE the `beautifier` key from `settings.json` and exit quietly without asking more questions.",
|
|
635
|
+
"4. Do NOT search filesystem or edit extension source files."
|
|
556
636
|
].join("\n");
|
|
557
637
|
|
|
558
638
|
if (typeof (ctx.ui as any).setEditorText === "function") {
|
package/package.json
CHANGED