archymedes-cli 2.2.0 → 2.5.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 +17 -7
- package/dist/{archymedes-76z6n643.mjs → archymedes-06fh0z84.mjs} +233 -12
- package/dist/archymedes-130jt0wr.mjs +1231 -0
- package/dist/{archymedes-pg3pvh9r.mjs → archymedes-138genyy.mjs} +214 -5
- package/dist/{archymedes-sc3mwttb.mjs → archymedes-2kvjaajw.mjs} +66 -25
- package/dist/archymedes-5vhvv8kr.mjs +1169 -0
- package/dist/{archymedes-wjaqydyg.mjs → archymedes-a3ms7jvr.mjs} +45 -29
- package/dist/{archymedes-cdgejs3p.mjs → archymedes-bmtdqqwt.mjs} +17 -44
- package/dist/{archymedes-npcrm9a0.mjs → archymedes-d3azqkay.mjs} +537 -9
- package/dist/archymedes-main.mjs +31452 -25912
- package/dist/archymedes-w4bjfye7.mjs +280 -0
- package/dist/{editor-screen-1b3z96tn.mjs → editor-screen-e01mn7dd.mjs} +62 -26
- package/dist/{factory-96yy6mxr.mjs → factory-hyv8agr0.mjs} +1 -1
- package/dist/{file-screen-m7q1xcer.mjs → file-screen-stcxznwy.mjs} +10 -8
- package/dist/guide-screen-w5nb9sry.mjs +273 -0
- package/dist/pager-screen-aamt6xv0.mjs +155 -0
- package/dist/projection-x6x6hm9t.mjs +248 -0
- package/dist/workspace-screen-62k6hnq7.mjs +70 -0
- package/package.json +1 -1
- package/dist/archymedes-5zn4zp84.mjs +0 -646
- package/dist/archymedes-r54qthg5.mjs +0 -495
- package/dist/guide-screen-aj9n9v80.mjs +0 -569
- package/dist/workspace-screen-w88mcw4w.mjs +0 -241
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import {
|
|
2
2
|
padToWidth,
|
|
3
3
|
progressBar,
|
|
4
|
+
scrollIndicator,
|
|
5
|
+
scrollPercent,
|
|
4
6
|
sliceToWidth
|
|
5
|
-
} from "./archymedes-
|
|
7
|
+
} from "./archymedes-5vhvv8kr.mjs";
|
|
8
|
+
import {
|
|
9
|
+
clip
|
|
10
|
+
} from "./archymedes-bmtdqqwt.mjs";
|
|
6
11
|
import {
|
|
7
12
|
ASCII_GLYPHS,
|
|
8
13
|
UNICODE_GLYPHS,
|
|
9
14
|
visibleWidth
|
|
10
|
-
} from "./archymedes-
|
|
15
|
+
} from "./archymedes-130jt0wr.mjs";
|
|
11
16
|
|
|
12
|
-
// packages/archymedes-cli/src/canvas.ts
|
|
17
|
+
// packages/archymedes-cli/src/render/canvas.ts
|
|
13
18
|
var BRAILLE_DOTS = [
|
|
14
19
|
[1, 2, 4, 64],
|
|
15
20
|
[8, 16, 32, 128]
|
|
@@ -95,7 +100,7 @@ function seriesBounds(values) {
|
|
|
95
100
|
return { low, high, span: high - low === 0 ? 1 : high - low };
|
|
96
101
|
}
|
|
97
102
|
|
|
98
|
-
// packages/archymedes-cli/src/charts.ts
|
|
103
|
+
// packages/archymedes-cli/src/render/charts.ts
|
|
99
104
|
function barChart(data, options) {
|
|
100
105
|
if (data.length === 0)
|
|
101
106
|
return [];
|
|
@@ -253,4 +258,208 @@ function heatStrip(data, options) {
|
|
|
253
258
|
});
|
|
254
259
|
}
|
|
255
260
|
|
|
256
|
-
|
|
261
|
+
// packages/archymedes-cli/src/ui/workspace-model.ts
|
|
262
|
+
function paneHeight(rows) {
|
|
263
|
+
return Math.max(1, rows - 4);
|
|
264
|
+
}
|
|
265
|
+
function selectedPane(snapshot) {
|
|
266
|
+
if (snapshot.panes.length === 0)
|
|
267
|
+
return;
|
|
268
|
+
const index = Math.max(0, Math.min(snapshot.selected, snapshot.panes.length - 1));
|
|
269
|
+
return snapshot.panes[index];
|
|
270
|
+
}
|
|
271
|
+
function visibleLines(pane, height, scroll) {
|
|
272
|
+
const clamped = Math.max(0, Math.min(scroll, Math.max(0, pane.lines.length - height)));
|
|
273
|
+
const end = pane.lines.length - clamped;
|
|
274
|
+
return pane.lines.slice(Math.max(0, end - height), end);
|
|
275
|
+
}
|
|
276
|
+
function atLiveEdge(pane, height, scroll) {
|
|
277
|
+
return Math.min(scroll, Math.max(0, pane.lines.length - height)) === 0;
|
|
278
|
+
}
|
|
279
|
+
function keyToAction(key, character) {
|
|
280
|
+
const name = key.name ?? "";
|
|
281
|
+
const isEscape = name === "escape" || name === "\x1B";
|
|
282
|
+
const isEnter = name === "return" || name === "enter" || name === "\r" || name === `
|
|
283
|
+
`;
|
|
284
|
+
if (isEscape || name === "q" && !key.ctrl || key.ctrl && name === "c")
|
|
285
|
+
return { kind: "exit" };
|
|
286
|
+
if (isEnter)
|
|
287
|
+
return { kind: "focus" };
|
|
288
|
+
if (name === "tab")
|
|
289
|
+
return { kind: "cycle", step: key.shift ? -1 : 1 };
|
|
290
|
+
if (name === "left")
|
|
291
|
+
return { kind: "cycle", step: -1 };
|
|
292
|
+
if (name === "right")
|
|
293
|
+
return { kind: "cycle", step: 1 };
|
|
294
|
+
if (name === "up" || name === "k")
|
|
295
|
+
return { kind: "scroll", lines: 1 };
|
|
296
|
+
if (name === "down" || name === "j")
|
|
297
|
+
return { kind: "scroll", lines: -1 };
|
|
298
|
+
if (name === "pageup")
|
|
299
|
+
return { kind: "scroll", lines: 10 };
|
|
300
|
+
if (name === "pagedown")
|
|
301
|
+
return { kind: "scroll", lines: -10 };
|
|
302
|
+
if (name === "home" || character === "g")
|
|
303
|
+
return { kind: "top" };
|
|
304
|
+
if (name === "end" || character === "G")
|
|
305
|
+
return { kind: "bottom" };
|
|
306
|
+
const digit = character && /^[1-9]$/.test(character) ? Number(character) : undefined;
|
|
307
|
+
if (digit !== undefined)
|
|
308
|
+
return { kind: "select", index: digit - 1 };
|
|
309
|
+
return { kind: "none" };
|
|
310
|
+
}
|
|
311
|
+
function applyAction(snapshot, action) {
|
|
312
|
+
const count = snapshot.panes.length;
|
|
313
|
+
if (count === 0 || action.kind === "none" || action.kind === "exit" || action.kind === "focus")
|
|
314
|
+
return snapshot;
|
|
315
|
+
if (action.kind === "select") {
|
|
316
|
+
if (action.index < 0 || action.index >= count)
|
|
317
|
+
return snapshot;
|
|
318
|
+
return { ...snapshot, selected: action.index, scroll: 0 };
|
|
319
|
+
}
|
|
320
|
+
if (action.kind === "cycle") {
|
|
321
|
+
const next = ((snapshot.selected + action.step) % count + count) % count;
|
|
322
|
+
return { ...snapshot, selected: next, scroll: 0 };
|
|
323
|
+
}
|
|
324
|
+
const pane = selectedPane(snapshot);
|
|
325
|
+
const height = paneHeight(snapshot.rows);
|
|
326
|
+
const furthest = Math.max(0, (pane?.lines.length ?? 0) - height);
|
|
327
|
+
if (action.kind === "bottom")
|
|
328
|
+
return { ...snapshot, scroll: 0 };
|
|
329
|
+
if (action.kind === "top")
|
|
330
|
+
return { ...snapshot, scroll: furthest };
|
|
331
|
+
return { ...snapshot, scroll: Math.max(0, Math.min(snapshot.scroll + action.lines, furthest)) };
|
|
332
|
+
}
|
|
333
|
+
function paneTabs(snapshot) {
|
|
334
|
+
const selected = Math.max(0, Math.min(snapshot.selected, snapshot.panes.length - 1));
|
|
335
|
+
return snapshot.panes.map((pane, index) => ({
|
|
336
|
+
label: `${index + 1} ${pane.title}`,
|
|
337
|
+
active: index === selected,
|
|
338
|
+
status: pane.status
|
|
339
|
+
}));
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
class PaneActivity {
|
|
343
|
+
capacity;
|
|
344
|
+
series = new Map;
|
|
345
|
+
seen = new Map;
|
|
346
|
+
constructor(capacity = 48) {
|
|
347
|
+
this.capacity = capacity;
|
|
348
|
+
}
|
|
349
|
+
sample(panes) {
|
|
350
|
+
const live = new Set(panes.map((pane) => pane.key));
|
|
351
|
+
for (const key of [...this.series.keys()]) {
|
|
352
|
+
if (!live.has(key)) {
|
|
353
|
+
this.series.delete(key);
|
|
354
|
+
this.seen.delete(key);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
const result = new Map;
|
|
358
|
+
for (const pane of panes) {
|
|
359
|
+
const produced = pane.lines.length + pane.dropped;
|
|
360
|
+
const previous = this.seen.get(pane.key);
|
|
361
|
+
this.seen.set(pane.key, produced);
|
|
362
|
+
const stream = this.series.get(pane.key) ?? new StreamSeries(this.capacity);
|
|
363
|
+
this.series.set(pane.key, stream);
|
|
364
|
+
if (previous !== undefined)
|
|
365
|
+
stream.push(Math.max(0, produced - previous));
|
|
366
|
+
result.set(pane.key, stream.values());
|
|
367
|
+
}
|
|
368
|
+
return result;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
function tabPanes(views, linesFor) {
|
|
372
|
+
return views.map((view) => {
|
|
373
|
+
const record = linesFor(view.id);
|
|
374
|
+
const where = view.backend && view.backend !== "local" ? ` · ${view.backend}` : "";
|
|
375
|
+
return {
|
|
376
|
+
kind: "tab",
|
|
377
|
+
key: `${view.id}`,
|
|
378
|
+
title: view.title,
|
|
379
|
+
subtitle: `${view.model ?? "model unknown"}${where}${view.cost ? ` · ${view.cost}` : ""}`,
|
|
380
|
+
status: view.status,
|
|
381
|
+
lines: record.lines,
|
|
382
|
+
dropped: record.dropped
|
|
383
|
+
};
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
var STATUS_MARK = {
|
|
387
|
+
running: "●",
|
|
388
|
+
failed: "✕",
|
|
389
|
+
done: "✓",
|
|
390
|
+
idle: " "
|
|
391
|
+
};
|
|
392
|
+
var WORKSPACE_LEGEND = "1-9 pane · ←→ move · ↑↓ scroll · g/G ends · Esc back";
|
|
393
|
+
function paneBar(snapshot, columns) {
|
|
394
|
+
const tabs = paneTabs(snapshot);
|
|
395
|
+
const cells = tabs.map((tab) => ` ${STATUS_MARK[tab.status] ?? " "}${tab.label} `);
|
|
396
|
+
const full = cells.join("");
|
|
397
|
+
if (full.length <= columns)
|
|
398
|
+
return full || " no panes ";
|
|
399
|
+
const selected = Math.max(0, Math.min(snapshot.selected, tabs.length - 1));
|
|
400
|
+
return `${selected > 0 ? "‹ " : ""}${cells[selected] ?? " no panes "}${selected < tabs.length - 1 ? " ›" : ""}`;
|
|
401
|
+
}
|
|
402
|
+
function composeFrame(snapshot) {
|
|
403
|
+
const rows = [];
|
|
404
|
+
const columns = Math.max(1, Math.floor(snapshot.columns));
|
|
405
|
+
const rowCount = Math.max(1, Math.floor(snapshot.rows));
|
|
406
|
+
const pane = selectedPane(snapshot);
|
|
407
|
+
const height = paneHeight(rowCount);
|
|
408
|
+
const theme = snapshot.palette.tokens;
|
|
409
|
+
const bar = paneBar(snapshot, columns);
|
|
410
|
+
rows.push({ text: bar || " no panes ", bold: true, color: theme.primary });
|
|
411
|
+
const scrolled = pane && !atLiveEdge(pane, height, snapshot.scroll);
|
|
412
|
+
const position = (() => {
|
|
413
|
+
if (!pane || !scrolled)
|
|
414
|
+
return "";
|
|
415
|
+
const maxOffset = Math.max(0, pane.lines.length - height);
|
|
416
|
+
const offsetFromTop = maxOffset - Math.min(snapshot.scroll, maxOffset);
|
|
417
|
+
return scrollIndicator(scrollPercent(offsetFromTop, pane.lines.length, height));
|
|
418
|
+
})();
|
|
419
|
+
const dropped = pane && pane.dropped > 0 ? ` (${pane.dropped} earlier lines dropped)` : "";
|
|
420
|
+
const header = pane ? `${pane.title} ${pane.subtitle}${dropped}` : "nothing open";
|
|
421
|
+
const activityWidth = Math.min(24, Math.max(0, columns - visibleWidth(header) - 3));
|
|
422
|
+
const activity = pane?.activity && pane.activity.length > 1 && activityWidth >= 8 ? ` ${waveLine(pane.activity, { width: activityWidth })}` : "";
|
|
423
|
+
rows.push({
|
|
424
|
+
text: pane ? `${header}${activity}` : header,
|
|
425
|
+
bold: true,
|
|
426
|
+
color: pane?.status === "failed" ? theme.error : pane?.status === "running" ? theme.success : theme.accent
|
|
427
|
+
});
|
|
428
|
+
const body = pane ? visibleLines(pane, height, snapshot.scroll) : [];
|
|
429
|
+
for (let index = 0;index < height; index += 1)
|
|
430
|
+
rows.push({ text: body[index] ?? "" });
|
|
431
|
+
while (rows.length < rowCount - 1)
|
|
432
|
+
rows.push({ text: "" });
|
|
433
|
+
rows.length = Math.max(0, rowCount - 1);
|
|
434
|
+
rows.push({
|
|
435
|
+
text: `${WORKSPACE_LEGEND}${scrolled ? ` ▲ scrolled back ${position}` : ""}`,
|
|
436
|
+
dim: true,
|
|
437
|
+
color: theme.textMuted
|
|
438
|
+
});
|
|
439
|
+
return rows.map((row) => ({ ...row, text: clip(row.text, columns) }));
|
|
440
|
+
}
|
|
441
|
+
function buildWorkspaceSnapshot(input) {
|
|
442
|
+
const panes = [
|
|
443
|
+
...tabPanes(input.views, input.linesFor),
|
|
444
|
+
...input.jobs.map((job) => ({
|
|
445
|
+
kind: "job",
|
|
446
|
+
key: job.id,
|
|
447
|
+
title: `job ${job.id.slice(-6)}`,
|
|
448
|
+
subtitle: job.objective,
|
|
449
|
+
status: job.done ? "done" : "running",
|
|
450
|
+
lines: job.lines,
|
|
451
|
+
dropped: job.dropped
|
|
452
|
+
}))
|
|
453
|
+
];
|
|
454
|
+
const activity = input.activity.sample(panes);
|
|
455
|
+
return {
|
|
456
|
+
panes: panes.map((pane) => ({ ...pane, activity: activity.get(pane.key) })),
|
|
457
|
+
selected: Math.max(0, input.views.findIndex((view) => view.active)),
|
|
458
|
+
scroll: 0,
|
|
459
|
+
palette: input.palette,
|
|
460
|
+
columns: input.columns,
|
|
461
|
+
rows: input.rows
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
export { barChart, lineChart, plotSeries, scatterChart, waveLine, heatStrip, keyToAction, applyAction, PaneActivity, composeFrame, buildWorkspaceSnapshot };
|
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
|
-
CYAN,
|
|
3
|
-
DIM,
|
|
4
|
-
GREEN,
|
|
5
2
|
GUTTER,
|
|
6
|
-
MAGENTA,
|
|
7
|
-
RED,
|
|
8
3
|
clip,
|
|
9
|
-
|
|
10
|
-
} from "./archymedes-
|
|
4
|
+
panel
|
|
5
|
+
} from "./archymedes-bmtdqqwt.mjs";
|
|
11
6
|
import {
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
BOLD,
|
|
8
|
+
DIM,
|
|
9
|
+
UNICODE_GLYPHS,
|
|
10
|
+
codeStyle,
|
|
11
|
+
highlightSyntax,
|
|
12
|
+
newSyntaxState,
|
|
13
|
+
paint,
|
|
14
|
+
paintAll,
|
|
15
|
+
roleCode,
|
|
16
|
+
visibleWidth
|
|
17
|
+
} from "./archymedes-130jt0wr.mjs";
|
|
14
18
|
|
|
15
|
-
// packages/archymedes-cli/src/code-view.ts
|
|
19
|
+
// packages/archymedes-cli/src/render/code-view.ts
|
|
16
20
|
var MAX_DIFF_CELLS = 250000;
|
|
17
21
|
function diffLines(before, after) {
|
|
18
22
|
const left = before === "" ? [] : before.split(`
|
|
@@ -57,6 +61,12 @@ function diffLines(before, after) {
|
|
|
57
61
|
}
|
|
58
62
|
return result;
|
|
59
63
|
}
|
|
64
|
+
function diffStat(diff) {
|
|
65
|
+
return {
|
|
66
|
+
added: diff.filter((line) => line.kind === "add").length,
|
|
67
|
+
removed: diff.filter((line) => line.kind === "remove").length
|
|
68
|
+
};
|
|
69
|
+
}
|
|
60
70
|
function condenseDiff(diff, context = 2) {
|
|
61
71
|
const keep = new Array(diff.length).fill(false);
|
|
62
72
|
diff.forEach((line, index) => {
|
|
@@ -186,7 +196,9 @@ var KEYWORDS = new Set([
|
|
|
186
196
|
"yield"
|
|
187
197
|
]);
|
|
188
198
|
var LITERALS = new Set(["true", "false", "null", "nil", "None", "True", "False", "undefined", "self", "this"]);
|
|
189
|
-
function highlightCode(line, depth) {
|
|
199
|
+
function highlightCode(line, depth, palette, language, state) {
|
|
200
|
+
if (codeStyle().colors === "vscode")
|
|
201
|
+
return highlightSyntax(line, { depth, palette, ...language ? { language } : {}, ...state ? { state } : {} });
|
|
190
202
|
if (depth === "none")
|
|
191
203
|
return line;
|
|
192
204
|
const commentAt = findCommentStart(line);
|
|
@@ -194,13 +206,13 @@ function highlightCode(line, depth) {
|
|
|
194
206
|
const comment = commentAt === -1 ? "" : paint(line.slice(commentAt), DIM, depth);
|
|
195
207
|
const painted = code.replace(/("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|`(?:[^`\\]|\\.)*`)|\b(\d+(?:\.\d+)?)\b|\b([A-Za-z_$][\w$]*)\b/g, (whole, text, numeric, word) => {
|
|
196
208
|
if (text !== undefined)
|
|
197
|
-
return paint(text,
|
|
209
|
+
return paint(text, roleCode("success", palette, depth), depth);
|
|
198
210
|
if (numeric !== undefined)
|
|
199
|
-
return paint(numeric,
|
|
211
|
+
return paint(numeric, roleCode("accent", palette, depth), depth);
|
|
200
212
|
if (word !== undefined && KEYWORDS.has(word))
|
|
201
|
-
return paint(word,
|
|
213
|
+
return paint(word, roleCode("primary", palette, depth), depth);
|
|
202
214
|
if (word !== undefined && LITERALS.has(word))
|
|
203
|
-
return paint(word,
|
|
215
|
+
return paint(word, roleCode("accent", palette, depth), depth);
|
|
204
216
|
return whole;
|
|
205
217
|
});
|
|
206
218
|
return `${painted}${comment}`;
|
|
@@ -239,11 +251,14 @@ function renderCode(content, style, options = {}) {
|
|
|
239
251
|
const start = options.startLine ?? 1;
|
|
240
252
|
const numberWidth = String(start + lines.length - 1).length;
|
|
241
253
|
const bodyWidth = Math.max(8, style.width - GUTTER.length - numberWidth - 4);
|
|
242
|
-
const render = (from, to) =>
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
254
|
+
const render = (from, to) => {
|
|
255
|
+
const syntax = newSyntaxState();
|
|
256
|
+
return lines.slice(from, to).map((line, index) => {
|
|
257
|
+
const number = paint(String(start + from + index).padStart(numberWidth), DIM, style.depth);
|
|
258
|
+
const painted = options.highlight === false ? line : highlightCode(line, style.depth, style.palette, options.language, syntax);
|
|
259
|
+
return `${number} ${clip(painted, bodyWidth, glyphs)}`;
|
|
260
|
+
});
|
|
261
|
+
};
|
|
247
262
|
const hidden = Math.max(0, lines.length - maxLines);
|
|
248
263
|
const shown = render(0, hidden > 0 ? maxLines : lines.length);
|
|
249
264
|
return {
|
|
@@ -259,12 +274,14 @@ function renderDiff(diff, style, options = {}) {
|
|
|
259
274
|
const maxLines = options.maxLines ?? 16;
|
|
260
275
|
const condensed = condenseDiff(diff);
|
|
261
276
|
const bodyWidth = Math.max(8, style.width - GUTTER.length - 4);
|
|
277
|
+
const vscode = codeStyle().colors === "vscode" && style.depth !== "none";
|
|
278
|
+
const bandWidth = Math.min(bodyWidth, Math.max(0, ...diff.map((line) => [...line.text].length)));
|
|
262
279
|
const row = (line) => {
|
|
263
280
|
if (line.kind === "gap")
|
|
264
281
|
return paint(`${glyphs.middot.repeat(3)} ${line.text}`, DIM, style.depth);
|
|
265
282
|
const mark = line.kind === "add" ? glyphs.plus : line.kind === "remove" ? glyphs.minus : " ";
|
|
266
|
-
const code = line.kind === "add" ?
|
|
267
|
-
const body = line.kind === "context" ? paint(line.text, DIM, style.depth) : highlightCode(line.text, style.depth);
|
|
283
|
+
const code = line.kind === "add" ? roleCode("success", style.palette, style.depth) : line.kind === "remove" ? roleCode("error", style.palette, style.depth) : DIM;
|
|
284
|
+
const body = line.kind === "context" ? vscode ? highlightCode(line.text, style.depth, style.palette, options.language) : paint(line.text, DIM, style.depth) : vscode ? highlightSyntax(line.text, { depth: style.depth, palette: style.palette, band: line.kind, padTo: bandWidth, ...options.language ? { language: options.language } : {} }) : highlightCode(line.text, style.depth, style.palette);
|
|
268
285
|
return `${paint(mark, code, style.depth)} ${clip(body, bodyWidth, glyphs)}`;
|
|
269
286
|
};
|
|
270
287
|
const rows = condensed.map(row);
|
|
@@ -277,8 +294,32 @@ function renderDiff(diff, style, options = {}) {
|
|
|
277
294
|
`)
|
|
278
295
|
};
|
|
279
296
|
}
|
|
280
|
-
function
|
|
281
|
-
|
|
297
|
+
function renderFileChange(change, style, options = {}) {
|
|
298
|
+
const language = languageOf(change.path);
|
|
299
|
+
const block = change.kind === "edit" ? renderDiff(diffLines(change.before ?? "", change.after ?? ""), style, { maxLines: options.maxLines, language }) : renderCode(change.content ?? "", style, { maxLines: options.maxLines, language });
|
|
300
|
+
const badge = change.kind === "edit" ? (() => {
|
|
301
|
+
const stat = diffStat(diffLines(change.before ?? "", change.after ?? ""));
|
|
302
|
+
return `+${stat.added} -${stat.removed}`;
|
|
303
|
+
})() : `${(change.content ?? "").split(`
|
|
304
|
+
`).length} lines · ${language}`;
|
|
305
|
+
const body = block.text.split(`
|
|
306
|
+
`);
|
|
307
|
+
const foot = block.hidden > 0 && options.expandHint ? [paint(`${(style.glyphs ?? UNICODE_GLYPHS).collapsed} ${block.hidden} more line${block.hidden === 1 ? "" : "s"} — ${options.expandHint}`, DIM, style.depth)] : [];
|
|
308
|
+
return {
|
|
309
|
+
text: panel([...body, ...foot], style, { title: `${change.kind === "edit" ? "diff" : "new file"} · ${change.path}`, badge, tone: change.kind === "edit" ? "accent" : "good" }),
|
|
310
|
+
hidden: block.hidden,
|
|
311
|
+
full: panel(block.full.split(`
|
|
312
|
+
`), style, { title: `${change.kind === "edit" ? "diff" : "new file"} · ${change.path}`, badge, tone: change.kind === "edit" ? "accent" : "good" })
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
function fenceHeader(language, style) {
|
|
316
|
+
const glyphs = style.glyphs ?? UNICODE_GLYPHS;
|
|
317
|
+
const label = language ? ` ${language} ` : glyphs.boxHorizontal.repeat(4);
|
|
318
|
+
const width = Math.max(0, style.width - GUTTER.length - visibleWidth(label) - 3);
|
|
319
|
+
return `${GUTTER}${paint(glyphs.boxTopLeft + glyphs.boxHorizontal, DIM, style.depth)}${paintAll(label, [roleCode("primary", style.palette, style.depth), BOLD], style.depth)}${paint(glyphs.boxHorizontal.repeat(Math.max(0, width)), DIM, style.depth)}`;
|
|
320
|
+
}
|
|
321
|
+
function describeChange(stat, depth, palette) {
|
|
322
|
+
return `${paint(`+${stat.added}`, roleCode("success", palette, depth), depth)} ${paint(`-${stat.removed}`, roleCode("error", palette, depth), depth)}`;
|
|
282
323
|
}
|
|
283
324
|
|
|
284
|
-
export { diffLines, languageOf, highlightCode, renderCode, renderDiff, describeChange };
|
|
325
|
+
export { diffLines, diffStat, languageOf, highlightCode, renderCode, renderDiff, renderFileChange, fenceHeader, describeChange };
|