reslop 0.2.7 → 0.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/CHANGELOG.md +17 -1
- package/README.md +16 -14
- package/bin/reslop.js +8 -5
- package/lib/agents/agents.js +504 -0
- package/lib/agents/allow.js +71 -0
- package/lib/agents/allow.json +16 -0
- package/lib/agents/models.js +460 -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} +123 -96
- package/lib/git/git.js +71 -0
- package/lib/git/worktree.js +475 -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 +111 -48
- package/lib/{editor.js → input/editor.js} +7 -8
- package/lib/{keys.js → input/keys.js} +15 -43
- package/lib/input/line-edit.js +77 -0
- package/lib/input/menu-pick.js +70 -0
- package/lib/render/agents.js +640 -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 +383 -0
- package/lib/render/frame.js +123 -25
- package/lib/render/header.js +176 -0
- package/lib/render/log.js +319 -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} +46 -14
- 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 +9 -0
- package/lib/review/format.js +426 -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 +958 -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 -39
- package/lib/session/change-actions.js +34 -100
- package/lib/session/commit.js +91 -52
- package/lib/session/compose.js +181 -145
- package/lib/session/dashboard.js +23 -22
- package/lib/session/dispatch.js +85 -21
- package/lib/session/files-pane.js +47 -26
- package/lib/session/find.js +16 -29
- package/lib/session/import.js +82 -0
- package/lib/session/items.js +8 -17
- package/lib/session/lifecycle.js +75 -72
- package/lib/session/load.js +2 -4
- package/lib/session/navigation.js +6 -3
- package/lib/session/npm/history.js +249 -0
- package/lib/session/npm/npm.js +815 -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} +156 -63
- package/lib/session/tasks.js +320 -65
- 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} +2 -2
- 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
package/lib/render/commits.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const ansi = require('../ansi.js');
|
|
4
|
-
const
|
|
5
|
-
const
|
|
3
|
+
const ansi = require('../term/ansi.js');
|
|
4
|
+
const { shortAge } = require('../common/format.js');
|
|
5
|
+
const { wrapMultiline, wrapDoc, cursorInWrap } = require('../term/wrap.js');
|
|
6
6
|
const primitives = require('./primitives.js');
|
|
7
|
+
const { trimText } = require('../common/utilities.js');
|
|
7
8
|
|
|
8
|
-
const { shortAge } = files;
|
|
9
|
-
const { wrapMultiline, wrapDoc, cursorInWrap } = wrap;
|
|
10
9
|
const { THEME, paint, visibleWidth, trimVisible, seq, EL } = ansi;
|
|
11
10
|
const { MARK_W, markPrefix, padVisible } = primitives;
|
|
12
11
|
const { editSpan, fieldWindow, paintBodyFill, listLine } = primitives;
|
|
@@ -55,10 +54,9 @@ const countLabel = (entry) => {
|
|
|
55
54
|
const unstagedDel = entry.unstagedRemoved ?? 0;
|
|
56
55
|
const any = stagedAdd || unstagedAdd || stagedDel || unstagedDel;
|
|
57
56
|
if (!any) return NO_COUNT;
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
};
|
|
57
|
+
const add = `+${stagedAdd}/${unstagedAdd}`;
|
|
58
|
+
const del = `-${stagedDel}/${unstagedDel}`;
|
|
59
|
+
return { add, del };
|
|
62
60
|
}
|
|
63
61
|
const added = entry.added ?? 0;
|
|
64
62
|
const removed = entry.removed ?? 0;
|
|
@@ -69,17 +67,14 @@ const countLabel = (entry) => {
|
|
|
69
67
|
const countWidths = (entries) =>
|
|
70
68
|
measureColumns(entries, countLabel, COUNT_ALIGN);
|
|
71
69
|
|
|
72
|
-
const refsText = (entry) =>
|
|
70
|
+
const refsText = (entry) => trimText(entry.refs);
|
|
73
71
|
|
|
74
72
|
const commitRowFields = (entry) => {
|
|
75
73
|
const { add, del } = countLabel(entry);
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
del,
|
|
81
|
-
date: shortAge(entry.date),
|
|
82
|
-
};
|
|
74
|
+
const sha = entry.shortSha ?? '';
|
|
75
|
+
const refs = trimVisible(refsText(entry), REFS_MAX);
|
|
76
|
+
const date = shortAge(entry.date);
|
|
77
|
+
return { sha, refs, add, del, date };
|
|
83
78
|
};
|
|
84
79
|
|
|
85
80
|
const contentWidth = (width) => Math.max(1, width - COMMIT_TAIL);
|
|
@@ -107,27 +102,21 @@ const viewedCommit = (entry, rev, revShort) => {
|
|
|
107
102
|
|
|
108
103
|
const commitTone = (selected, current) => {
|
|
109
104
|
if (current) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
nameFg: THEME.mutedFg,
|
|
115
|
-
};
|
|
105
|
+
const fgRgb = THEME.headerFg;
|
|
106
|
+
const bgRgb = THEME.currentBg;
|
|
107
|
+
const nameFg = THEME.mutedFg;
|
|
108
|
+
return { current, fgRgb, bgRgb, nameFg };
|
|
116
109
|
}
|
|
117
110
|
if (selected) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
nameFg: THEME.buttonHotFg,
|
|
123
|
-
};
|
|
111
|
+
const fgRgb = THEME.chromeFg;
|
|
112
|
+
const bgRgb = THEME.buttonBg;
|
|
113
|
+
const nameFg = THEME.buttonHotFg;
|
|
114
|
+
return { current, fgRgb, bgRgb, nameFg };
|
|
124
115
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
nameFg: THEME.chromeFg,
|
|
130
|
-
};
|
|
116
|
+
const fgRgb = THEME.mutedFg;
|
|
117
|
+
const bgRgb = THEME.ctxBg;
|
|
118
|
+
const nameFg = THEME.chromeFg;
|
|
119
|
+
return { current, fgRgb, bgRgb, nameFg };
|
|
131
120
|
};
|
|
132
121
|
|
|
133
122
|
const paintCommitRow = (entry, width, color, selected, cols, current) => {
|
|
@@ -159,13 +148,13 @@ const paintCommitEdit = (compose, width, color, entry, cols, index) => {
|
|
|
159
148
|
const shown = { ...entry, body: win.text, subject: win.text };
|
|
160
149
|
const textX = MARK_W + 1;
|
|
161
150
|
const edit = editSpan(1, textX, textX + rest, 0, text);
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
};
|
|
151
|
+
const row = paintCommitRow(shown, width, color, true, cols);
|
|
152
|
+
const x = textX + win.col;
|
|
153
|
+
const scroll = win.scroll;
|
|
154
|
+
const cursor = { x, scroll };
|
|
155
|
+
const at = entry ? 'replace' : 'start';
|
|
156
|
+
const edits = [{ ...edit, scroll }];
|
|
157
|
+
return { row, cursor, at, index, edits };
|
|
169
158
|
};
|
|
170
159
|
|
|
171
160
|
const editTarget = (compose, commits, cursor) => {
|
|
@@ -214,8 +203,11 @@ const paintPieces = (pieces, width, color, tone) => {
|
|
|
214
203
|
return out + paint(tail, tone.fgRgb, tone.bgRgb, color);
|
|
215
204
|
};
|
|
216
205
|
|
|
217
|
-
const messageText = (entry) =>
|
|
218
|
-
|
|
206
|
+
const messageText = (entry) => {
|
|
207
|
+
const body = `${entry.body ?? ''}`.trimEnd();
|
|
208
|
+
const subject = `${entry.subject ?? ''}`.trimEnd();
|
|
209
|
+
return body || subject;
|
|
210
|
+
};
|
|
219
211
|
|
|
220
212
|
const messageParts = (text, width) => {
|
|
221
213
|
if (!text) return [{ text: '', kind: 'text' }];
|
|
@@ -231,8 +223,8 @@ const messageParts = (text, width) => {
|
|
|
231
223
|
};
|
|
232
224
|
|
|
233
225
|
const authorParts = (entry) => {
|
|
234
|
-
const name =
|
|
235
|
-
const email =
|
|
226
|
+
const name = trimText(entry.author);
|
|
227
|
+
const email = trimText(entry.email);
|
|
236
228
|
if (name && email) {
|
|
237
229
|
return [
|
|
238
230
|
{ text: name, kind: 'author' },
|
|
@@ -248,7 +240,7 @@ const partsWidth = (parts) =>
|
|
|
248
240
|
parts.reduce((width, part) => width + visibleWidth(part.text), 0);
|
|
249
241
|
|
|
250
242
|
const timeFields = (entry) => ({
|
|
251
|
-
when:
|
|
243
|
+
when: trimText(entry.when),
|
|
252
244
|
ago: shortAge(entry.date),
|
|
253
245
|
});
|
|
254
246
|
|
|
@@ -363,21 +355,20 @@ const commitMessageWidth = (entry, screenWidth) => {
|
|
|
363
355
|
return Math.max(1, cols.leftW);
|
|
364
356
|
};
|
|
365
357
|
|
|
358
|
+
const PIECE_FG = {
|
|
359
|
+
add: () => THEME.addLineFg,
|
|
360
|
+
del: () => THEME.delLineFg,
|
|
361
|
+
hash: (tone) => (tone.current ? THEME.shaDarkFg : THEME.shaFg),
|
|
362
|
+
refs: (tone) => (tone.current ? THEME.shaDarkFg : THEME.warnFg),
|
|
363
|
+
author: (tone) => (tone.current ? tone.fgRgb : THEME.addLineFg),
|
|
364
|
+
email: (tone) => (tone.current ? tone.fgRgb : THEME.mutedFg),
|
|
365
|
+
text: (tone) => (tone.current ? THEME.mutedFg : tone.nameFg),
|
|
366
|
+
body: () => THEME.mutedFg,
|
|
367
|
+
};
|
|
368
|
+
|
|
366
369
|
const pieceFg = (kind, tone) => {
|
|
367
|
-
|
|
368
|
-
if (
|
|
369
|
-
if (tone.current) {
|
|
370
|
-
if (kind === 'hash') return THEME.shaDarkFg;
|
|
371
|
-
if (kind === 'refs') return THEME.shaDarkFg;
|
|
372
|
-
if (kind === 'text' || kind === 'body') return THEME.mutedFg;
|
|
373
|
-
return tone.fgRgb;
|
|
374
|
-
}
|
|
375
|
-
if (kind === 'hash') return THEME.shaFg;
|
|
376
|
-
if (kind === 'author') return THEME.addLineFg;
|
|
377
|
-
if (kind === 'email') return THEME.mutedFg;
|
|
378
|
-
if (kind === 'refs') return THEME.warnFg;
|
|
379
|
-
if (kind === 'text') return tone.nameFg;
|
|
380
|
-
if (kind === 'body') return THEME.mutedFg;
|
|
370
|
+
const pick = PIECE_FG[kind];
|
|
371
|
+
if (pick) return pick(tone);
|
|
381
372
|
return tone.fgRgb;
|
|
382
373
|
};
|
|
383
374
|
|
|
@@ -427,9 +418,8 @@ const commitLines = (entry, index, spec) => {
|
|
|
427
418
|
const atCaret = caret && caret.row === messageRow;
|
|
428
419
|
const cursor = atCaret ? { x: textX + caret.col } : null;
|
|
429
420
|
const piece = doc[messageRow];
|
|
430
|
-
const edits =
|
|
431
|
-
|
|
432
|
-
: [];
|
|
421
|
+
const edits = [];
|
|
422
|
+
if (piece) edits.push(editSpan(1, textX, x1, piece.start, piece.text));
|
|
433
423
|
lines.push(listLine(painted, index, cursor, edits));
|
|
434
424
|
}
|
|
435
425
|
return lines;
|
|
@@ -1,18 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const { seg, spinner } = tiles;
|
|
5
|
-
const table = require('
|
|
6
|
-
const {
|
|
7
|
-
const {
|
|
3
|
+
const { ago, duration } = require('../../common/format.js');
|
|
4
|
+
const { seg, spinner, blinkTone, RUN_ICON } = require('../tiles.js');
|
|
5
|
+
const table = require('../table.js');
|
|
6
|
+
const { isHot, waiting, notice } = table;
|
|
7
|
+
const { cell, cellSegs, flexCell, tableLines } = table;
|
|
8
|
+
const { titleAside, captionOver } = table;
|
|
8
9
|
|
|
9
10
|
const NAME_MAX = 18;
|
|
10
|
-
const RUN_ICON = {
|
|
11
|
-
passed: ['✔', 'add'],
|
|
12
|
-
failed: ['✖', 'error'],
|
|
13
|
-
aborted: ['⊘', 'muted'],
|
|
14
|
-
};
|
|
15
|
-
|
|
16
11
|
const blankCell = () => cell('', 'muted', 'r');
|
|
17
12
|
|
|
18
13
|
const ageCell = (at, now) => cell(at ? ago(at, now) : '', 'muted', 'r');
|
|
@@ -37,8 +32,9 @@ const commitsBlock = (model, width, height, ctx, tile) => {
|
|
|
37
32
|
const step = rebaseStep(data.rebase);
|
|
38
33
|
badge.push(seg(`⟳ rebase ${step}`, 'warn', true));
|
|
39
34
|
}
|
|
40
|
-
const
|
|
41
|
-
|
|
35
|
+
const count = [seg(`${total}`, 'key', true)];
|
|
36
|
+
const titleLine = titleAside(tile, count, width, badge);
|
|
37
|
+
if (!recent.length) return notice('no commits', titleLine);
|
|
42
38
|
const hot = isHot(data.changedAt, ctx.now);
|
|
43
39
|
const shown = recent.slice(0, Math.max(0, height));
|
|
44
40
|
const rows = shown.map((entry, i) => commitRow(entry, ctx, hot && i === 0));
|
|
@@ -59,8 +55,6 @@ const branchOrder = (list) =>
|
|
|
59
55
|
return right.at - left.at || left.name.localeCompare(right.name, 'en');
|
|
60
56
|
});
|
|
61
57
|
|
|
62
|
-
const blinkTone = (frame) => (Math.abs(frame) % 2 ? 'hot' : 'warn');
|
|
63
|
-
|
|
64
58
|
const branchRow = (entry, data, ctx) => {
|
|
65
59
|
const hot = isHot(data.hot.get(entry.name) ?? 0, ctx.now);
|
|
66
60
|
const tone = hot ? blinkTone(ctx.frame) : 'text';
|
|
@@ -100,11 +94,9 @@ const branchesBlock = (model, width, height, ctx, tile) => {
|
|
|
100
94
|
const data = model.branches;
|
|
101
95
|
if (!data.ready) return waiting('reading git…');
|
|
102
96
|
const badge = data.rebase ? [seg('⟳', 'warn', true)] : [];
|
|
103
|
-
const aside = [seg(`${data.list.length}`, '
|
|
97
|
+
const aside = [seg(`${data.list.length}`, 'key', true)];
|
|
104
98
|
const titleLine = titleAside(tile, aside, width, badge);
|
|
105
|
-
if (!data.list.length)
|
|
106
|
-
return { titleLine, lines: [[seg('no branches', 'muted')]] };
|
|
107
|
-
}
|
|
99
|
+
if (!data.list.length) return notice('no branches', titleLine);
|
|
108
100
|
const extras = branchExtras(data, ctx);
|
|
109
101
|
const room = Math.max(1, height - extras.length);
|
|
110
102
|
const shown = branchOrder(data.list).slice(0, room);
|
|
@@ -126,8 +118,7 @@ const countCell = (value, tone) => {
|
|
|
126
118
|
|
|
127
119
|
const failTone = (value) => (value ? 'error' : 'muted');
|
|
128
120
|
|
|
129
|
-
const testMetrics = (
|
|
130
|
-
countCell(done, 'text'),
|
|
121
|
+
const testMetrics = (ok, fail, total) => [
|
|
131
122
|
countCell(ok, ok ? 'add' : 'muted'),
|
|
132
123
|
countCell(fail, failTone(fail)),
|
|
133
124
|
countCell(total, 'text'),
|
|
@@ -138,12 +129,13 @@ const runMetrics = (run) => {
|
|
|
138
129
|
if (result && typeof result.tests === 'number') {
|
|
139
130
|
const fail = result.failed ?? 0;
|
|
140
131
|
const ok = result.passed ?? Math.max(0, result.tests - fail);
|
|
141
|
-
return testMetrics(
|
|
132
|
+
return testMetrics(ok, fail, result.tests);
|
|
142
133
|
}
|
|
143
|
-
const
|
|
144
|
-
|
|
134
|
+
const counted = run.done > 0 || run.failed > 0 || run.expected > 0;
|
|
135
|
+
const live = run.status === 'running' && (run.source !== 'reslop' || counted);
|
|
136
|
+
if (!live) return [blankCell(), blankCell(), blankCell()];
|
|
145
137
|
const total = run.expected > 0 ? run.expected : null;
|
|
146
|
-
return testMetrics(run.done
|
|
138
|
+
return testMetrics(run.done, run.failed, total);
|
|
147
139
|
};
|
|
148
140
|
|
|
149
141
|
const lintNote = (run) => {
|
|
@@ -157,7 +149,7 @@ const lintNote = (run) => {
|
|
|
157
149
|
return note;
|
|
158
150
|
};
|
|
159
151
|
|
|
160
|
-
const
|
|
152
|
+
const spentCell = (run, ctx) => {
|
|
161
153
|
const running = run.status === 'running';
|
|
162
154
|
const end = running ? ctx.now : run.endedAt;
|
|
163
155
|
if (!run.startedAt || !end) return blankCell();
|
|
@@ -168,16 +160,15 @@ const named = (icon, tone, name, nameTone) => ({
|
|
|
168
160
|
segs: [seg(icon, tone, true), seg(' '), seg(name, nameTone)],
|
|
169
161
|
align: 'l',
|
|
170
162
|
flex: true,
|
|
171
|
-
min:
|
|
163
|
+
min: 6,
|
|
172
164
|
});
|
|
173
165
|
|
|
174
166
|
const runHeader = () => [
|
|
175
167
|
cell(''),
|
|
176
|
-
cell('
|
|
177
|
-
cell('
|
|
178
|
-
cell('
|
|
179
|
-
cell('
|
|
180
|
-
cell('duration', 'muted', 'r'),
|
|
168
|
+
cell('ok', 'caption', 'r'),
|
|
169
|
+
cell('fail', 'caption', 'r'),
|
|
170
|
+
cell('total', 'caption', 'r'),
|
|
171
|
+
cell('spent', 'caption', 'r'),
|
|
181
172
|
];
|
|
182
173
|
|
|
183
174
|
const runRow = (run, ctx) => {
|
|
@@ -185,7 +176,7 @@ const runRow = (run, ctx) => {
|
|
|
185
176
|
const tone = run.status === 'running' ? 'text' : 'muted';
|
|
186
177
|
const label = named(icon[0], icon[1], run.name, tone);
|
|
187
178
|
label.segs.push(...lintNote(run));
|
|
188
|
-
return [label, ...runMetrics(run),
|
|
179
|
+
return [label, ...runMetrics(run), spentCell(run, ctx)];
|
|
189
180
|
};
|
|
190
181
|
|
|
191
182
|
const runsBlock = (model, width, height, ctx, tile) => {
|
|
@@ -194,13 +185,7 @@ const runsBlock = (model, width, height, ctx, tile) => {
|
|
|
194
185
|
rows.push([named(spinner(ctx.frame), 'warn', model.busy, 'warn')]);
|
|
195
186
|
}
|
|
196
187
|
for (const run of model.runs) rows.push(runRow(run, ctx));
|
|
197
|
-
if (!rows.length)
|
|
198
|
-
const items = [
|
|
199
|
-
stat('status', 'idle', 'muted'),
|
|
200
|
-
stat('usage', 'reslop t -- <command>', 'muted'),
|
|
201
|
-
];
|
|
202
|
-
return { badge: [], lines: tableLines(pairRows(items, 1), width) };
|
|
203
|
-
}
|
|
188
|
+
if (!rows.length) return notice(['idle', 'reslop t -- <command>']);
|
|
204
189
|
const shown = rows.slice(0, Math.max(1, height));
|
|
205
190
|
const lines = tableLines([runHeader(), ...shown], width);
|
|
206
191
|
return {
|