@heyhuynhgiabuu/pi-pretty 0.6.23 → 0.6.25
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/CHANGELOG.md +24 -0
- package/README.md +51 -1
- package/dist/autocomplete.js +1 -4
- package/dist/autocomplete.js.map +1 -1
- package/dist/config.d.ts +19 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +141 -118
- package/dist/config.js.map +1 -1
- package/dist/fff-helpers.js +2 -7
- package/dist/fff-helpers.js.map +1 -1
- package/dist/fff.js +16 -23
- package/dist/fff.js.map +1 -1
- package/dist/find-glob.js +2 -6
- package/dist/find-glob.js.map +1 -1
- package/dist/helpers.js +11 -21
- package/dist/helpers.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +182 -59
- package/dist/index.js.map +1 -1
- package/dist/notices.js +1 -4
- package/dist/notices.js.map +1 -1
- package/dist/render.js +78 -96
- package/dist/render.js.map +1 -1
- package/dist/session-color.d.ts +30 -0
- package/dist/session-color.d.ts.map +1 -0
- package/dist/session-color.js +170 -0
- package/dist/session-color.js.map +1 -0
- package/dist/tools/bash.js +26 -29
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/find.js +31 -34
- package/dist/tools/find.js.map +1 -1
- package/dist/tools/grep.js +22 -25
- package/dist/tools/grep.js.map +1 -1
- package/dist/tools/labels.js +1 -4
- package/dist/tools/labels.js.map +1 -1
- package/dist/tools/ls.js +18 -21
- package/dist/tools/ls.js.map +1 -1
- package/dist/tools/metrics.js +4 -7
- package/dist/tools/metrics.js.map +1 -1
- package/dist/tools/read.js +35 -38
- package/dist/tools/read.js.map +1 -1
- package/dist/tui-text.js +5 -9
- package/dist/tui-text.js.map +1 -1
- package/dist/types.js +1 -2
- package/dist/types.js.map +1 -1
- package/dist/working-indicator.d.ts +184 -0
- package/dist/working-indicator.d.ts.map +1 -0
- package/dist/working-indicator.js +524 -0
- package/dist/working-indicator.js.map +1 -0
- package/package.json +7 -6
- package/src/config.ts +48 -0
- package/src/index.ts +177 -2
- package/src/session-color.ts +172 -0
- package/src/working-indicator.ts +691 -0
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* omp-style shimmer working indicator (widget takeover).
|
|
3
|
+
*
|
|
4
|
+
* Ports the shimmer sweep from oh-my-pi's `modes/theme/shimmer.ts`: the sweep
|
|
5
|
+
* is discretized into one pre-rendered frame per band position, cycled at
|
|
6
|
+
* 1000/30 ms so the band travels 30 cells/second — omp's exact speed.
|
|
7
|
+
*
|
|
8
|
+
* Why a widget: the host `Loader` extends `Text` with a hardcoded paddingX=1,
|
|
9
|
+
* and `setWorkingIndicator({ frames })` cannot change host component layout.
|
|
10
|
+
* To render the row flush-left we hide the host loader
|
|
11
|
+
* (`setWorkingVisible(false)`) and install our own zero-padding component via
|
|
12
|
+
* `setWidget(..., "aboveEditor")`, animating it with a 33ms interval.
|
|
13
|
+
*
|
|
14
|
+
* Frame layout: `<dim spinner> <shimmer text> <dim interrupt hint>`, one full
|
|
15
|
+
* sweep per phrase — `texts` rotates through phrases chapter by chapter with
|
|
16
|
+
* a continuous spinner phase.
|
|
17
|
+
*/
|
|
18
|
+
import { truncateToWidth } from "@earendil-works/pi-tui";
|
|
19
|
+
import { FG_BLUE, FG_DIM, FG_MUTED } from "./config.js";
|
|
20
|
+
import { dimAccentHex, hexToAnsiFg, sessionAccentHex } from "./session-color.js";
|
|
21
|
+
// ─── Sweep tunables (oh-my-pi shimmer.ts) ────────────────────────────────────
|
|
22
|
+
const CLASSIC_PADDING = 10;
|
|
23
|
+
const CLASSIC_BAND_HALF_WIDTH = 6;
|
|
24
|
+
const KITT_HEAD_HALF = 0.6;
|
|
25
|
+
const KITT_TRAIL_LEN = 7;
|
|
26
|
+
const TIER_HIGH = 0.65;
|
|
27
|
+
const TIER_MID = 0.22;
|
|
28
|
+
/** One cell per frame at 33ms = omp's 30 cells/second band speed. */
|
|
29
|
+
export const WORKING_INTERVAL_MS = Math.round(1000 / 30);
|
|
30
|
+
const SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
31
|
+
/** Spinner glyph advances every N frames (~99ms ≈ pi's default 80ms cadence). */
|
|
32
|
+
const SPINNER_STEP = 3;
|
|
33
|
+
const RESET_FG = "\x1b[39m";
|
|
34
|
+
const BOLD_OPEN = "\x1b[1m";
|
|
35
|
+
const BOLD_CLOSE = "\x1b[22m";
|
|
36
|
+
const ITALIC_OPEN = "\x1b[3m";
|
|
37
|
+
const ITALIC_CLOSE = "\x1b[23m";
|
|
38
|
+
/** Fallback for pi's thinkingText tier when no theme is available. */
|
|
39
|
+
const FG_THINKING_FALLBACK = "\x1b[38;2;148;148;184m";
|
|
40
|
+
export const WORKING_INDICATOR_DEFAULTS = {
|
|
41
|
+
enabled: true,
|
|
42
|
+
texts: ["Working…"],
|
|
43
|
+
mode: "shimmer",
|
|
44
|
+
palette: { low: "dim", mid: "muted", high: "accent" },
|
|
45
|
+
bold: true,
|
|
46
|
+
hint: true,
|
|
47
|
+
sessionAccent: true,
|
|
48
|
+
tiersCustomized: false,
|
|
49
|
+
};
|
|
50
|
+
const MODES = ["shimmer", "kitt", "static"];
|
|
51
|
+
function isMode(value) {
|
|
52
|
+
return typeof value === "string" && MODES.includes(value);
|
|
53
|
+
}
|
|
54
|
+
function envFlag(value) {
|
|
55
|
+
const v = value?.trim().toLowerCase();
|
|
56
|
+
if (!v)
|
|
57
|
+
return undefined;
|
|
58
|
+
if (v === "off" || v === "false" || v === "0")
|
|
59
|
+
return false;
|
|
60
|
+
if (v === "on" || v === "true" || v === "1")
|
|
61
|
+
return true;
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
/** Longest working label we build frames for (the sweep is one frame per code point + padding). */
|
|
65
|
+
const MAX_TEXT_CODE_POINTS = 120;
|
|
66
|
+
// biome-ignore lint/suspicious/noControlCharactersInRegex: control chars are exactly what we sanitize out of user text
|
|
67
|
+
const CONTROL_CHARS_RE = /[\u0000-\u001f\u007f]/;
|
|
68
|
+
/**
|
|
69
|
+
* Accept a configured label only if it renders safely in the single-line
|
|
70
|
+
* working row: no control characters (including newlines) and bounded length.
|
|
71
|
+
* Returns undefined for anything invalid, falling back to the default.
|
|
72
|
+
*/
|
|
73
|
+
function sanitizeText(value) {
|
|
74
|
+
const text = typeof value === "string" ? value.trim() : undefined;
|
|
75
|
+
if (!text)
|
|
76
|
+
return undefined;
|
|
77
|
+
if (CONTROL_CHARS_RE.test(text))
|
|
78
|
+
return undefined;
|
|
79
|
+
if ([...text].length > MAX_TEXT_CODE_POINTS)
|
|
80
|
+
return undefined;
|
|
81
|
+
return text;
|
|
82
|
+
}
|
|
83
|
+
/** Sanitize a `string | string[]` config value into a valid phrase list. */
|
|
84
|
+
function sanitizeTexts(input) {
|
|
85
|
+
const list = Array.isArray(input) ? input : [input];
|
|
86
|
+
const out = [];
|
|
87
|
+
for (const item of list) {
|
|
88
|
+
const text = sanitizeText(item);
|
|
89
|
+
if (text)
|
|
90
|
+
out.push(text);
|
|
91
|
+
}
|
|
92
|
+
return out.length > 0 ? out : undefined;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Resolve final settings from `pi-pretty.json`'s flat `workingIndicator` object
|
|
96
|
+
* and env overrides. Precedence: env var > config > default; empty or invalid
|
|
97
|
+
* env values mean unset (matching pi-pretty's config conventions).
|
|
98
|
+
*/
|
|
99
|
+
export function resolveWorkingIndicatorSettings(config, env = process.env) {
|
|
100
|
+
const settings = {
|
|
101
|
+
...WORKING_INDICATOR_DEFAULTS,
|
|
102
|
+
palette: { ...WORKING_INDICATOR_DEFAULTS.palette },
|
|
103
|
+
};
|
|
104
|
+
const envEnabled = envFlag(env.PRETTY_WORKING_INDICATOR);
|
|
105
|
+
if (envEnabled !== undefined)
|
|
106
|
+
settings.enabled = envEnabled;
|
|
107
|
+
else if (typeof config?.enabled === "boolean")
|
|
108
|
+
settings.enabled = config.enabled;
|
|
109
|
+
const envMode = isMode(env.PRETTY_WORKING_INDICATOR_MODE) ? env.PRETTY_WORKING_INDICATOR_MODE : undefined;
|
|
110
|
+
settings.mode = envMode ?? (isMode(config?.mode) ? config.mode : settings.mode);
|
|
111
|
+
const envTexts = sanitizeTexts(env.PRETTY_WORKING_INDICATOR_TEXT?.split(",").map((part) => part.trim()));
|
|
112
|
+
settings.texts = envTexts ?? sanitizeTexts(config?.text) ?? settings.texts;
|
|
113
|
+
for (const tier of ["low", "mid", "high"]) {
|
|
114
|
+
const value = config?.[tier];
|
|
115
|
+
if (typeof value === "string" && value.trim() !== "")
|
|
116
|
+
settings.palette[tier] = value;
|
|
117
|
+
}
|
|
118
|
+
if (typeof config?.bold === "boolean")
|
|
119
|
+
settings.bold = config.bold;
|
|
120
|
+
if (typeof config?.hint === "boolean")
|
|
121
|
+
settings.hint = config.hint;
|
|
122
|
+
if (typeof config?.sessionAccent === "boolean")
|
|
123
|
+
settings.sessionAccent = config.sessionAccent;
|
|
124
|
+
settings.tiersCustomized = typeof config?.mid === "string" || typeof config?.high === "string";
|
|
125
|
+
return settings;
|
|
126
|
+
}
|
|
127
|
+
function colorToAnsi(value, theme, fallback) {
|
|
128
|
+
const hex = hexToAnsiFg(value);
|
|
129
|
+
if (hex)
|
|
130
|
+
return hex;
|
|
131
|
+
try {
|
|
132
|
+
// Pi's ThemeColor is a closed TS union, but getFgAnsi accepts any registered
|
|
133
|
+
// theme color at runtime; unknown names throw or return non-ANSI garbage,
|
|
134
|
+
// both handled below.
|
|
135
|
+
const getFgAnsi = theme?.getFgAnsi;
|
|
136
|
+
const viaTheme = getFgAnsi?.(value);
|
|
137
|
+
if (viaTheme?.startsWith("\x1b["))
|
|
138
|
+
return viaTheme;
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
// Unknown theme color name: fall through to the built-in constant.
|
|
142
|
+
}
|
|
143
|
+
return fallback;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Resolve tier colors to ANSI open sequences. `#rrggbb` wins, then the active
|
|
147
|
+
* pi theme (`getFgAnsi`), then pi-pretty's built-in constants.
|
|
148
|
+
*/
|
|
149
|
+
export function resolvePaletteAnsi(palette, theme) {
|
|
150
|
+
return {
|
|
151
|
+
low: colorToAnsi(palette.low, theme, FG_DIM),
|
|
152
|
+
mid: colorToAnsi(palette.mid, theme, FG_MUTED),
|
|
153
|
+
high: colorToAnsi(palette.high, theme, FG_BLUE),
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
function tierFor(intensity) {
|
|
157
|
+
if (intensity >= TIER_HIGH)
|
|
158
|
+
return "high";
|
|
159
|
+
if (intensity >= TIER_MID)
|
|
160
|
+
return "mid";
|
|
161
|
+
return "low";
|
|
162
|
+
}
|
|
163
|
+
/** Smooth cosine bump sweeping left → right with edge padding. */
|
|
164
|
+
function classicIntensity(index, pos) {
|
|
165
|
+
const dist = Math.abs(index + CLASSIC_PADDING - pos);
|
|
166
|
+
if (dist >= CLASSIC_BAND_HALF_WIDTH)
|
|
167
|
+
return 0;
|
|
168
|
+
return 0.5 * (1 + Math.cos((Math.PI * dist) / CLASSIC_BAND_HALF_WIDTH));
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Knight Rider K.I.T.T. scanner: a single bright head ping-pongs across the
|
|
172
|
+
* text with a quadratic-decay trail behind it (oh-my-pi shimmer.ts).
|
|
173
|
+
*/
|
|
174
|
+
function kittIntensity(index, head, goingRight) {
|
|
175
|
+
const delta = index - head;
|
|
176
|
+
if (Math.abs(delta) <= KITT_HEAD_HALF)
|
|
177
|
+
return 1;
|
|
178
|
+
const behind = goingRight ? -delta : delta;
|
|
179
|
+
if (behind <= KITT_HEAD_HALF)
|
|
180
|
+
return 0;
|
|
181
|
+
const t = (behind - KITT_HEAD_HALF) / KITT_TRAIL_LEN;
|
|
182
|
+
if (t >= 1)
|
|
183
|
+
return 0;
|
|
184
|
+
const f = 1 - t;
|
|
185
|
+
return f * f;
|
|
186
|
+
}
|
|
187
|
+
/** UTF-16 [start, end] index pairs per code point (surrogate-pair safe). */
|
|
188
|
+
function codePointRanges(text) {
|
|
189
|
+
const ranges = [];
|
|
190
|
+
let i = 0;
|
|
191
|
+
while (i < text.length) {
|
|
192
|
+
const c = text.charCodeAt(i);
|
|
193
|
+
if (c >= 0xd800 && c <= 0xdbff && i + 1 < text.length) {
|
|
194
|
+
const c2 = text.charCodeAt(i + 1);
|
|
195
|
+
if (c2 >= 0xdc00 && c2 <= 0xdfff) {
|
|
196
|
+
ranges.push([i, i + 2]);
|
|
197
|
+
i += 2;
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
ranges.push([i, i + 1]);
|
|
202
|
+
i += 1;
|
|
203
|
+
}
|
|
204
|
+
return ranges;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Build the frame list for the working row: one full sweep per phrase, in
|
|
208
|
+
* order, with the spinner phase running continuously across chapter
|
|
209
|
+
* boundaries. Same-tier runs share one ANSI pair (omp's run coalescing).
|
|
210
|
+
*/
|
|
211
|
+
export function buildWorkingFrames(texts, options) {
|
|
212
|
+
const intervalMs = options.intervalMs ?? WORKING_INTERVAL_MS;
|
|
213
|
+
const bold = options.bold ?? true;
|
|
214
|
+
const suffix = options.hint ?? "";
|
|
215
|
+
const withSpinner = options.spinner ?? true;
|
|
216
|
+
const spinnerColor = options.spinnerColor ?? options.ansi.low;
|
|
217
|
+
const highOpen = bold ? `${BOLD_OPEN}${options.ansi.high}` : options.ansi.high;
|
|
218
|
+
const highClose = bold ? `${BOLD_CLOSE}${RESET_FG}` : RESET_FG;
|
|
219
|
+
const seq = {
|
|
220
|
+
low: { open: options.ansi.low, close: RESET_FG },
|
|
221
|
+
mid: { open: options.ansi.mid, close: RESET_FG },
|
|
222
|
+
high: { open: highOpen, close: highClose },
|
|
223
|
+
};
|
|
224
|
+
const spinnerPrefix = (frameIndex) => {
|
|
225
|
+
if (!withSpinner)
|
|
226
|
+
return "";
|
|
227
|
+
const glyph = SPINNER_FRAMES[Math.floor(frameIndex / SPINNER_STEP) % SPINNER_FRAMES.length] ?? "";
|
|
228
|
+
return `${spinnerColor}${glyph}${RESET_FG} `;
|
|
229
|
+
};
|
|
230
|
+
const paintFrame = (text, ranges, tiers) => {
|
|
231
|
+
const total = ranges.length;
|
|
232
|
+
let out = "";
|
|
233
|
+
let runStart = 0;
|
|
234
|
+
let runTier = null;
|
|
235
|
+
const flush = (endIndex) => {
|
|
236
|
+
if (runTier === null || endIndex <= runStart)
|
|
237
|
+
return;
|
|
238
|
+
const s = seq[runTier];
|
|
239
|
+
out += `${s.open}${text.slice(ranges[runStart][0], ranges[endIndex - 1][1])}${s.close}`;
|
|
240
|
+
};
|
|
241
|
+
for (let i = 0; i < total; i++) {
|
|
242
|
+
if (tiers[i] !== runTier) {
|
|
243
|
+
flush(i);
|
|
244
|
+
runTier = tiers[i] ?? null;
|
|
245
|
+
runStart = i;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
flush(total);
|
|
249
|
+
return options.italic ? `${ITALIC_OPEN}${out}${ITALIC_CLOSE}` : out;
|
|
250
|
+
};
|
|
251
|
+
const frames = [];
|
|
252
|
+
let spinnerIndex = 0;
|
|
253
|
+
for (const raw of texts) {
|
|
254
|
+
const text = raw.trim();
|
|
255
|
+
const ranges = codePointRanges(text);
|
|
256
|
+
const total = ranges.length;
|
|
257
|
+
if (total === 0)
|
|
258
|
+
continue;
|
|
259
|
+
if (options.mode === "static") {
|
|
260
|
+
// Static mode: one unanimated frame — only the first phrase renders.
|
|
261
|
+
frames.push(`${spinnerPrefix(spinnerIndex++)}${paintFrame(text, ranges, Array.from({ length: total }, () => "mid"))}${suffix}`);
|
|
262
|
+
return { frames, intervalMs };
|
|
263
|
+
}
|
|
264
|
+
if (options.mode === "kitt") {
|
|
265
|
+
const range = total - 1;
|
|
266
|
+
if (range <= 0) {
|
|
267
|
+
frames.push(`${spinnerPrefix(spinnerIndex++)}${paintFrame(text, ranges, Array.from({ length: total }, () => "high"))}${suffix}`);
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
const cycleCells = 2 * range;
|
|
271
|
+
for (let sweep = 0; sweep < cycleCells; sweep++) {
|
|
272
|
+
const goingRight = sweep < range;
|
|
273
|
+
const head = goingRight ? sweep : cycleCells - sweep;
|
|
274
|
+
const tiers = Array.from({ length: total }, (_, i) => tierFor(kittIntensity(i, head, goingRight)));
|
|
275
|
+
frames.push(`${spinnerPrefix(spinnerIndex++)}${paintFrame(text, ranges, tiers)}${suffix}`);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
const period = total + CLASSIC_PADDING * 2;
|
|
280
|
+
for (let pos = 0; pos < period; pos++) {
|
|
281
|
+
const tiers = Array.from({ length: total }, (_, i) => tierFor(classicIntensity(i, pos)));
|
|
282
|
+
frames.push(`${spinnerPrefix(spinnerIndex++)}${paintFrame(text, ranges, tiers)}${suffix}`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return { frames, intervalMs };
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Zero-padding working-row component. The host renders whatever `render()`
|
|
290
|
+
* returns with no margins, so the row sits flush-left — the thing the frames
|
|
291
|
+
* API could not do.
|
|
292
|
+
*/
|
|
293
|
+
export class WorkingWidget {
|
|
294
|
+
#frames = [];
|
|
295
|
+
#index = 0;
|
|
296
|
+
#intervalMs = WORKING_INTERVAL_MS;
|
|
297
|
+
#interval;
|
|
298
|
+
#tui;
|
|
299
|
+
#started = false;
|
|
300
|
+
#disposed = false;
|
|
301
|
+
setFrames(frames, intervalMs) {
|
|
302
|
+
this.#frames = frames;
|
|
303
|
+
this.#intervalMs = intervalMs;
|
|
304
|
+
this.#index = 0;
|
|
305
|
+
}
|
|
306
|
+
attach(tui) {
|
|
307
|
+
this.#tui = tui;
|
|
308
|
+
}
|
|
309
|
+
start() {
|
|
310
|
+
if (this.#disposed || this.#started)
|
|
311
|
+
return;
|
|
312
|
+
this.#started = true;
|
|
313
|
+
this.#index = 0;
|
|
314
|
+
// A single frame has nothing to cycle — skip the 30fps render churn.
|
|
315
|
+
if (this.#frames.length <= 1)
|
|
316
|
+
return;
|
|
317
|
+
this.#interval = setInterval(() => {
|
|
318
|
+
this.#index = (this.#index + 1) % Math.max(1, this.#frames.length);
|
|
319
|
+
this.#tui?.requestRender();
|
|
320
|
+
}, this.#intervalMs);
|
|
321
|
+
}
|
|
322
|
+
stop() {
|
|
323
|
+
this.#started = false;
|
|
324
|
+
if (this.#interval) {
|
|
325
|
+
clearInterval(this.#interval);
|
|
326
|
+
this.#interval = undefined;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
/** Flush-left single line; invisible (no lines) while stopped. */
|
|
330
|
+
render(width) {
|
|
331
|
+
if (!this.#started || this.#frames.length === 0)
|
|
332
|
+
return [];
|
|
333
|
+
const frame = this.#frames[this.#index % this.#frames.length] ?? "";
|
|
334
|
+
return [truncateToWidth(frame, Math.max(1, width))];
|
|
335
|
+
}
|
|
336
|
+
invalidate() {
|
|
337
|
+
// Stateless per render — nothing to invalidate.
|
|
338
|
+
}
|
|
339
|
+
dispose() {
|
|
340
|
+
this.stop();
|
|
341
|
+
this.#disposed = true;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
export const THINKING_INDICATOR_DEFAULTS = { enabled: true };
|
|
345
|
+
/**
|
|
346
|
+
* Resolve thinking-label shimmer settings from `pi-pretty.json`'s
|
|
347
|
+
* `thinkingIndicator` object and env overrides (env > config > default).
|
|
348
|
+
*/
|
|
349
|
+
export function resolveThinkingIndicatorSettings(config, env = process.env) {
|
|
350
|
+
const settings = { ...THINKING_INDICATOR_DEFAULTS };
|
|
351
|
+
const envEnabled = envFlag(env.PRETTY_THINKING_INDICATOR);
|
|
352
|
+
if (envEnabled !== undefined)
|
|
353
|
+
settings.enabled = envEnabled;
|
|
354
|
+
else if (typeof config?.enabled === "boolean")
|
|
355
|
+
settings.enabled = config.enabled;
|
|
356
|
+
return settings;
|
|
357
|
+
}
|
|
358
|
+
const THINKING_LABEL = "Thinking...";
|
|
359
|
+
/**
|
|
360
|
+
* True while a streaming assistant message is currently emitting a thinking
|
|
361
|
+
* block (its last content block). Used to gate label ticks to the thinking
|
|
362
|
+
* phase — once text or tool calls stream, the label is frozen back to pi's
|
|
363
|
+
* default instead of rebuilding the transcript for a row nobody watches.
|
|
364
|
+
*/
|
|
365
|
+
export function thinkingBlockActive(message) {
|
|
366
|
+
const content = message?.content;
|
|
367
|
+
if (!Array.isArray(content) || content.length === 0)
|
|
368
|
+
return false;
|
|
369
|
+
return content[content.length - 1]?.type === "thinking";
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Animate pi's hidden-thinking label ("Thinking...") with the same shimmer as
|
|
373
|
+
* the working row. Pi renders the label as static italic `thinkingText` text;
|
|
374
|
+
* the only extension lever is `setHiddenThinkingLabel(label)`, which rebuilds
|
|
375
|
+
* chat children — the streaming component already rebuilds per delta, so the
|
|
376
|
+
* animator is driven at a throttled cadence (100ms) from index.ts while the
|
|
377
|
+
* agent streams and thinking blocks are hidden.
|
|
378
|
+
*
|
|
379
|
+
* Tiers: low = theme `thinkingText` (pi's own label look), mid/high = session
|
|
380
|
+
* accent when enabled; every frame is italic like pi's label; no spinner.
|
|
381
|
+
*/
|
|
382
|
+
export function createThinkingLabelAnimator(ui, workSettings, sessionName, thinking) {
|
|
383
|
+
const noop = {
|
|
384
|
+
tick() { },
|
|
385
|
+
restore() { },
|
|
386
|
+
frames: [],
|
|
387
|
+
};
|
|
388
|
+
if (thinking && !thinking.enabled)
|
|
389
|
+
return noop;
|
|
390
|
+
if (typeof ui.setHiddenThinkingLabel !== "function")
|
|
391
|
+
return noop;
|
|
392
|
+
const ansiResolved = resolvePaletteAnsi(workSettings.palette, ui.theme);
|
|
393
|
+
let ansi = {
|
|
394
|
+
...ansiResolved,
|
|
395
|
+
low: colorToAnsi("thinkingText", ui.theme, FG_THINKING_FALLBACK),
|
|
396
|
+
};
|
|
397
|
+
if (workSettings.sessionAccent && sessionName && !workSettings.tiersCustomized) {
|
|
398
|
+
const accent = hexToAnsiFg(sessionAccentHex(sessionName));
|
|
399
|
+
if (accent)
|
|
400
|
+
ansi = { ...ansi, mid: accent, high: accent };
|
|
401
|
+
}
|
|
402
|
+
const { frames } = buildWorkingFrames([THINKING_LABEL], {
|
|
403
|
+
mode: workSettings.mode,
|
|
404
|
+
ansi,
|
|
405
|
+
bold: workSettings.bold,
|
|
406
|
+
spinner: false,
|
|
407
|
+
italic: true,
|
|
408
|
+
});
|
|
409
|
+
if (frames.length === 0)
|
|
410
|
+
return noop;
|
|
411
|
+
let index = 0;
|
|
412
|
+
let applied = false;
|
|
413
|
+
return {
|
|
414
|
+
frames,
|
|
415
|
+
tick() {
|
|
416
|
+
// A single frame (static mode) never changes — skip redundant rebuilds.
|
|
417
|
+
if (applied && frames.length === 1)
|
|
418
|
+
return;
|
|
419
|
+
ui.setHiddenThinkingLabel(frames[index % frames.length]);
|
|
420
|
+
index++;
|
|
421
|
+
applied = true;
|
|
422
|
+
},
|
|
423
|
+
restore() {
|
|
424
|
+
// undefined → pi falls back to its default static label.
|
|
425
|
+
ui.setHiddenThinkingLabel(undefined);
|
|
426
|
+
},
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
const WIDGET_KEY = "pi-pretty-working";
|
|
430
|
+
async function loadHostKeybindings() {
|
|
431
|
+
try {
|
|
432
|
+
const tui = (await import("@earendil-works/pi-tui"));
|
|
433
|
+
return tui.getKeybindings?.();
|
|
434
|
+
}
|
|
435
|
+
catch {
|
|
436
|
+
return undefined;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
function formatKeyText(keys) {
|
|
440
|
+
const darwin = process.platform === "darwin";
|
|
441
|
+
return keys
|
|
442
|
+
.join("/")
|
|
443
|
+
.split("/")
|
|
444
|
+
.map((key) => key
|
|
445
|
+
.split("+")
|
|
446
|
+
.map((part) => (darwin && part.toLowerCase() === "alt" ? "option" : part))
|
|
447
|
+
.join("+"))
|
|
448
|
+
.join("/");
|
|
449
|
+
}
|
|
450
|
+
async function resolveHint(ui, deps) {
|
|
451
|
+
try {
|
|
452
|
+
const loader = deps?.getKeybindings ?? loadHostKeybindings;
|
|
453
|
+
const keybindings = await loader();
|
|
454
|
+
const keys = keybindings?.getKeys?.("app.interrupt");
|
|
455
|
+
if (!keys?.length)
|
|
456
|
+
return undefined;
|
|
457
|
+
const text = ` (${formatKeyText(keys)} to interrupt)`;
|
|
458
|
+
return ui.theme?.fg ? ui.theme.fg("dim", text) : text;
|
|
459
|
+
}
|
|
460
|
+
catch {
|
|
461
|
+
return undefined;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Take over pi's working row with our own flush-left shimmer widget.
|
|
466
|
+
*
|
|
467
|
+
* Installs a zero-padding component above the editor and hides the host
|
|
468
|
+
* loader; returns a controller the host lifecycle drives (`start` on
|
|
469
|
+
* agent_start, `stop` on agent_end). No-op (host defaults untouched) when
|
|
470
|
+
* disabled or the phrase list is empty.
|
|
471
|
+
*/
|
|
472
|
+
export async function installWorkingIndicator(ui, settings, deps, sessionName) {
|
|
473
|
+
const noopController = {
|
|
474
|
+
start() { },
|
|
475
|
+
stop() { },
|
|
476
|
+
dispose() { },
|
|
477
|
+
frames: [],
|
|
478
|
+
};
|
|
479
|
+
if (!settings.enabled)
|
|
480
|
+
return noopController;
|
|
481
|
+
const texts = settings.texts.map((t) => t.trim()).filter((t) => t.length > 0);
|
|
482
|
+
if (texts.length === 0)
|
|
483
|
+
return noopController;
|
|
484
|
+
const ansiResolved = resolvePaletteAnsi(settings.palette, ui.theme);
|
|
485
|
+
let ansi = ansiResolved;
|
|
486
|
+
let spinnerColor;
|
|
487
|
+
if (settings.sessionAccent && sessionName && !settings.tiersCustomized) {
|
|
488
|
+
const accentHex = sessionAccentHex(sessionName);
|
|
489
|
+
const accent = hexToAnsiFg(accentHex);
|
|
490
|
+
if (accent) {
|
|
491
|
+
ansi = { ...ansi, mid: accent, high: accent };
|
|
492
|
+
spinnerColor = hexToAnsiFg(dimAccentHex(accentHex));
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
const hint = settings.hint ? await resolveHint(ui, deps) : undefined;
|
|
496
|
+
const { frames, intervalMs } = buildWorkingFrames(texts, {
|
|
497
|
+
mode: settings.mode,
|
|
498
|
+
ansi,
|
|
499
|
+
bold: settings.bold,
|
|
500
|
+
spinnerColor,
|
|
501
|
+
hint,
|
|
502
|
+
});
|
|
503
|
+
if (frames.length === 0)
|
|
504
|
+
return noopController;
|
|
505
|
+
const widget = new WorkingWidget();
|
|
506
|
+
widget.setFrames(frames, intervalMs);
|
|
507
|
+
// Widget first, visibility second: if setWidget throws (older host without
|
|
508
|
+
// the API) the host loader was never hidden and pi's default remains.
|
|
509
|
+
ui.setWidget(WIDGET_KEY, (tui) => {
|
|
510
|
+
widget.attach(tui);
|
|
511
|
+
return widget;
|
|
512
|
+
}, { placement: "aboveEditor" });
|
|
513
|
+
ui.setWorkingVisible(false);
|
|
514
|
+
return {
|
|
515
|
+
start: () => widget.start(),
|
|
516
|
+
stop: () => widget.stop(),
|
|
517
|
+
dispose: () => {
|
|
518
|
+
widget.dispose();
|
|
519
|
+
ui.setWidget(WIDGET_KEY, undefined);
|
|
520
|
+
},
|
|
521
|
+
frames,
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
//# sourceMappingURL=working-indicator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"working-indicator.js","sourceRoot":"","sources":["../src/working-indicator.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@heyhuynhgiabuu/pi-pretty",
|
|
3
|
-
"version": "0.6.
|
|
4
|
-
"description": "Pretty terminal output for pi
|
|
3
|
+
"version": "0.6.25",
|
|
4
|
+
"description": "Pretty terminal output for pi \u2014 syntax-highlighted file reads, colored bash output, tree-view directory listings, and more.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi",
|
|
7
7
|
"pi-extension",
|
|
@@ -42,9 +42,9 @@
|
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@biomejs/biome": "^2.3.5",
|
|
45
|
-
"@earendil-works/pi-ai": "^0.
|
|
46
|
-
"@earendil-works/pi-coding-agent": "^0.
|
|
47
|
-
"@earendil-works/pi-tui": "^0.
|
|
45
|
+
"@earendil-works/pi-ai": "^0.84.4",
|
|
46
|
+
"@earendil-works/pi-coding-agent": "^0.84.4",
|
|
47
|
+
"@earendil-works/pi-tui": "^0.84.4",
|
|
48
48
|
"@types/node": "^20.0.0",
|
|
49
49
|
"typescript": "^5.0.0",
|
|
50
50
|
"vitest": "^4.0.18"
|
|
@@ -58,5 +58,6 @@
|
|
|
58
58
|
"extensions": [
|
|
59
59
|
"./dist/index.js"
|
|
60
60
|
]
|
|
61
|
-
}
|
|
61
|
+
},
|
|
62
|
+
"type": "module"
|
|
62
63
|
}
|
package/src/config.ts
CHANGED
|
@@ -67,6 +67,25 @@ function hexToAnsiBg(hex: string): string | null {
|
|
|
67
67
|
return `\x1b[48;2;${r};${g};${b}m`;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
export interface WorkingIndicatorConfig {
|
|
71
|
+
enabled?: boolean;
|
|
72
|
+
/** One phrase or a list of phrases rotated across sweeps. */
|
|
73
|
+
text?: string | string[];
|
|
74
|
+
mode?: "shimmer" | "kitt" | "static";
|
|
75
|
+
/** Tier colors: a pi theme color name or a `#rrggbb` hex. */
|
|
76
|
+
low?: string;
|
|
77
|
+
mid?: string;
|
|
78
|
+
high?: string;
|
|
79
|
+
bold?: boolean;
|
|
80
|
+
hint?: boolean;
|
|
81
|
+
/** Tint the indicator with a stable per-session accent color. */
|
|
82
|
+
sessionAccent?: boolean;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface ThinkingIndicatorConfig {
|
|
86
|
+
enabled?: boolean;
|
|
87
|
+
}
|
|
88
|
+
|
|
70
89
|
export interface PrettyConfig {
|
|
71
90
|
background?: {
|
|
72
91
|
tool?: string;
|
|
@@ -79,6 +98,8 @@ export interface PrettyConfig {
|
|
|
79
98
|
maxHlChars?: number;
|
|
80
99
|
maxPreviewLines?: number;
|
|
81
100
|
cacheLimit?: number;
|
|
101
|
+
workingIndicator?: WorkingIndicatorConfig;
|
|
102
|
+
thinkingIndicator?: ThinkingIndicatorConfig;
|
|
82
103
|
}
|
|
83
104
|
|
|
84
105
|
/** Normalize a comma-separated env value or JSON array into tool names. */
|
|
@@ -127,6 +148,33 @@ export function loadConfig(agentDir = getConfigDir()): PrettyConfig {
|
|
|
127
148
|
if (maxHlChars) config.maxHlChars = maxHlChars;
|
|
128
149
|
if (maxPreviewLines) config.maxPreviewLines = maxPreviewLines;
|
|
129
150
|
if (cacheLimit) config.cacheLimit = cacheLimit;
|
|
151
|
+
const workingIndicator = parsed.workingIndicator;
|
|
152
|
+
if (workingIndicator && typeof workingIndicator === "object") {
|
|
153
|
+
const wi: WorkingIndicatorConfig = {};
|
|
154
|
+
const src = workingIndicator as Record<string, unknown>;
|
|
155
|
+
if (typeof src.enabled === "boolean") wi.enabled = src.enabled;
|
|
156
|
+
if (typeof src.text === "string" && src.text.trim() !== "") wi.text = src.text;
|
|
157
|
+
else if (Array.isArray(src.text)) {
|
|
158
|
+
const list = src.text.filter((item) => typeof item === "string" && item.trim() !== "");
|
|
159
|
+
if (list.length > 0) wi.text = list;
|
|
160
|
+
}
|
|
161
|
+
if (src.mode === "shimmer" || src.mode === "kitt" || src.mode === "static") wi.mode = src.mode;
|
|
162
|
+
for (const tier of ["low", "mid", "high"] as const) {
|
|
163
|
+
const value = src[tier];
|
|
164
|
+
if (typeof value === "string" && value.trim() !== "") wi[tier] = value;
|
|
165
|
+
}
|
|
166
|
+
if (typeof src.bold === "boolean") wi.bold = src.bold;
|
|
167
|
+
if (typeof src.hint === "boolean") wi.hint = src.hint;
|
|
168
|
+
if (typeof src.sessionAccent === "boolean") wi.sessionAccent = src.sessionAccent;
|
|
169
|
+
if (Object.keys(wi).length > 0) config.workingIndicator = wi;
|
|
170
|
+
}
|
|
171
|
+
const thinkingIndicator = parsed.thinkingIndicator;
|
|
172
|
+
if (thinkingIndicator && typeof thinkingIndicator === "object") {
|
|
173
|
+
const ti: ThinkingIndicatorConfig = {};
|
|
174
|
+
const src = thinkingIndicator as Record<string, unknown>;
|
|
175
|
+
if (typeof src.enabled === "boolean") ti.enabled = src.enabled;
|
|
176
|
+
if (Object.keys(ti).length > 0) config.thinkingIndicator = ti;
|
|
177
|
+
}
|
|
130
178
|
return config;
|
|
131
179
|
} catch {
|
|
132
180
|
return {};
|