reslop 0.2.7 → 0.3.1
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 +30 -1
- package/README.md +16 -14
- package/bin/reslop.js +8 -5
- package/lib/agents/agents.js +573 -0
- package/lib/agents/allow.js +71 -0
- package/lib/agents/allow.json +17 -0
- package/lib/agents/models.js +467 -0
- package/lib/api.js +15 -12
- package/lib/cli.js +43 -68
- package/lib/{files.js → common/files.js} +48 -55
- package/lib/{find.js → common/find.js} +1 -1
- package/lib/common/format.js +101 -0
- package/lib/{utilities.js → common/process.js} +7 -95
- package/lib/common/tasks.json +27 -0
- package/lib/common/utilities.js +112 -0
- package/lib/dashboard/git.js +9 -16
- package/lib/dashboard/model.js +90 -49
- package/lib/dashboard/npm.js +17 -13
- package/lib/dashboard/tree.js +27 -30
- package/lib/{session → dashboard}/watch.js +36 -31
- package/lib/{workspace.js → dashboard/workspace.js} +23 -38
- package/lib/{deps.js → deps/deps.js} +31 -45
- package/lib/{deps-diff.js → deps/diff.js} +35 -25
- package/lib/{manifest.js → deps/manifest.js} +47 -30
- package/lib/diff/align.js +1 -2
- package/lib/diff/diff.js +2 -2
- package/lib/diff/display.js +29 -5
- package/lib/diff/inline.js +10 -14
- package/lib/diff/items.js +6 -4
- package/lib/diff/patch.js +39 -3
- package/lib/diff/unit.js +45 -16
- package/lib/{git-branches.js → git/branches.js} +53 -48
- package/lib/{git-deps.js → git/deps.js} +151 -95
- package/lib/git/git.js +71 -0
- package/lib/git/worktree.js +504 -0
- package/lib/highlight/bash.js +1 -2
- package/lib/highlight/csv.js +1 -2
- package/lib/highlight/dot.js +1 -2
- package/lib/{highlight.js → highlight/highlight.js} +42 -11
- package/lib/highlight/html.js +20 -18
- package/lib/highlight/json.js +1 -2
- package/lib/highlight/log.js +1 -2
- package/lib/highlight/txt.js +1 -2
- package/lib/{session → input}/actions.js +114 -48
- package/lib/{editor.js → input/editor.js} +16 -8
- package/lib/{keys.js → input/keys.js} +24 -45
- package/lib/input/line-edit.js +78 -0
- package/lib/input/menu-pick.js +70 -0
- package/lib/render/agents.js +642 -0
- package/lib/render/branches.js +4 -5
- package/lib/render/commits.js +54 -64
- package/lib/render/{dash-activity.js → dashboard/activity.js} +25 -40
- package/lib/render/{dash-blocks.js → dashboard/blocks.js} +131 -137
- package/lib/render/{dashboard.js → dashboard/dashboard.js} +25 -22
- package/lib/render/diff.js +166 -45
- package/lib/render/field.js +131 -0
- package/lib/render/files.js +9 -14
- package/lib/render/footer.js +385 -0
- package/lib/render/frame.js +123 -25
- package/lib/render/header.js +176 -0
- package/lib/render/log.js +320 -0
- package/lib/render/menu.js +60 -0
- package/lib/render/notes.js +16 -11
- package/lib/render/npm.js +322 -196
- package/lib/render/packages.js +9 -13
- package/lib/render/primitives.js +101 -15
- package/lib/render/render.js +7 -11
- package/lib/render/repos.js +13 -25
- package/lib/render/status.js +370 -0
- package/lib/render/status.json +85 -0
- package/lib/render/{dash-table.js → table.js} +13 -60
- package/lib/render/tiles.js +109 -48
- package/lib/render/unit.js +32 -13
- package/lib/{report-model.js → report/model.js} +4 -6
- package/lib/{report-parse.js → report/parse.js} +9 -14
- package/lib/{report-render.js → report/render.js} +48 -19
- package/lib/{report-run.js → report/run.js} +42 -30
- package/lib/{report-test.js → report/test.js} +56 -55
- package/lib/{report-tools.js → report/tools.js} +24 -33
- package/lib/review/agent-instructions.md +14 -0
- package/lib/review/format.js +420 -0
- package/lib/{review-merge.js → review/merge.js} +9 -8
- package/lib/review/review.js +190 -0
- package/lib/review/store.js +281 -0
- package/lib/review/templates.js +83 -0
- package/lib/runs/commands.js +14 -0
- package/lib/runs/logs.js +299 -0
- package/lib/runs/output.js +174 -0
- package/lib/runs/process.js +113 -0
- package/lib/{runs.js → runs/runs.js} +84 -36
- package/lib/runs/scripts.js +150 -0
- package/lib/session/agents/agents.js +976 -0
- package/lib/session/agents/job.js +320 -0
- package/lib/session/agents/jobs.js +355 -0
- package/lib/session/agents/options.js +153 -0
- package/lib/session/agents/plans.js +83 -0
- package/lib/session/branches.js +33 -40
- package/lib/session/change-actions.js +34 -100
- package/lib/session/commit.js +91 -52
- package/lib/session/compose.js +189 -147
- package/lib/session/dashboard.js +23 -22
- package/lib/session/dispatch.js +86 -21
- package/lib/session/files-pane.js +47 -26
- package/lib/session/find.js +16 -29
- package/lib/session/import.js +93 -0
- package/lib/session/items.js +8 -17
- package/lib/session/lifecycle.js +78 -72
- package/lib/session/load.js +2 -4
- package/lib/session/navigation.js +6 -3
- package/lib/session/npm/history.js +250 -0
- package/lib/session/npm/npm.js +836 -0
- package/lib/session/{packages.js → npm/packages.js} +21 -14
- package/lib/session/ops.js +125 -34
- package/lib/session/pointer.js +202 -10
- package/lib/session/prefs.js +112 -0
- package/lib/session/reads.js +109 -0
- package/lib/session/review.js +28 -10
- package/lib/session/run-panel.js +40 -0
- package/lib/{session.js → session/session.js} +158 -63
- package/lib/session/tasks.js +321 -66
- package/lib/session/templates.js +1 -1
- package/lib/session/terminal.js +94 -12
- package/lib/session/unit.js +35 -30
- package/lib/session/update.js +194 -6
- package/lib/session/view.js +65 -65
- package/lib/session/workspace.js +39 -78
- package/lib/{capabilities.js → source/capabilities.js} +3 -12
- package/lib/{github.js → source/github.js} +102 -32
- package/lib/{gitlab.js → source/gitlab.js} +87 -10
- package/lib/{remote.js → source/remote.js} +144 -40
- package/lib/source/review-threads.graphql +20 -0
- package/lib/source/source.js +74 -0
- package/lib/term/ansi.js +396 -0
- package/lib/{clipboard.js → term/clipboard.js} +3 -6
- package/lib/{select.js → term/select.js} +4 -3
- package/lib/term/themes/dark.json +122 -0
- package/lib/term/themes/light.json +122 -0
- package/lib/term/wide.txt +21 -0
- package/lib/{wrap.js → term/wrap.js} +4 -4
- package/package.json +2 -2
- package/lib/ansi.js +0 -545
- package/lib/detect.js +0 -34
- package/lib/diff/edit.js +0 -33
- package/lib/git-worktree.js +0 -455
- package/lib/git.js +0 -79
- package/lib/npm-commands.js +0 -522
- package/lib/render/chrome.js +0 -806
- package/lib/render/present.js +0 -19
- package/lib/render/report.js +0 -43
- package/lib/render/search.js +0 -25
- package/lib/review.js +0 -745
- package/lib/session/accessors.js +0 -26
- package/lib/session/edit-click.js +0 -57
- package/lib/session/npm.js +0 -452
- package/lib/session/progress.js +0 -41
- package/lib/source.js +0 -36
- package/lib/update.js +0 -192
- /package/lib/{git-reword-todo.js → git/reword-todo.js} +0 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
{
|
|
2
|
+
"busy": [
|
|
3
|
+
"pulling",
|
|
4
|
+
"pushing",
|
|
5
|
+
"loading",
|
|
6
|
+
"importing",
|
|
7
|
+
"checking npm",
|
|
8
|
+
"updating reslop",
|
|
9
|
+
"npm i",
|
|
10
|
+
"npm uninstall",
|
|
11
|
+
"npm audit fix",
|
|
12
|
+
"running",
|
|
13
|
+
"checking out",
|
|
14
|
+
"creating branch",
|
|
15
|
+
"rebasing",
|
|
16
|
+
"dropping",
|
|
17
|
+
"committing",
|
|
18
|
+
"updating",
|
|
19
|
+
"rewording",
|
|
20
|
+
"force pushing"
|
|
21
|
+
],
|
|
22
|
+
"info": [
|
|
23
|
+
"copied",
|
|
24
|
+
"staged",
|
|
25
|
+
"unstaged",
|
|
26
|
+
"not staged",
|
|
27
|
+
"dropped",
|
|
28
|
+
"already staged",
|
|
29
|
+
"read only",
|
|
30
|
+
"transitive",
|
|
31
|
+
"nothing to review",
|
|
32
|
+
"nothing to commit",
|
|
33
|
+
"not installed",
|
|
34
|
+
"no plan",
|
|
35
|
+
"returned",
|
|
36
|
+
"stopped",
|
|
37
|
+
"started",
|
|
38
|
+
"unified",
|
|
39
|
+
"mixed",
|
|
40
|
+
"side-by-side",
|
|
41
|
+
"line numbers",
|
|
42
|
+
"no line numbers",
|
|
43
|
+
"dark",
|
|
44
|
+
"light",
|
|
45
|
+
"saved",
|
|
46
|
+
"reloaded",
|
|
47
|
+
"not a diff block",
|
|
48
|
+
"file scope",
|
|
49
|
+
"diff mode",
|
|
50
|
+
"committed",
|
|
51
|
+
"amended",
|
|
52
|
+
"reworded",
|
|
53
|
+
"fixup",
|
|
54
|
+
"updated",
|
|
55
|
+
"imported",
|
|
56
|
+
"pulled",
|
|
57
|
+
"pushed",
|
|
58
|
+
"force pushed",
|
|
59
|
+
"checked out",
|
|
60
|
+
"created",
|
|
61
|
+
"empty branch name",
|
|
62
|
+
"empty commit message",
|
|
63
|
+
"terminated",
|
|
64
|
+
"verbose",
|
|
65
|
+
"filtered",
|
|
66
|
+
"fast on",
|
|
67
|
+
"fast off",
|
|
68
|
+
"logged in",
|
|
69
|
+
"logging in",
|
|
70
|
+
"ignored",
|
|
71
|
+
"already ignored",
|
|
72
|
+
"brief",
|
|
73
|
+
"full"
|
|
74
|
+
],
|
|
75
|
+
"infoPrefix": [
|
|
76
|
+
"checked out ",
|
|
77
|
+
"created ",
|
|
78
|
+
"rebased onto ",
|
|
79
|
+
"dropped ",
|
|
80
|
+
"exit ",
|
|
81
|
+
"model ",
|
|
82
|
+
"updated ",
|
|
83
|
+
"installed "
|
|
84
|
+
]
|
|
85
|
+
}
|
|
@@ -1,45 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const {
|
|
5
|
-
const files = require('../files.js');
|
|
6
|
-
const { relativeAge } = files;
|
|
7
|
-
const ansi = require('../ansi.js');
|
|
8
|
-
const { visibleWidth, graphemes, graphemeWidth } = ansi;
|
|
3
|
+
const { num } = require('../common/format.js');
|
|
4
|
+
const { visibleWidth, graphemes, graphemeWidth } = require('../term/ansi.js');
|
|
9
5
|
const tiles = require('./tiles.js');
|
|
10
6
|
const { seg, segmentsWidth, clipSegments, titleSegments } = tiles;
|
|
11
|
-
const
|
|
12
|
-
const { HEAT_MS } = tree;
|
|
7
|
+
const { HEAT_MS } = require('../dashboard/tree.js');
|
|
13
8
|
|
|
14
9
|
const MIN_FLEX = 6;
|
|
15
|
-
const SECONDS_AGO = /^\d+s ago$/;
|
|
16
|
-
|
|
17
|
-
const trimmed = (value) =>
|
|
18
|
-
value >= 10 ? `${Math.round(value)}` : `${Math.round(value * 10) / 10}`;
|
|
19
|
-
|
|
20
|
-
const num = (value) => {
|
|
21
|
-
const n = Math.max(0, Math.round(value));
|
|
22
|
-
if (n >= 1e6) return `${trimmed(n / 1e6)}m`;
|
|
23
|
-
if (n >= 1e4) return `${trimmed(n / 1e3)}k`;
|
|
24
|
-
return `${n}`;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const size = (bytes) => bytesToSize(bytes > 0 ? bytes : 0);
|
|
28
|
-
|
|
29
|
-
const ago = (at, now) => {
|
|
30
|
-
if (!at) return '';
|
|
31
|
-
const text = relativeAge(at, now);
|
|
32
|
-
return SECONDS_AGO.test(text) ? '<1m ago' : text;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const duration = (ms) => {
|
|
36
|
-
const value = Math.max(0, ms);
|
|
37
|
-
if (value < 1000) return `${Math.round(value)}ms`;
|
|
38
|
-
if (value < 60000) return `${(value / 1000).toFixed(1)}s`;
|
|
39
|
-
const minutes = Math.floor(value / 60000);
|
|
40
|
-
const seconds = Math.floor((value % 60000) / 1000);
|
|
41
|
-
return `${minutes}m${`${seconds}`.padStart(2, '0')}s`;
|
|
42
|
-
};
|
|
43
10
|
|
|
44
11
|
const isHot = (at, now) => at > 0 && now - at < HEAT_MS;
|
|
45
12
|
|
|
@@ -49,7 +16,15 @@ const delta = (value, now, at) => {
|
|
|
49
16
|
return seg(`▼${num(-value)}`, 'del', true);
|
|
50
17
|
};
|
|
51
18
|
|
|
52
|
-
const
|
|
19
|
+
const notice = (text, titleLine) => {
|
|
20
|
+
const rows = Array.isArray(text) ? text : [text];
|
|
21
|
+
const lines = rows.map((row) => [seg(row, 'muted')]);
|
|
22
|
+
const block = { badge: [], center: true, lines };
|
|
23
|
+
if (titleLine) block.titleLine = titleLine;
|
|
24
|
+
return block;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const waiting = (text) => notice(text);
|
|
53
28
|
|
|
54
29
|
const cell = (text, tone = 'text', align = 'l', bold = false) => ({
|
|
55
30
|
segs: [seg(text, tone, bold)],
|
|
@@ -246,23 +221,6 @@ const titleAside = (tile, aside, width, badge = []) => {
|
|
|
246
221
|
return [...left, seg(' '.repeat(Math.max(1, gap))), ...aside];
|
|
247
222
|
};
|
|
248
223
|
|
|
249
|
-
const stat = (label, value, tone = 'text', bold = false) => ({
|
|
250
|
-
label,
|
|
251
|
-
value: typeof value === 'string' ? [seg(value, tone, bold)] : value,
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
const pairRows = (items, perRow = 2) => {
|
|
255
|
-
const rows = [];
|
|
256
|
-
for (let i = 0; i < items.length; i += perRow) {
|
|
257
|
-
const row = [];
|
|
258
|
-
for (const item of items.slice(i, i + perRow)) {
|
|
259
|
-
row.push(cell(item.label, 'muted'), cellSegs(item.value));
|
|
260
|
-
}
|
|
261
|
-
rows.push(row);
|
|
262
|
-
}
|
|
263
|
-
return rows;
|
|
264
|
-
};
|
|
265
|
-
|
|
266
224
|
const pickGroups = (folders, exts, rows) => {
|
|
267
225
|
const count = Math.max(0, rows);
|
|
268
226
|
const dirs = folders.slice(0, count);
|
|
@@ -275,19 +233,14 @@ const labelOf = (key, isDir) => {
|
|
|
275
233
|
};
|
|
276
234
|
|
|
277
235
|
module.exports = {
|
|
278
|
-
num,
|
|
279
|
-
size,
|
|
280
|
-
ago,
|
|
281
|
-
duration,
|
|
282
236
|
isHot,
|
|
283
237
|
delta,
|
|
238
|
+
notice,
|
|
284
239
|
waiting,
|
|
285
240
|
cell,
|
|
286
241
|
cellSegs,
|
|
287
242
|
flexCell,
|
|
288
243
|
tableLines,
|
|
289
|
-
stat,
|
|
290
|
-
pairRows,
|
|
291
244
|
pickGroups,
|
|
292
245
|
labelOf,
|
|
293
246
|
titleAside,
|
package/lib/render/tiles.js
CHANGED
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
|
|
3
|
+
const { clamp } = require('../common/utilities.js');
|
|
4
|
+
|
|
5
|
+
const {
|
|
6
|
+
THEME,
|
|
7
|
+
paint,
|
|
8
|
+
visibleWidth,
|
|
9
|
+
truncateVisible,
|
|
10
|
+
} = require('../term/ansi.js');
|
|
5
11
|
|
|
6
12
|
const GAP_X = 2;
|
|
7
13
|
const GAP_Y = 1;
|
|
8
14
|
const MIN_W = 34;
|
|
9
15
|
const MIN_H = 6;
|
|
10
16
|
const MAX_COLS = 4;
|
|
17
|
+
const MAX_NORMAL = 3;
|
|
18
|
+
const MAX_WIDE = 2;
|
|
11
19
|
const RULE = '─';
|
|
12
20
|
const ELLIPSIS = '…';
|
|
13
21
|
const BAR_ON = '█';
|
|
14
22
|
const BAR_OFF = '░';
|
|
15
|
-
const SPARK = '▁▂▃▄▅▆▇█';
|
|
16
23
|
const SPINNER = '⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏';
|
|
17
24
|
|
|
18
25
|
const seg = (text, tone = 'text', bold = false) => ({
|
|
@@ -36,8 +43,13 @@ const toneColors = () => ({
|
|
|
36
43
|
pkg: THEME.pkgFg,
|
|
37
44
|
chain: THEME.pkgChainFg,
|
|
38
45
|
heat: THEME.heatFg,
|
|
46
|
+
heat1: THEME.heat1,
|
|
47
|
+
heat2: THEME.heat2,
|
|
48
|
+
heat3: THEME.heat3,
|
|
49
|
+
heat4: THEME.heat4,
|
|
39
50
|
blink: THEME.heatBlinkFg,
|
|
40
51
|
key: THEME.dashKeyFg,
|
|
52
|
+
caption: THEME.dashCaptionFg,
|
|
41
53
|
});
|
|
42
54
|
|
|
43
55
|
const headColors = () => ({
|
|
@@ -91,7 +103,7 @@ const paintSegments = (segs, width, bg, color, fill = ' ', colors = null) => {
|
|
|
91
103
|
};
|
|
92
104
|
|
|
93
105
|
const barSegments = (ratio, width, tone = 'add') => {
|
|
94
|
-
const clamped =
|
|
106
|
+
const clamped = clamp(Number.isFinite(ratio) ? ratio : 0, 0, 1);
|
|
95
107
|
const on = Math.round(clamped * width);
|
|
96
108
|
return [
|
|
97
109
|
seg(BAR_ON.repeat(on), tone),
|
|
@@ -99,52 +111,67 @@ const barSegments = (ratio, width, tone = 'add') => {
|
|
|
99
111
|
];
|
|
100
112
|
};
|
|
101
113
|
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const top = SPARK.length - 1;
|
|
107
|
-
let out = '';
|
|
108
|
-
for (let i = 0; i < width; i++) {
|
|
109
|
-
const span = width <= 1 ? count - 1 : (i * (count - 1)) / (width - 1);
|
|
110
|
-
const at = Math.round(span);
|
|
111
|
-
const level = max > 0 ? Math.round((values[at] / max) * top) : 0;
|
|
112
|
-
out += SPARK[level];
|
|
113
|
-
}
|
|
114
|
-
return out;
|
|
114
|
+
const RUN_ICON = {
|
|
115
|
+
passed: ['✔', 'add'],
|
|
116
|
+
failed: ['✖', 'error'],
|
|
117
|
+
aborted: ['⊘', 'muted'],
|
|
115
118
|
};
|
|
116
119
|
|
|
117
120
|
const spinner = (frame) => SPINNER[Math.abs(frame ?? 0) % SPINNER.length];
|
|
118
121
|
|
|
122
|
+
const blinkTone = (frame) => (Math.abs(frame) % 2 ? 'hot' : 'warn');
|
|
123
|
+
|
|
119
124
|
const spread = (total, parts) => {
|
|
120
125
|
const base = Math.floor(total / parts);
|
|
121
126
|
const extra = total % parts;
|
|
122
127
|
return Array.from({ length: parts }, (_, i) => base + (i < extra ? 1 : 0));
|
|
123
128
|
};
|
|
124
129
|
|
|
125
|
-
const
|
|
130
|
+
const isWide = (tile) => tile.size === 'wide';
|
|
131
|
+
|
|
132
|
+
const rowCap = (row, tile, maxCols) => {
|
|
133
|
+
const wide = isWide(tile) || row.some(isWide);
|
|
134
|
+
const cap = wide ? MAX_WIDE : MAX_NORMAL;
|
|
135
|
+
return Math.min(maxCols, cap);
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const canFit = (row, tile, maxCols) => row.length < rowCap(row, tile, maxCols);
|
|
139
|
+
|
|
140
|
+
const packRows = (shown, maxCols) => {
|
|
141
|
+
const rows = [];
|
|
142
|
+
let current = [];
|
|
143
|
+
for (const tile of shown) {
|
|
144
|
+
if (current.length && !canFit(current, tile, maxCols)) {
|
|
145
|
+
rows.push(current);
|
|
146
|
+
current = [];
|
|
147
|
+
}
|
|
148
|
+
current.push(tile);
|
|
149
|
+
}
|
|
150
|
+
if (current.length) rows.push(current);
|
|
151
|
+
return rows;
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const placeBand = (row, width) => {
|
|
155
|
+
const size = row.length;
|
|
126
156
|
const room = Math.max(0, width - (size - 1) * GAP_X);
|
|
127
157
|
const widths = spread(room, size);
|
|
128
158
|
const tiles = [];
|
|
129
159
|
let x = 0;
|
|
130
160
|
for (let i = 0; i < size; i++) {
|
|
131
|
-
tiles.push({ id:
|
|
161
|
+
tiles.push({ id: row[i].id, x, w: widths[i] });
|
|
132
162
|
x += widths[i] + GAP_X;
|
|
133
163
|
}
|
|
134
164
|
return tiles;
|
|
135
165
|
};
|
|
136
166
|
|
|
137
|
-
const
|
|
138
|
-
const
|
|
139
|
-
const
|
|
140
|
-
const heights = spread(height - (rows - 1) * GAP_Y, rows);
|
|
167
|
+
const placePacked = (rows, width, height) => {
|
|
168
|
+
const count = Math.max(1, rows.length);
|
|
169
|
+
const heights = spread(height - (count - 1) * GAP_Y, count);
|
|
141
170
|
const bands = [];
|
|
142
|
-
let from = 0;
|
|
143
171
|
let y = 0;
|
|
144
|
-
for (let row = 0; row < rows; row++) {
|
|
145
|
-
const tiles = placeBand(
|
|
172
|
+
for (let row = 0; row < rows.length; row++) {
|
|
173
|
+
const tiles = placeBand(rows[row], width);
|
|
146
174
|
bands.push({ y, h: Math.max(1, heights[row]), tiles });
|
|
147
|
-
from += sizes[row];
|
|
148
175
|
y += heights[row] + GAP_Y;
|
|
149
176
|
}
|
|
150
177
|
return bands;
|
|
@@ -152,16 +179,16 @@ const placeTiles = (shown, cols, width, height) => {
|
|
|
152
179
|
|
|
153
180
|
const layoutTiles = (width, height, tiles) => {
|
|
154
181
|
const cap = Math.floor((width + GAP_X) / (MIN_W + GAP_X));
|
|
155
|
-
const maxCols =
|
|
182
|
+
const maxCols = clamp(cap, 1, MAX_COLS);
|
|
156
183
|
const ranked = [...tiles].sort((left, right) => left.rank - right.rank);
|
|
157
184
|
for (let count = tiles.length; count >= 1; count--) {
|
|
158
185
|
const keep = new Set(ranked.slice(0, count).map((tile) => tile.id));
|
|
159
186
|
const shown = tiles.filter((tile) => keep.has(tile.id));
|
|
160
|
-
const
|
|
161
|
-
const
|
|
162
|
-
const rowH = Math.floor((height - (
|
|
187
|
+
const rows = packRows(shown, maxCols);
|
|
188
|
+
const n = rows.length;
|
|
189
|
+
const rowH = Math.floor((height - (n - 1) * GAP_Y) / n);
|
|
163
190
|
if (rowH >= MIN_H || count === 1) {
|
|
164
|
-
return
|
|
191
|
+
return placePacked(rows, width, height);
|
|
165
192
|
}
|
|
166
193
|
}
|
|
167
194
|
return [];
|
|
@@ -202,18 +229,48 @@ const rowBackground = (index, filled, backs) => {
|
|
|
202
229
|
return backs.tile;
|
|
203
230
|
};
|
|
204
231
|
|
|
232
|
+
const centeredSegments = (line, room) => {
|
|
233
|
+
const clipped = clipSegments(line, room);
|
|
234
|
+
const pad = Math.floor((room - segmentsWidth(clipped)) / 2);
|
|
235
|
+
if (pad < 1) return clipped;
|
|
236
|
+
return [seg(' '.repeat(pad)), ...clipped];
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
const centeredBody = (lines, room, inner) => {
|
|
240
|
+
const count = Math.min(lines.length, room);
|
|
241
|
+
const start = Math.floor((room - count) / 2);
|
|
242
|
+
const rows = [];
|
|
243
|
+
for (let i = 0; i < room; i++) {
|
|
244
|
+
const at = i - start;
|
|
245
|
+
const line = at >= 0 && at < count ? lines[at] : null;
|
|
246
|
+
if (!line || !line.length) {
|
|
247
|
+
rows.push([]);
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
rows.push(centeredSegments(line, inner));
|
|
251
|
+
}
|
|
252
|
+
return rows;
|
|
253
|
+
};
|
|
254
|
+
|
|
205
255
|
const paintTile = (tile, content, width, height, color, backs = null) => {
|
|
206
256
|
const shade = backs ?? {
|
|
207
257
|
head: THEME.dashHeadBg,
|
|
208
258
|
tile: THEME.dashTileBg,
|
|
209
259
|
row: THEME.dashRowBg,
|
|
210
260
|
};
|
|
211
|
-
const
|
|
261
|
+
const lines = content.lines ?? [];
|
|
262
|
+
const { footer } = content;
|
|
212
263
|
const rows = [paintHead(tile, content, width, color, shade.head)];
|
|
213
264
|
const bodyRoom = footer ? height - 2 : height - 1;
|
|
265
|
+
const inner = Math.max(0, width - 2);
|
|
266
|
+
const centered = content.center ? centeredBody(lines, bodyRoom, inner) : null;
|
|
214
267
|
for (let i = 0; i < bodyRoom; i++) {
|
|
215
|
-
|
|
216
|
-
|
|
268
|
+
let line = [];
|
|
269
|
+
if (centered) line = centered[i];
|
|
270
|
+
else if (lines[i]) line = lines[i];
|
|
271
|
+
const filled = !centered && i < lines.length;
|
|
272
|
+
const bg = rowBackground(i, filled, shade);
|
|
273
|
+
rows.push(paintFramed(line, width, bg, color));
|
|
217
274
|
}
|
|
218
275
|
if (footer && height > 1) {
|
|
219
276
|
const bg = rowBackground(bodyRoom, true, shade);
|
|
@@ -272,12 +329,13 @@ const equalGrid = (width, height, count, minW = MIN_W, minH = MIN_H) => {
|
|
|
272
329
|
const shown = Math.min(safe, cap);
|
|
273
330
|
const score = shown * 1000000 + size.tileW * size.tileH;
|
|
274
331
|
if (!best || score > best.score) {
|
|
275
|
-
best = { cols, rows, cap, ...size, score };
|
|
332
|
+
best = { width, cols, rows, cap, ...size, score };
|
|
276
333
|
}
|
|
277
334
|
}
|
|
278
335
|
}
|
|
279
336
|
if (best) return best;
|
|
280
337
|
return {
|
|
338
|
+
width,
|
|
281
339
|
cols: 1,
|
|
282
340
|
rows: 1,
|
|
283
341
|
cap: 1,
|
|
@@ -290,7 +348,7 @@ const equalGrid = (width, height, count, minW = MIN_W, minH = MIN_H) => {
|
|
|
290
348
|
const pageWindow = (count, cursor, cap) => {
|
|
291
349
|
const room = Math.max(1, cap);
|
|
292
350
|
if (count <= room) return { start: 0, end: count };
|
|
293
|
-
const at =
|
|
351
|
+
const at = clamp(cursor, 0, count - 1);
|
|
294
352
|
let start = Math.floor(at / room) * room;
|
|
295
353
|
if (start + room > count) start = count - room;
|
|
296
354
|
return { start, end: start + room };
|
|
@@ -300,22 +358,24 @@ const placeEqualTiles = (tiles, grid) => {
|
|
|
300
358
|
const bands = [];
|
|
301
359
|
const cols = Math.max(1, grid.cols);
|
|
302
360
|
const rows = Math.ceil(tiles.length / cols);
|
|
361
|
+
const gaps = Math.max(0, cols - 1) * GAP_X;
|
|
362
|
+
const full = grid.width ?? cols * grid.tileW + gaps;
|
|
363
|
+
const room = Math.max(0, full - gaps);
|
|
364
|
+
const widths = spread(room, cols);
|
|
303
365
|
for (let row = 0; row < rows; row++) {
|
|
304
366
|
const slice = tiles.slice(row * cols, (row + 1) * cols);
|
|
305
367
|
if (!slice.length) break;
|
|
306
368
|
const placed = [];
|
|
369
|
+
let x = 0;
|
|
307
370
|
for (let i = 0; i < slice.length; i++) {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
w: grid.tileW,
|
|
312
|
-
});
|
|
371
|
+
const w = widths[i];
|
|
372
|
+
placed.push({ id: slice[i].id, x, w });
|
|
373
|
+
x += w + GAP_X;
|
|
313
374
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
});
|
|
375
|
+
const y = row * (grid.tileH + GAP_Y);
|
|
376
|
+
const h = grid.tileH;
|
|
377
|
+
const band = { y, h, tiles: placed };
|
|
378
|
+
bands.push(band);
|
|
319
379
|
}
|
|
320
380
|
return bands;
|
|
321
381
|
};
|
|
@@ -340,8 +400,9 @@ module.exports = {
|
|
|
340
400
|
segmentsWidth,
|
|
341
401
|
clipSegments,
|
|
342
402
|
barSegments,
|
|
343
|
-
|
|
403
|
+
RUN_ICON,
|
|
344
404
|
spinner,
|
|
405
|
+
blinkTone,
|
|
345
406
|
titleSegments,
|
|
346
407
|
layoutTiles,
|
|
347
408
|
equalGrid,
|
package/lib/render/unit.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
const { detectLang } = require('../highlight/highlight.js');
|
|
4
|
+
const { sameHunk } = require('../diff/diff.js');
|
|
5
|
+
const { paneResult, lazyRows } = require('./primitives.js');
|
|
6
|
+
const {
|
|
7
|
+
paintDiffLine,
|
|
8
|
+
expandSoftRows,
|
|
9
|
+
codeHits,
|
|
10
|
+
viewDigits,
|
|
11
|
+
} = require('./diff.js');
|
|
12
12
|
|
|
13
13
|
const paintBodyUnit = (view, width, color) => {
|
|
14
14
|
const { item, codeOverlay: overlay } = view;
|
|
@@ -17,14 +17,33 @@ const paintBodyUnit = (view, width, color) => {
|
|
|
17
17
|
view.mode === 'compose' && typeof overlay?.cursor === 'number';
|
|
18
18
|
const scrollCol = (editing ? overlay.scrollCol : 0) ?? 0;
|
|
19
19
|
const lines = view.unitLines ?? [];
|
|
20
|
-
const
|
|
21
|
-
|
|
20
|
+
const digits = viewDigits(view);
|
|
21
|
+
let source = lines;
|
|
22
|
+
if (!editing) source = expandSoftRows(lines, width, false, true, digits);
|
|
23
|
+
const body = lazyRows(source.length, (index) => {
|
|
24
|
+
const line = source[index];
|
|
22
25
|
const changed = line.type === 'add' || line.type === 'del';
|
|
23
26
|
const outside = changed && !(item && sameHunk(line.item, item));
|
|
24
27
|
const row = editing || outside ? { ...line, mark: ' ' } : line;
|
|
25
|
-
return paintDiffLine(
|
|
28
|
+
return paintDiffLine(
|
|
29
|
+
row,
|
|
30
|
+
width,
|
|
31
|
+
color,
|
|
32
|
+
row.origin,
|
|
33
|
+
lang,
|
|
34
|
+
scrollCol,
|
|
35
|
+
digits,
|
|
36
|
+
);
|
|
26
37
|
});
|
|
27
|
-
const hits = codeHits(
|
|
38
|
+
const hits = codeHits(
|
|
39
|
+
source,
|
|
40
|
+
false,
|
|
41
|
+
width,
|
|
42
|
+
overlay,
|
|
43
|
+
editing,
|
|
44
|
+
scrollCol,
|
|
45
|
+
digits,
|
|
46
|
+
);
|
|
28
47
|
return paneResult({ body, ...hits });
|
|
29
48
|
};
|
|
30
49
|
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const {
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
const { traceLine, relativize } = commands;
|
|
3
|
+
const { stripAnsi } = require('../term/ansi.js');
|
|
4
|
+
const { traceLine, relativize } = require('../runs/output.js');
|
|
5
|
+
const { trimText } = require('../common/utilities.js');
|
|
8
6
|
|
|
9
7
|
const summary = () => ({
|
|
10
8
|
tests: null,
|
|
@@ -59,7 +57,7 @@ const userTrace = (text, root) => {
|
|
|
59
57
|
};
|
|
60
58
|
|
|
61
59
|
const normalizeMessage = (message) => {
|
|
62
|
-
const text =
|
|
60
|
+
const text = trimText(message).replace(/\s+/g, ' ');
|
|
63
61
|
return text.replace(/\s+\S+:\d+:\d+$/, '');
|
|
64
62
|
};
|
|
65
63
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const { stripAnsi } = ansi;
|
|
5
|
-
const model = require('./
|
|
6
|
-
const testParse = require('./
|
|
7
|
-
const toolParse = require('./
|
|
3
|
+
const { jsonParse } = require('metautil');
|
|
4
|
+
const { stripAnsi } = require('../term/ansi.js');
|
|
5
|
+
const model = require('./model.js');
|
|
6
|
+
const testParse = require('./test.js');
|
|
7
|
+
const toolParse = require('./tools.js');
|
|
8
8
|
|
|
9
9
|
const { problem, report, userTrace, groupReport, envelope } = model;
|
|
10
10
|
const { parseTap, parseNodeJsonl, parseTestJson, parseSpec } = testParse;
|
|
@@ -27,11 +27,7 @@ const toolHint = (program, args) => {
|
|
|
27
27
|
const parseJson = (text) => {
|
|
28
28
|
const trimmed = text.trim();
|
|
29
29
|
if (!trimmed || (trimmed[0] !== '{' && trimmed[0] !== '[')) return null;
|
|
30
|
-
|
|
31
|
-
return JSON.parse(trimmed);
|
|
32
|
-
} catch {
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
30
|
+
return jsonParse(trimmed);
|
|
35
31
|
};
|
|
36
32
|
|
|
37
33
|
const parseJsonReports = (text, root) => {
|
|
@@ -91,10 +87,9 @@ const mergeReports = (left, right) => {
|
|
|
91
87
|
const buildDocument = (stdout, stderr, root, exit, hint) => {
|
|
92
88
|
const out = stripAnsi(stdout);
|
|
93
89
|
const err = stripAnsi(stderr);
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
);
|
|
90
|
+
const fromOut = parseReports(out, root);
|
|
91
|
+
const fromErr = parseReports(err, root);
|
|
92
|
+
const reports = mergeReports(fromOut, fromErr);
|
|
98
93
|
const text = out.trim() ? out : err;
|
|
99
94
|
const grouped = withHint(reports, text, exit, hint).map(groupReport);
|
|
100
95
|
const rest = stderrRest(err, grouped);
|