archymedes-cli 2.1.0 → 2.3.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 +25 -0
- package/dist/{archymedes-brkqgrxv.mjs → archymedes-4kx65anz.mjs} +47 -50
- package/dist/{archymedes-jecyxv5c.mjs → archymedes-a10k8yrk.mjs} +218 -3
- package/dist/{archymedes-76z6n643.mjs → archymedes-aj30app4.mjs} +160 -150
- package/dist/{archymedes-0jxzsh4z.mjs → archymedes-d5wqcmdr.mjs} +97 -97
- package/dist/archymedes-dz59nvw7.mjs +315 -0
- package/dist/{archymedes-dwvn4c51.mjs → archymedes-g8y3rt6t.mjs} +220 -200
- package/dist/{archymedes-1g1y6q74.mjs → archymedes-h13ap0za.mjs} +1 -1
- package/dist/archymedes-main.mjs +17634 -14542
- package/dist/{archymedes-k1bx08z9.mjs → archymedes-sf9t1hz9.mjs} +481 -50
- package/dist/{archymedes-44c1mqas.mjs → archymedes-tsne2m7p.mjs} +17 -44
- package/dist/{archymedes-2tp22t9a.mjs → archymedes-twbks7g3.mjs} +9 -7
- package/dist/{editor-screen-51z7z11j.mjs → editor-screen-g08zzt70.mjs} +263 -14
- package/dist/{factory-96yy6mxr.mjs → factory-7vtm2fed.mjs} +326 -326
- package/dist/{file-screen-eg28a3ky.mjs → file-screen-ma9yxq2b.mjs} +9 -9
- package/dist/guide-screen-gd129txd.mjs +271 -0
- package/dist/{index-teq1cta4.mjs → index-qvgcwsvm.mjs} +1 -1
- package/dist/{node-0fh63p8z.mjs → node-mdgzx68h.mjs} +7 -7
- package/dist/{sandbox-templates-8sd1psez.mjs → sandbox-templates-9jcjws23.mjs} +2 -2
- package/dist/{workspace-screen-3zztn4by.mjs → workspace-screen-8cwk6jz9.mjs} +10 -9
- package/package.json +2 -2
- package/dist/guide-screen-mfvwkdhb.mjs +0 -565
|
@@ -1,141 +1,62 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
ANSI_PALETTE,
|
|
3
|
+
ASCII_GLYPHS,
|
|
4
|
+
BOLD,
|
|
5
|
+
DIM,
|
|
6
|
+
ITALIC,
|
|
7
|
+
STRIKE,
|
|
8
|
+
UNICODE_GLYPHS,
|
|
9
|
+
borderGlyphsFor,
|
|
10
|
+
paint,
|
|
11
|
+
rainbowText,
|
|
12
|
+
rgbTo256,
|
|
13
|
+
roleCode,
|
|
14
|
+
visibleWidth
|
|
15
|
+
} from "./archymedes-a10k8yrk.mjs";
|
|
4
16
|
|
|
5
|
-
//
|
|
6
|
-
var
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
bullet: "•",
|
|
17
|
-
ellipsis: "…",
|
|
18
|
-
middot: "·",
|
|
19
|
-
elbow: "⎿",
|
|
20
|
-
boxTopLeft: "╭",
|
|
21
|
-
boxTopRight: "╮",
|
|
22
|
-
boxBottomLeft: "╰",
|
|
23
|
-
boxBottomRight: "╯",
|
|
24
|
-
boxHorizontal: "─",
|
|
25
|
-
boxVertical: "│",
|
|
26
|
-
boxTeeLeft: "├",
|
|
27
|
-
boxTeeRight: "┤",
|
|
28
|
-
boxCross: "┼",
|
|
29
|
-
circleEmpty: "○",
|
|
30
|
-
circleHalf: "◐",
|
|
31
|
-
circleFull: "●",
|
|
32
|
-
checkbox: "☐",
|
|
33
|
-
checkboxDone: "☑",
|
|
34
|
-
paused: "⏸",
|
|
35
|
-
cancelled: "⊘",
|
|
36
|
-
treeBranch: "├─",
|
|
37
|
-
treeLast: "╰─",
|
|
38
|
-
treeTrunk: "│ ",
|
|
39
|
-
collapsed: "▸",
|
|
40
|
-
expanded: "▾",
|
|
41
|
-
arrowUp: "↑",
|
|
42
|
-
arrowLeft: "←",
|
|
43
|
-
arrowRight: "→",
|
|
44
|
-
arrowDown: "↓",
|
|
45
|
-
plus: "+",
|
|
46
|
-
minus: "-",
|
|
47
|
-
warning: "!",
|
|
48
|
-
effectWorkspace: "✎",
|
|
49
|
-
effectExternal: "◎",
|
|
50
|
-
sparkLevels: ["▁", "▂", "▃", "▄", "▅", "▆", "▇", "█"]
|
|
51
|
-
};
|
|
52
|
-
var ASCII_GLYPHS = {
|
|
53
|
-
starGlyphs: [".", ".", "+", "*", "*"],
|
|
54
|
-
spinnerFrames: ["-", "\\", "|", "/"],
|
|
55
|
-
star: "*",
|
|
56
|
-
starDim: "+",
|
|
57
|
-
check: "+",
|
|
58
|
-
cross: "x",
|
|
59
|
-
pending: "~",
|
|
60
|
-
prompt: ">",
|
|
61
|
-
caret: ">",
|
|
62
|
-
bullet: "-",
|
|
63
|
-
ellipsis: "...",
|
|
64
|
-
middot: "-",
|
|
65
|
-
elbow: "\\",
|
|
66
|
-
boxTopLeft: "+",
|
|
67
|
-
boxTopRight: "+",
|
|
68
|
-
boxBottomLeft: "+",
|
|
69
|
-
boxBottomRight: "+",
|
|
70
|
-
boxHorizontal: "-",
|
|
71
|
-
boxVertical: "|",
|
|
72
|
-
boxTeeLeft: "+",
|
|
73
|
-
boxTeeRight: "+",
|
|
74
|
-
boxCross: "+",
|
|
75
|
-
circleEmpty: "o",
|
|
76
|
-
circleHalf: "*",
|
|
77
|
-
circleFull: "*",
|
|
78
|
-
checkbox: "[ ]",
|
|
79
|
-
checkboxDone: "[x]",
|
|
80
|
-
paused: "=",
|
|
81
|
-
cancelled: "x",
|
|
82
|
-
treeBranch: "|-",
|
|
83
|
-
treeLast: "`-",
|
|
84
|
-
treeTrunk: "| ",
|
|
85
|
-
collapsed: ">",
|
|
86
|
-
expanded: "v",
|
|
87
|
-
arrowUp: "^",
|
|
88
|
-
arrowLeft: "<-",
|
|
89
|
-
arrowRight: "->",
|
|
90
|
-
arrowDown: "v",
|
|
91
|
-
plus: "+",
|
|
92
|
-
minus: "-",
|
|
93
|
-
warning: "!",
|
|
94
|
-
effectWorkspace: "w",
|
|
95
|
-
effectExternal: "e",
|
|
96
|
-
sparkLevels: [" ", ".", ":", "-", "=", "+", "*", "#"]
|
|
17
|
+
// src/terminal/output.ts
|
|
18
|
+
var terminalStream = {
|
|
19
|
+
write(text) {
|
|
20
|
+
process.stdout.write(text);
|
|
21
|
+
},
|
|
22
|
+
get columns() {
|
|
23
|
+
return process.stdout.columns;
|
|
24
|
+
},
|
|
25
|
+
get rows() {
|
|
26
|
+
return process.stdout.rows;
|
|
27
|
+
}
|
|
97
28
|
};
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
return
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
var STRIKE = "\x1B[9m";
|
|
118
|
-
var CYAN = "\x1B[36m";
|
|
119
|
-
var BLUE = "\x1B[34m";
|
|
120
|
-
var GREEN = "\x1B[32m";
|
|
121
|
-
var YELLOW = "\x1B[33m";
|
|
122
|
-
var ANSI = /\x1b\[[0-9;]*m/g;
|
|
123
|
-
function visibleWidth(text) {
|
|
124
|
-
let width = 0;
|
|
125
|
-
for (const character of text.replace(ANSI, "")) {
|
|
126
|
-
const code = character.codePointAt(0) ?? 0;
|
|
127
|
-
if (code >= 768 && code <= 879)
|
|
128
|
-
continue;
|
|
129
|
-
width += isWide(code) ? 2 : 1;
|
|
29
|
+
class OutputRouter {
|
|
30
|
+
target;
|
|
31
|
+
constructor(target = terminalStream) {
|
|
32
|
+
this.target = target;
|
|
33
|
+
}
|
|
34
|
+
get current() {
|
|
35
|
+
return this.target;
|
|
36
|
+
}
|
|
37
|
+
route(target) {
|
|
38
|
+
this.target = target;
|
|
39
|
+
}
|
|
40
|
+
write(text) {
|
|
41
|
+
this.target.write(text);
|
|
42
|
+
}
|
|
43
|
+
get columns() {
|
|
44
|
+
return this.target.columns;
|
|
45
|
+
}
|
|
46
|
+
get rows() {
|
|
47
|
+
return this.target.rows;
|
|
130
48
|
}
|
|
131
|
-
return width;
|
|
132
49
|
}
|
|
133
|
-
function
|
|
134
|
-
|
|
50
|
+
function replayLines(log, count) {
|
|
51
|
+
const lines = log.tail(count);
|
|
52
|
+
return { lines, dropped: log.dropped, omitted: Math.max(0, log.size - lines.length) };
|
|
135
53
|
}
|
|
54
|
+
|
|
55
|
+
// src/render/markdown.ts
|
|
56
|
+
var colour = (role, palette) => palette?.[role] || ANSI_PALETTE[role];
|
|
136
57
|
var INLINE_PATTERN = /(?<!\\)(`[^`\n]+`)|(?<!\\)(\*\*[^*\n]+\*\*)|(?<!\\)(__[^_\n]+__)|(?<!\\)(~~[^~\n]+~~)|(?<!\\)(\*[^*\n]+\*)|(?<!\\)(_[^_\n]+_)|(!?\[([^\]\n]+)\]\((https?:\/\/[^\s)\n]+)\))|(<(https?:\/\/[^>\s]+)>)/g;
|
|
137
58
|
var unescapeMarkdown = (text) => text.replace(/\\([\\`*_[\]{}()#+.!~>-])/g, "$1");
|
|
138
|
-
function parseInline(line) {
|
|
59
|
+
function parseInline(line, palette) {
|
|
139
60
|
const tokens = [];
|
|
140
61
|
let lastIndex = 0;
|
|
141
62
|
INLINE_PATTERN.lastIndex = 0;
|
|
@@ -144,7 +65,7 @@ function parseInline(line) {
|
|
|
144
65
|
tokens.push({ text: unescapeMarkdown(line.slice(lastIndex, match.index)), code: "" });
|
|
145
66
|
const [whole, code, boldStars, boldUnderscores, strike, italicStars, italicUnderscores, link, linkLabel, linkUrl, autolink, autolinkUrl] = match;
|
|
146
67
|
if (code !== undefined)
|
|
147
|
-
tokens.push({ text: code.slice(1, -1), code:
|
|
68
|
+
tokens.push({ text: code.slice(1, -1), code: colour("primary", palette) });
|
|
148
69
|
else if (boldStars !== undefined)
|
|
149
70
|
tokens.push({ text: boldStars.slice(2, -2), code: BOLD });
|
|
150
71
|
else if (boldUnderscores !== undefined)
|
|
@@ -156,18 +77,15 @@ function parseInline(line) {
|
|
|
156
77
|
else if (italicUnderscores !== undefined)
|
|
157
78
|
tokens.push({ text: italicUnderscores.slice(1, -1), code: ITALIC });
|
|
158
79
|
else if (link !== undefined)
|
|
159
|
-
tokens.push({ text: `${link.startsWith("!") ? `image: ${linkLabel}` : linkLabel} (${linkUrl})`, code:
|
|
80
|
+
tokens.push({ text: `${link.startsWith("!") ? `image: ${linkLabel}` : linkLabel} (${linkUrl})`, code: colour("primary", palette) });
|
|
160
81
|
else if (autolink !== undefined)
|
|
161
|
-
tokens.push({ text: autolinkUrl, code:
|
|
82
|
+
tokens.push({ text: autolinkUrl, code: colour("primary", palette) });
|
|
162
83
|
lastIndex = match.index + whole.length;
|
|
163
84
|
}
|
|
164
85
|
if (lastIndex < line.length)
|
|
165
86
|
tokens.push({ text: unescapeMarkdown(line.slice(lastIndex)), code: "" });
|
|
166
87
|
return tokens.filter((token) => token.text.length > 0);
|
|
167
88
|
}
|
|
168
|
-
function paint(text, code, depth) {
|
|
169
|
-
return depth === "none" || code === "" ? text : `${code}${text}${RESET}`;
|
|
170
|
-
}
|
|
171
89
|
function wrapTokens(tokens, width, options) {
|
|
172
90
|
const firstPrefix = options.firstPrefix ?? "";
|
|
173
91
|
const continuationPrefix = options.continuationPrefix ?? "";
|
|
@@ -263,7 +181,7 @@ function renderTableLine(cells, separator, width, depth, glyphs) {
|
|
|
263
181
|
return `${glyphs.boxVertical}${rendered.map((cell) => ` ${cell} `).join(glyphs.boxVertical)}${glyphs.boxVertical}`;
|
|
264
182
|
}
|
|
265
183
|
function renderMarkdownLine(line, state, options) {
|
|
266
|
-
const { width, depth } = options;
|
|
184
|
+
const { width, depth, palette } = options;
|
|
267
185
|
const glyphs = options.glyphs ?? UNICODE_GLYPHS;
|
|
268
186
|
const fence = FENCE.exec(line);
|
|
269
187
|
if (fence) {
|
|
@@ -280,7 +198,7 @@ function renderMarkdownLine(line, state, options) {
|
|
|
280
198
|
return [paint(` ${glyphs.boxTopLeft}${glyphs.boxHorizontal}${label}${glyphs.boxHorizontal.repeat(Math.max(0, ruleWidth - drawn))}`, DIM, depth)];
|
|
281
199
|
}
|
|
282
200
|
if (state.inFence) {
|
|
283
|
-
return [`${paint(` ${glyphs.boxVertical} `, DIM, depth)}${paint(line,
|
|
201
|
+
return [`${paint(` ${glyphs.boxVertical} `, DIM, depth)}${paint(line, colour("success", palette), depth)}`];
|
|
284
202
|
}
|
|
285
203
|
const table = tableCells(line);
|
|
286
204
|
if (table) {
|
|
@@ -293,14 +211,14 @@ function renderMarkdownLine(line, state, options) {
|
|
|
293
211
|
const heading = HEADING.exec(line);
|
|
294
212
|
if (heading) {
|
|
295
213
|
const level = heading[1].length;
|
|
296
|
-
const code = level <= 2 ? `${BOLD}${
|
|
214
|
+
const code = level <= 2 ? `${BOLD}${colour("primary", palette)}` : BOLD;
|
|
297
215
|
const tokens = parseInline(heading[2]).map((token) => ({ text: token.text, code }));
|
|
298
216
|
return wrapTokens(tokens, width, { depth });
|
|
299
217
|
}
|
|
300
218
|
const task = TASK.exec(line);
|
|
301
219
|
if (task) {
|
|
302
|
-
return wrapTokens(parseInline(task[3]), width, {
|
|
303
|
-
firstPrefix: `${task[1]}${paint(task[2].trim() ? glyphs.checkboxDone : glyphs.checkbox, task[2].trim() ?
|
|
220
|
+
return wrapTokens(parseInline(task[3], palette), width, {
|
|
221
|
+
firstPrefix: `${task[1]}${paint(task[2].trim() ? glyphs.checkboxDone : glyphs.checkbox, task[2].trim() ? colour("success", palette) : colour("secondary", palette), depth)} `,
|
|
304
222
|
continuationPrefix: `${task[1]} `,
|
|
305
223
|
depth
|
|
306
224
|
});
|
|
@@ -308,8 +226,8 @@ function renderMarkdownLine(line, state, options) {
|
|
|
308
226
|
const bullet = BULLET.exec(line);
|
|
309
227
|
if (bullet) {
|
|
310
228
|
const indent = bullet[1];
|
|
311
|
-
return wrapTokens(parseInline(bullet[3]), width, {
|
|
312
|
-
firstPrefix: `${indent}${paint(glyphs.bullet,
|
|
229
|
+
return wrapTokens(parseInline(bullet[3], palette), width, {
|
|
230
|
+
firstPrefix: `${indent}${paint(glyphs.bullet, colour("secondary", palette), depth)} `,
|
|
313
231
|
continuationPrefix: `${indent} `,
|
|
314
232
|
depth
|
|
315
233
|
});
|
|
@@ -318,8 +236,8 @@ function renderMarkdownLine(line, state, options) {
|
|
|
318
236
|
if (numbered) {
|
|
319
237
|
const indent = numbered[1];
|
|
320
238
|
const marker = numbered[2];
|
|
321
|
-
return wrapTokens(parseInline(numbered[3]), width, {
|
|
322
|
-
firstPrefix: `${indent}${paint(marker,
|
|
239
|
+
return wrapTokens(parseInline(numbered[3], palette), width, {
|
|
240
|
+
firstPrefix: `${indent}${paint(marker, colour("secondary", palette), depth)} `,
|
|
323
241
|
continuationPrefix: `${indent}${" ".repeat(marker.length + 1)}`,
|
|
324
242
|
depth
|
|
325
243
|
});
|
|
@@ -327,14 +245,14 @@ function renderMarkdownLine(line, state, options) {
|
|
|
327
245
|
const quote = BLOCKQUOTE.exec(line);
|
|
328
246
|
if (quote) {
|
|
329
247
|
return wrapTokens([{ text: quote[1], code: DIM }], width, {
|
|
330
|
-
firstPrefix: paint(`${glyphs.boxVertical} `,
|
|
331
|
-
continuationPrefix: paint(`${glyphs.boxVertical} `,
|
|
248
|
+
firstPrefix: paint(`${glyphs.boxVertical} `, colour("accent", palette), depth),
|
|
249
|
+
continuationPrefix: paint(`${glyphs.boxVertical} `, colour("accent", palette), depth),
|
|
332
250
|
depth
|
|
333
251
|
});
|
|
334
252
|
}
|
|
335
253
|
if (line.trim() === "")
|
|
336
254
|
return [""];
|
|
337
|
-
return wrapTokens(parseInline(line), width, { depth });
|
|
255
|
+
return wrapTokens(parseInline(line, palette), width, { depth });
|
|
338
256
|
}
|
|
339
257
|
function renderMarkdown(text, options) {
|
|
340
258
|
const state = newMarkdownState();
|
|
@@ -347,29 +265,7 @@ function renderMarkdown(text, options) {
|
|
|
347
265
|
`);
|
|
348
266
|
}
|
|
349
267
|
|
|
350
|
-
//
|
|
351
|
-
var terminalStream = {
|
|
352
|
-
write(text) {
|
|
353
|
-
process.stdout.write(text);
|
|
354
|
-
},
|
|
355
|
-
get columns() {
|
|
356
|
-
return process.stdout.columns;
|
|
357
|
-
},
|
|
358
|
-
get rows() {
|
|
359
|
-
return process.stdout.rows;
|
|
360
|
-
}
|
|
361
|
-
};
|
|
362
|
-
|
|
363
|
-
// packages/archymedes-cli/src/tui.ts
|
|
364
|
-
var RESET2 = "\x1B[0m";
|
|
365
|
-
var DIM2 = "\x1B[2m";
|
|
366
|
-
var CYAN2 = "\x1B[36m";
|
|
367
|
-
var GREEN2 = "\x1B[32m";
|
|
368
|
-
var YELLOW2 = "\x1B[33m";
|
|
369
|
-
var RED = "\x1B[31m";
|
|
370
|
-
function paint2(text, code, depth) {
|
|
371
|
-
return depth === "none" ? text : `${code}${text}${RESET2}`;
|
|
372
|
-
}
|
|
268
|
+
// src/render/tui.ts
|
|
373
269
|
function archymedesSpinnerFrame(index, glyphs = UNICODE_GLYPHS) {
|
|
374
270
|
const frames = glyphs.spinnerFrames;
|
|
375
271
|
const normalized = Number.isFinite(index) ? Math.max(0, Math.floor(index)) : 0;
|
|
@@ -541,7 +437,7 @@ function table(columns, rows, options) {
|
|
|
541
437
|
const row = (cells) => `${border.vertical} ${widths.map((width, index) => cell(cells[index] ?? "", width)).join(` ${border.vertical} `)} ${border.vertical}`;
|
|
542
438
|
return [
|
|
543
439
|
rule(border.topLeft, border.horizontal, border.topRight),
|
|
544
|
-
row(columns.map((header) =>
|
|
440
|
+
row(columns.map((header) => paint(header, DIM, options.depth))),
|
|
545
441
|
rule(border.teeLeft, border.cross, border.teeRight),
|
|
546
442
|
...rows.map((line) => row(line)),
|
|
547
443
|
rule(border.bottomLeft, border.horizontal, border.bottomRight)
|
|
@@ -617,12 +513,12 @@ function stepProgress(done, total, options) {
|
|
|
617
513
|
});
|
|
618
514
|
return `${label}${counted} ${bar}`;
|
|
619
515
|
}
|
|
620
|
-
function formatStatusLine(fields, width, depth, glyphs = UNICODE_GLYPHS, accent =
|
|
516
|
+
function formatStatusLine(fields, width, depth, glyphs = UNICODE_GLYPHS, accent = ANSI_PALETTE.primary) {
|
|
621
517
|
const label = activityLabel(fields.phase ?? "thinking", fields.operation, fields.elapsedMs);
|
|
622
518
|
const ellipsis = glyphs.ellipsis;
|
|
623
519
|
const separator = ` ${glyphs.middot} `;
|
|
624
520
|
const left = `${fields.spinnerGlyph} ${label}${ellipsis}`;
|
|
625
|
-
const paintedLeft = `${
|
|
521
|
+
const paintedLeft = `${paint(fields.spinnerGlyph, accent, depth)} ${paint(`${label}${ellipsis}`, DIM, depth)}`;
|
|
626
522
|
const optional = [
|
|
627
523
|
fields.cost,
|
|
628
524
|
fields.tokens > 0 ? formatTokens(fields.tokens) : "",
|
|
@@ -642,36 +538,124 @@ function formatStatusLine(fields, width, depth, glyphs = UNICODE_GLYPHS, accent
|
|
|
642
538
|
return paintedLeft;
|
|
643
539
|
const compact = `${fields.spinnerGlyph} ${ellipsis}`;
|
|
644
540
|
if (visibleWidth(compact) <= width)
|
|
645
|
-
return `${
|
|
646
|
-
return width > 0 ?
|
|
541
|
+
return `${paint(fields.spinnerGlyph, accent, depth)} ${paint(ellipsis, DIM, depth)}`;
|
|
542
|
+
return width > 0 ? paint(glyphs.star, accent, depth) : "";
|
|
647
543
|
}
|
|
648
544
|
const gap = Math.max(1, width - visibleWidth(left) - right.length);
|
|
649
|
-
return `${paintedLeft}${" ".repeat(gap)}${
|
|
545
|
+
return `${paintedLeft}${" ".repeat(gap)}${paint(right, DIM, depth)}`;
|
|
650
546
|
}
|
|
651
547
|
kept = kept.slice(0, -1);
|
|
652
548
|
}
|
|
653
549
|
}
|
|
550
|
+
|
|
551
|
+
class StatusBar {
|
|
552
|
+
stream;
|
|
553
|
+
linesDrawn = 0;
|
|
554
|
+
constructor(stream = terminalStream) {
|
|
555
|
+
this.stream = stream;
|
|
556
|
+
}
|
|
557
|
+
render(fields, depth, glyphs = UNICODE_GLYPHS, accent) {
|
|
558
|
+
this.clear();
|
|
559
|
+
const width = this.stream.columns ?? 80;
|
|
560
|
+
const line = formatStatusLine(fields, width, depth, glyphs, accent);
|
|
561
|
+
this.stream.write(`${line}
|
|
562
|
+
`);
|
|
563
|
+
this.linesDrawn = 1;
|
|
564
|
+
}
|
|
565
|
+
renderLine(text) {
|
|
566
|
+
this.clear();
|
|
567
|
+
if (text === "")
|
|
568
|
+
return;
|
|
569
|
+
this.stream.write(`${text}
|
|
570
|
+
`);
|
|
571
|
+
this.linesDrawn = 1;
|
|
572
|
+
}
|
|
573
|
+
clear() {
|
|
574
|
+
if (this.linesDrawn === 0)
|
|
575
|
+
return;
|
|
576
|
+
for (let index = 0;index < this.linesDrawn; index += 1) {
|
|
577
|
+
this.stream.write("\x1B[1A\x1B[2K");
|
|
578
|
+
}
|
|
579
|
+
this.linesDrawn = 0;
|
|
580
|
+
}
|
|
581
|
+
}
|
|
654
582
|
function rowsOccupied(text, columns) {
|
|
655
583
|
const width = visibleWidth(text);
|
|
656
584
|
if (width === 0)
|
|
657
585
|
return 1;
|
|
658
586
|
return Math.ceil(width / Math.max(1, columns));
|
|
659
587
|
}
|
|
588
|
+
|
|
589
|
+
class ReplaceableBlock {
|
|
590
|
+
stream;
|
|
591
|
+
columns;
|
|
592
|
+
entries = [];
|
|
593
|
+
rows = 0;
|
|
594
|
+
constructor(stream = terminalStream, columns = () => process.stdout.columns ?? 80) {
|
|
595
|
+
this.stream = stream;
|
|
596
|
+
this.columns = columns;
|
|
597
|
+
}
|
|
598
|
+
append(text) {
|
|
599
|
+
this.entries.push(text);
|
|
600
|
+
this.stream.write(`${text}
|
|
601
|
+
`);
|
|
602
|
+
this.rows += rowsOccupied(text, this.columns());
|
|
603
|
+
return this.entries.length - 1;
|
|
604
|
+
}
|
|
605
|
+
update(index, text) {
|
|
606
|
+
if (index < 0 || index >= this.entries.length)
|
|
607
|
+
return false;
|
|
608
|
+
this.entries[index] = text;
|
|
609
|
+
for (let row = 0;row < this.rows; row += 1)
|
|
610
|
+
this.stream.write("\x1B[1A\x1B[2K");
|
|
611
|
+
this.stream.write("\r");
|
|
612
|
+
this.rows = 0;
|
|
613
|
+
for (const entry of this.entries) {
|
|
614
|
+
this.stream.write(`${entry}
|
|
615
|
+
`);
|
|
616
|
+
this.rows += rowsOccupied(entry, this.columns());
|
|
617
|
+
}
|
|
618
|
+
return true;
|
|
619
|
+
}
|
|
620
|
+
updateAll(texts) {
|
|
621
|
+
for (let row = 0;row < this.rows; row += 1)
|
|
622
|
+
this.stream.write("\x1B[1A\x1B[2K");
|
|
623
|
+
this.stream.write("\r");
|
|
624
|
+
for (let index = 0;index < texts.length && index < this.entries.length; index += 1)
|
|
625
|
+
this.entries[index] = texts[index];
|
|
626
|
+
this.rows = 0;
|
|
627
|
+
for (const entry of this.entries) {
|
|
628
|
+
this.stream.write(`${entry}
|
|
629
|
+
`);
|
|
630
|
+
this.rows += rowsOccupied(entry, this.columns());
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
forget() {
|
|
634
|
+
this.entries = [];
|
|
635
|
+
this.rows = 0;
|
|
636
|
+
}
|
|
637
|
+
get active() {
|
|
638
|
+
return this.entries.length > 0;
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
|
|
660
642
|
class MarkdownStream {
|
|
661
643
|
stream;
|
|
662
644
|
depth;
|
|
663
645
|
columns;
|
|
664
646
|
live;
|
|
665
647
|
glyphs;
|
|
648
|
+
palette;
|
|
666
649
|
pending = "";
|
|
667
650
|
atLineStart = true;
|
|
668
651
|
state = newMarkdownState();
|
|
669
|
-
constructor(stream = terminalStream, depth = "none", columns = () => process.stdout.columns ?? 80, live = true, glyphs = UNICODE_GLYPHS) {
|
|
652
|
+
constructor(stream = terminalStream, depth = "none", columns = () => process.stdout.columns ?? 80, live = true, glyphs = UNICODE_GLYPHS, palette) {
|
|
670
653
|
this.stream = stream;
|
|
671
654
|
this.depth = depth;
|
|
672
655
|
this.columns = columns;
|
|
673
656
|
this.live = live;
|
|
674
657
|
this.glyphs = glyphs;
|
|
658
|
+
this.palette = palette;
|
|
675
659
|
}
|
|
676
660
|
get active() {
|
|
677
661
|
return this.live ? this.pending !== "" : !this.atLineStart;
|
|
@@ -708,7 +692,7 @@ class MarkdownStream {
|
|
|
708
692
|
if (this.pending !== "")
|
|
709
693
|
this.finalizeLine();
|
|
710
694
|
if (this.state.inFence) {
|
|
711
|
-
const rendered = renderMarkdownLine("```", this.state, { width: this.columns(), depth: this.depth, glyphs: this.glyphs });
|
|
695
|
+
const rendered = renderMarkdownLine("```", this.state, { width: this.columns(), depth: this.depth, glyphs: this.glyphs, palette: this.palette });
|
|
712
696
|
this.stream.write(`${rendered.join(`
|
|
713
697
|
`)}
|
|
714
698
|
`);
|
|
@@ -721,7 +705,7 @@ class MarkdownStream {
|
|
|
721
705
|
}
|
|
722
706
|
finalizeLine() {
|
|
723
707
|
this.erasePending();
|
|
724
|
-
const rendered = renderMarkdownLine(this.pending, this.state, { width: this.columns(), depth: this.depth, glyphs: this.glyphs });
|
|
708
|
+
const rendered = renderMarkdownLine(this.pending, this.state, { width: this.columns(), depth: this.depth, glyphs: this.glyphs, palette: this.palette });
|
|
725
709
|
this.stream.write(`${rendered.join(`
|
|
726
710
|
`)}
|
|
727
711
|
`);
|
|
@@ -739,17 +723,24 @@ class MarkdownStream {
|
|
|
739
723
|
function box(lines, options) {
|
|
740
724
|
const terminalWidth = options.width ?? process.stdout.columns ?? 80;
|
|
741
725
|
const glyphs = options.glyphs ?? UNICODE_GLYPHS;
|
|
742
|
-
const border = borderGlyphsFor(options.borderStyle ?? "round", glyphs);
|
|
726
|
+
const border = borderGlyphsFor(options.borderStyle ?? options.palette?.borderStyle ?? "round", glyphs);
|
|
743
727
|
const titleWidth = options.title ? visibleWidth(options.title) : 0;
|
|
744
|
-
const titlePaint =
|
|
745
|
-
const
|
|
728
|
+
const titlePaint = roleCode(TONE_ROLE[options.titleColor ?? "cyan"], options.palette, options.depth);
|
|
729
|
+
const rainbowBorder = options.borderColor === "rainbow";
|
|
730
|
+
const edge = (text, phase = 0) => {
|
|
731
|
+
if (options.borderColor === undefined)
|
|
732
|
+
return text;
|
|
733
|
+
return rainbowBorder ? rainbowText(text, options.depth, phase) : paint(text, roleCode(TONE_ROLE[options.borderColor], options.palette, options.depth), options.depth);
|
|
734
|
+
};
|
|
746
735
|
const contentWidth = Math.min(Math.max(titleWidth, ...lines.map((line) => visibleWidth(line)), 1), Math.max(1, terminalWidth - 4));
|
|
747
736
|
const horizontal = border.horizontal.repeat(contentWidth + 2);
|
|
748
|
-
const top = options.title ? `${edge(`${border.topLeft}${border.horizontal}
|
|
749
|
-
const
|
|
750
|
-
const
|
|
737
|
+
const top = options.title ? `${edge(`${border.topLeft}${border.horizontal}`, 0)} ${paint(options.title, titlePaint, options.depth)} ${edge(`${border.horizontal.repeat(Math.max(0, contentWidth - titleWidth - 1))}${border.topRight}`, 0.08)}` : edge(`${border.topLeft}${horizontal}${border.topRight}`, 0);
|
|
738
|
+
const bottomPhase = (lines.length + 1) * 0.1;
|
|
739
|
+
const bottom = edge(`${border.bottomLeft}${horizontal}${border.bottomRight}`, bottomPhase);
|
|
740
|
+
const body = lines.map((line, index) => {
|
|
751
741
|
const clipped = visibleWidth(line) > contentWidth ? `${sliceToWidth(line, contentWidth - visibleWidth(glyphs.ellipsis))}${glyphs.ellipsis}` : line;
|
|
752
|
-
|
|
742
|
+
const rowPhase = (index + 1) * 0.1;
|
|
743
|
+
return `${edge(border.vertical, rowPhase)} ${clipped}${" ".repeat(Math.max(0, contentWidth - visibleWidth(clipped)))} ${edge(border.vertical, rowPhase)}`;
|
|
753
744
|
});
|
|
754
745
|
return [top, ...body, bottom].join(`
|
|
755
746
|
`);
|
|
@@ -785,22 +776,22 @@ function joinHorizontal(left, right, options) {
|
|
|
785
776
|
const separator = options.separator ?? " ";
|
|
786
777
|
return `${padToWidth(left, options.leftWidth, options.leftAlign)}${separator}${padToWidth(right, options.rightWidth, options.rightAlign)}`;
|
|
787
778
|
}
|
|
788
|
-
var
|
|
789
|
-
var
|
|
779
|
+
var TONE_ROLE = { cyan: "primary", green: "success", yellow: "warning", red: "error" };
|
|
780
|
+
var MODE_ROLE = { plan: "warning", auto: "success", build: "primary", defender: "error" };
|
|
790
781
|
var PROMPT_CHROME_COLUMNS = 6;
|
|
791
782
|
function renderPromptBox(options) {
|
|
792
783
|
const { mode, workspace, depth } = options;
|
|
793
784
|
const glyphs = options.glyphs ?? UNICODE_GLYPHS;
|
|
794
785
|
const border = borderGlyphsFor(options.palette?.borderStyle ?? options.borderStyle ?? "round", glyphs);
|
|
795
786
|
const width = Math.max(12, options.width);
|
|
796
|
-
const primary = options.palette
|
|
797
|
-
const modeColor =
|
|
798
|
-
const horizontal = (count) =>
|
|
787
|
+
const primary = roleCode("primary", options.palette, depth);
|
|
788
|
+
const modeColor = roleCode(MODE_ROLE[mode] ?? "primary", options.palette, depth);
|
|
789
|
+
const horizontal = (count) => paint(border.horizontal.repeat(Math.max(0, count)), primary, depth);
|
|
799
790
|
const CHROME = PROMPT_CHROME_COLUMNS;
|
|
800
791
|
const status = options.status ?? "";
|
|
801
792
|
const separator = ` ${glyphs.middot} `;
|
|
802
|
-
const full = `${
|
|
803
|
-
const compact = `${
|
|
793
|
+
const full = `${paint(glyphs.star, primary, depth)} ${paint("archymedes", primary, depth)}${separator}${paint(mode, modeColor, depth)}`;
|
|
794
|
+
const compact = `${paint(glyphs.star, primary, depth)} ${paint(mode, modeColor, depth)}`;
|
|
804
795
|
const statusRoom = status === "" ? 0 : visibleWidth(status) + 2;
|
|
805
796
|
const showStatus = status !== "" && width - CHROME - 1 - statusRoom - visibleWidth(compact) >= 0;
|
|
806
797
|
const room = width - CHROME - 1 - (showStatus ? statusRoom : 0);
|
|
@@ -808,19 +799,48 @@ function renderPromptBox(options) {
|
|
|
808
799
|
let title;
|
|
809
800
|
if (workspaceRoom >= 4) {
|
|
810
801
|
const shown = visibleWidth(workspace) <= workspaceRoom ? workspace : `${sliceToWidth(workspace, Math.max(0, workspaceRoom - visibleWidth(glyphs.ellipsis)))}${glyphs.ellipsis}`;
|
|
811
|
-
title = `${full}${separator}${
|
|
802
|
+
title = `${full}${separator}${paint(shown, DIM, depth)}`;
|
|
812
803
|
} else if (visibleWidth(full) <= room)
|
|
813
804
|
title = full;
|
|
814
805
|
else if (visibleWidth(compact) <= room)
|
|
815
806
|
title = compact;
|
|
816
807
|
else
|
|
817
|
-
title =
|
|
808
|
+
title = paint(glyphs.star, primary, depth);
|
|
818
809
|
const tail = showStatus ? ` ${status} ` : "";
|
|
819
810
|
const filler = Math.max(1, width - visibleWidth(title) - visibleWidth(tail) - CHROME);
|
|
820
|
-
const top = `${
|
|
821
|
-
const prefix = `${
|
|
822
|
-
const bottom = `${
|
|
811
|
+
const top = `${paint(`${border.topLeft}${border.horizontal}`, primary, depth)} ${title} ${horizontal(filler)}${tail}${horizontal(1)}${paint(border.topRight, primary, depth)}`;
|
|
812
|
+
const prefix = `${paint(border.vertical, primary, depth)} ${paint(glyphs.caret, modeColor, depth)} `;
|
|
813
|
+
const bottom = `${paint(border.bottomLeft, primary, depth)}${horizontal(width - 2)}${paint(border.bottomRight, primary, depth)}`;
|
|
823
814
|
return { top, prefix, bottom };
|
|
824
815
|
}
|
|
816
|
+
function wrapPlain(text, width) {
|
|
817
|
+
const lines = [];
|
|
818
|
+
let current = "";
|
|
819
|
+
for (const word of text.split(/\s+/)) {
|
|
820
|
+
if (word === "")
|
|
821
|
+
continue;
|
|
822
|
+
const candidate = current === "" ? word : `${current} ${word}`;
|
|
823
|
+
if (visibleWidth(candidate) <= width) {
|
|
824
|
+
current = candidate;
|
|
825
|
+
continue;
|
|
826
|
+
}
|
|
827
|
+
if (current !== "")
|
|
828
|
+
lines.push(current);
|
|
829
|
+
if (visibleWidth(word) > width) {
|
|
830
|
+
let rest = word;
|
|
831
|
+
while (visibleWidth(rest) > width) {
|
|
832
|
+
const chunk = sliceToWidth(rest, width);
|
|
833
|
+
lines.push(chunk);
|
|
834
|
+
rest = rest.slice(chunk.length);
|
|
835
|
+
}
|
|
836
|
+
current = rest;
|
|
837
|
+
} else {
|
|
838
|
+
current = word;
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
if (current !== "")
|
|
842
|
+
lines.push(current);
|
|
843
|
+
return lines.length === 0 ? [""] : lines;
|
|
844
|
+
}
|
|
825
845
|
|
|
826
|
-
export {
|
|
846
|
+
export { terminalStream, OutputRouter, replayLines, newMarkdownState, renderMarkdownLine, renderMarkdown, archymedesSpinnerFrame, SpringAnimator, sparkline, progressBar, table, scrollPercent, scrollIndicator, paginator, stepProgress, formatStatusLine, StatusBar, rowsOccupied, ReplaceableBlock, MarkdownStream, box, sliceToWidth, padToWidth, joinHorizontal, renderPromptBox, wrapPlain };
|