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
package/lib/render/npm.js
CHANGED
|
@@ -1,46 +1,22 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const ansi = require('../ansi.js');
|
|
4
|
-
const
|
|
5
|
-
const wrap = require('../wrap.js');
|
|
6
|
-
const chrome = require('./chrome.js');
|
|
3
|
+
const ansi = require('../term/ansi.js');
|
|
4
|
+
const { spinner } = require('./tiles.js');
|
|
7
5
|
const primitives = require('./primitives.js');
|
|
8
|
-
|
|
9
|
-
const {
|
|
10
|
-
const {
|
|
11
|
-
const {
|
|
12
|
-
const { TABLE_KEY, TABLE_VAL } = npmCommands;
|
|
13
|
-
const { wrapPlain } = wrap;
|
|
14
|
-
const { formatBusyStatus } = chrome;
|
|
6
|
+
const { scrollMark } = primitives;
|
|
7
|
+
const { placeHits } = primitives;
|
|
8
|
+
const { THEME, paint, visibleWidth } = ansi;
|
|
9
|
+
const { trimVisible, seq, EL } = ansi;
|
|
15
10
|
const { fill, MARK_W, markPrefix, editSpan } = primitives;
|
|
16
11
|
const { paneResult, paintCursorList, fieldWindow } = primitives;
|
|
12
|
+
const log = require('./log.js');
|
|
13
|
+
const { mixRgb, withLogScroller, paintNpmLog } = log;
|
|
17
14
|
|
|
18
15
|
const EDGE = 2;
|
|
19
|
-
const TAIL = 1;
|
|
20
|
-
const LOG_PAD_Y = 1;
|
|
21
|
-
const LOG_PAD_X = 2;
|
|
22
|
-
const NPM_NAME_MAX = 24;
|
|
23
|
-
|
|
24
|
-
const TABLE_INK = {
|
|
25
|
-
actual: THEME.errorFg,
|
|
26
|
-
expected: THEME.addLineFg,
|
|
27
|
-
code: THEME.shaFg,
|
|
28
|
-
type: CODE_FG.className,
|
|
29
|
-
count: THEME.warnFg,
|
|
30
|
-
omitted: THEME.warnFg,
|
|
31
|
-
};
|
|
32
16
|
|
|
33
|
-
const
|
|
34
|
-
failed: THEME.errorFg,
|
|
35
|
-
errors: THEME.errorFg,
|
|
36
|
-
passed: THEME.addLineFg,
|
|
37
|
-
};
|
|
17
|
+
const TAIL = 1;
|
|
38
18
|
|
|
39
|
-
const
|
|
40
|
-
const height = Math.max(1, bodyH);
|
|
41
|
-
if (height >= LOG_PAD_Y * 2 + 1) return height - LOG_PAD_Y * 2;
|
|
42
|
-
return height;
|
|
43
|
-
};
|
|
19
|
+
const NPM_NAME_MAX = 24;
|
|
44
20
|
|
|
45
21
|
const npmNameWidth = (commands, typed = '') => {
|
|
46
22
|
let width = visibleWidth(typed);
|
|
@@ -50,11 +26,15 @@ const npmNameWidth = (commands, typed = '') => {
|
|
|
50
26
|
return Math.min(NPM_NAME_MAX, width);
|
|
51
27
|
};
|
|
52
28
|
|
|
29
|
+
const COMMAND_MIN = 8;
|
|
30
|
+
|
|
53
31
|
const npmColumns = (width, nameCol) => {
|
|
54
32
|
const rest = Math.max(1, width - EDGE - TAIL - MARK_W);
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
-
|
|
33
|
+
const gap = rest > 3 ? ' ' : '';
|
|
34
|
+
const nameRoom = Math.max(1, rest - gap.length - COMMAND_MIN);
|
|
35
|
+
const nameW = Math.min(nameCol, nameRoom);
|
|
36
|
+
const detailW = Math.max(0, rest - nameW - gap.length);
|
|
37
|
+
return { rest, nameW, gap, detailW };
|
|
58
38
|
};
|
|
59
39
|
|
|
60
40
|
const paintNpmLine = (cols, name, detail, color, selected, bin) => {
|
|
@@ -65,8 +45,8 @@ const paintNpmLine = (cols, name, detail, color, selected, bin) => {
|
|
|
65
45
|
const pad = ' '.repeat(Math.max(0, cols.rest - visibleWidth(mid + after)));
|
|
66
46
|
const tail = ' '.repeat(TAIL);
|
|
67
47
|
const fgRgb = selected ? THEME.chromeFg : THEME.mutedFg;
|
|
68
|
-
const bgRgb = selected ? THEME.
|
|
69
|
-
const edge = fill(EDGE, fgRgb,
|
|
48
|
+
const bgRgb = selected ? THEME.checkBg : THEME.buttonBg;
|
|
49
|
+
const edge = fill(EDGE, fgRgb, bgRgb, color);
|
|
70
50
|
if (!color) return `${prefix}${mid}${after}${pad}${tail}${edge}`;
|
|
71
51
|
const nameFg = bin ? THEME.shaFg : THEME.buttonHotFg;
|
|
72
52
|
let out = `${seq(fgRgb, bgRgb)}${EL}`;
|
|
@@ -88,9 +68,9 @@ const editingName = (view) => view.npmEditField !== 'command';
|
|
|
88
68
|
|
|
89
69
|
const editWindow = (compose, live, draft, width) => {
|
|
90
70
|
const value = `${(live ? compose.text : draft) ?? ''}`.replaceAll('\n', ' ');
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
71
|
+
const cursor = live ? compose.cursor : 0;
|
|
72
|
+
const scrollCol = live ? compose.scrollCol : 0;
|
|
73
|
+
const win = fieldWindow(value, cursor, scrollCol, width);
|
|
94
74
|
return { ...win, value };
|
|
95
75
|
};
|
|
96
76
|
|
|
@@ -126,6 +106,9 @@ const paintNpmEdit = (view, width, color, nameCol) => {
|
|
|
126
106
|
return { row, cursor, edits };
|
|
127
107
|
};
|
|
128
108
|
|
|
109
|
+
const leftFill = (width, color) =>
|
|
110
|
+
fill(width, THEME.chromeFg, THEME.buttonBg, color);
|
|
111
|
+
|
|
129
112
|
const paintNpmList = (view, width, color, bodyH, headerLines) => {
|
|
130
113
|
const commands = view.npmCommands ?? [];
|
|
131
114
|
const { compose } = view;
|
|
@@ -133,9 +116,17 @@ const paintNpmList = (view, width, color, bodyH, headerLines) => {
|
|
|
133
116
|
const typed = editingName(view) ? compose?.text : view.npmDraftName;
|
|
134
117
|
const nameW = npmNameWidth(commands, editing ? `${typed ?? ''}` : '');
|
|
135
118
|
const cursor = view.npmCursor ?? 0;
|
|
136
|
-
const pane = {
|
|
119
|
+
const pane = {
|
|
120
|
+
width,
|
|
121
|
+
color,
|
|
122
|
+
bodyH,
|
|
123
|
+
headerLines,
|
|
124
|
+
offset: view.listScroll,
|
|
125
|
+
blank: leftFill(width, color),
|
|
126
|
+
};
|
|
127
|
+
const onCommands = view.npmFocus !== 'runs';
|
|
137
128
|
const paintRow = (entry, selected) =>
|
|
138
|
-
paintNpmRow(entry, width, color, selected, nameW);
|
|
129
|
+
paintNpmRow(entry, width, color, onCommands && selected, nameW);
|
|
139
130
|
let extra = null;
|
|
140
131
|
if (editing) {
|
|
141
132
|
const painted = paintNpmEdit(view, width, color, nameW);
|
|
@@ -145,194 +136,329 @@ const paintNpmList = (view, width, color, bodyH, headerLines) => {
|
|
|
145
136
|
return paintCursorList(commands, cursor, pane, paintRow, extra);
|
|
146
137
|
};
|
|
147
138
|
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
139
|
+
const HISTORY_SHARE = 0.7;
|
|
140
|
+
|
|
141
|
+
const sessionSplit = (width) => {
|
|
142
|
+
const rightW = Math.max(1, Math.floor(width * HISTORY_SHARE));
|
|
143
|
+
const leftW = Math.max(0, width - rightW);
|
|
144
|
+
return { leftW, rightW };
|
|
152
145
|
};
|
|
153
146
|
|
|
154
|
-
const
|
|
147
|
+
const rightFill = (width, color) =>
|
|
148
|
+
fill(width, THEME.chromeFg, THEME.ctxBg, color);
|
|
149
|
+
|
|
150
|
+
const HISTORY_HEADER = [
|
|
151
|
+
'command',
|
|
152
|
+
'done',
|
|
153
|
+
'ok',
|
|
154
|
+
'fail',
|
|
155
|
+
'total',
|
|
156
|
+
'duration',
|
|
157
|
+
'time',
|
|
158
|
+
];
|
|
159
|
+
|
|
160
|
+
const HISTORY_ALIGN = ['l', 'r', 'r', 'r', 'r', 'r', 'r'];
|
|
155
161
|
|
|
156
|
-
const
|
|
157
|
-
from.map((value, i) => Math.round(value + (to[i] - value) * part));
|
|
162
|
+
const HISTORY_CAP = [0, 6, 6, 6, 8, 8, 14];
|
|
158
163
|
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
164
|
+
const HISTORY_FLEX = 0;
|
|
165
|
+
|
|
166
|
+
const HISTORY_PREFIX = ' ';
|
|
167
|
+
|
|
168
|
+
const HISTORY_TAIL = ' ';
|
|
169
|
+
|
|
170
|
+
const SELECT_LIFT = 0.45;
|
|
171
|
+
|
|
172
|
+
const WHITE = [0xff, 0xff, 0xff];
|
|
173
|
+
|
|
174
|
+
const HISTORY_TONE = {
|
|
175
|
+
add: 'addLineFg',
|
|
176
|
+
error: 'errorFg',
|
|
177
|
+
warn: 'warnFg',
|
|
178
|
+
text: 'chromeFg',
|
|
179
|
+
caption: 'dashCaptionFg',
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
const historyTone = (name) => THEME[HISTORY_TONE[name] ?? 'mutedFg'];
|
|
183
|
+
|
|
184
|
+
const toneRgb = (name, selected) => {
|
|
185
|
+
const base = historyTone(name);
|
|
186
|
+
if (!selected || name === 'caption') return base;
|
|
187
|
+
return mixRgb(base, WHITE, SELECT_LIFT);
|
|
165
188
|
};
|
|
166
189
|
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
190
|
+
const HISTORY_ICON = {
|
|
191
|
+
pass: { text: '✔', tone: 'add' },
|
|
192
|
+
stop: { text: '⊘', tone: 'muted' },
|
|
193
|
+
fail: { text: '✖', tone: 'error' },
|
|
171
194
|
};
|
|
172
195
|
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
196
|
+
const UNKNOWN_ICON = { text: '?', tone: 'muted' };
|
|
197
|
+
|
|
198
|
+
const historyIcon = (row, frame) => {
|
|
199
|
+
if (row.live || row.mark === 'run') {
|
|
200
|
+
const text = spinner(frame);
|
|
201
|
+
const tone = 'warn';
|
|
202
|
+
return { text, tone };
|
|
177
203
|
}
|
|
178
|
-
return
|
|
204
|
+
return HISTORY_ICON[row.mark] ?? UNKNOWN_ICON;
|
|
179
205
|
};
|
|
180
206
|
|
|
181
|
-
const
|
|
182
|
-
const
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
const gap = rest.startsWith(' ') ? ' ' : '';
|
|
187
|
-
const value = rest.slice(gap.length);
|
|
188
|
-
const edge = Math.min(1, Math.floor(width / 2));
|
|
189
|
-
const inner = Math.max(0, width - edge * 2);
|
|
190
|
-
const keyW = Math.min(visibleWidth(key), inner);
|
|
191
|
-
const gapW = Math.min(visibleWidth(gap), Math.max(0, inner - keyW));
|
|
192
|
-
const valueW = Math.max(0, inner - keyW - gapW);
|
|
193
|
-
return { key, gap, value, edge, keyW, gapW, valueW };
|
|
207
|
+
const commandLabel = (row, frame) => {
|
|
208
|
+
const icon = historyIcon(row, frame).text;
|
|
209
|
+
const name = `${row.name ?? ''}`;
|
|
210
|
+
if (!name) return icon;
|
|
211
|
+
return `${icon} ${name}`;
|
|
194
212
|
};
|
|
195
213
|
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
214
|
+
const historyCells = (row, frame) => [
|
|
215
|
+
commandLabel(row, frame),
|
|
216
|
+
`${row.done ?? ''}`,
|
|
217
|
+
`${row.ok ?? ''}`,
|
|
218
|
+
`${row.fail ?? ''}`,
|
|
219
|
+
`${row.total ?? ''}`,
|
|
220
|
+
`${row.elapsed ?? ''}`,
|
|
221
|
+
`${row.when ?? ''}`,
|
|
222
|
+
];
|
|
223
|
+
|
|
224
|
+
const columnWants = (rows, frame) => {
|
|
225
|
+
const want = HISTORY_HEADER.map((label) => visibleWidth(label));
|
|
226
|
+
for (const row of rows) {
|
|
227
|
+
if (row.empty) continue;
|
|
228
|
+
const cells = historyCells(row, frame);
|
|
229
|
+
for (let i = 0; i < cells.length; i++) {
|
|
230
|
+
const seen = visibleWidth(cells[i]);
|
|
231
|
+
const cap = HISTORY_CAP[i];
|
|
232
|
+
const width = i === HISTORY_FLEX || !cap ? seen : Math.min(cap, seen);
|
|
233
|
+
want[i] = Math.max(want[i], width);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return want;
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
const fitColumns = (want, budget) => {
|
|
240
|
+
const gaps = Math.max(0, want.length - 1);
|
|
241
|
+
let fixed = 0;
|
|
242
|
+
for (let i = 0; i < want.length; i++) {
|
|
243
|
+
if (i !== HISTORY_FLEX) fixed += want[i];
|
|
244
|
+
}
|
|
245
|
+
const room = budget - gaps - fixed;
|
|
246
|
+
if (room >= 1) {
|
|
247
|
+
const widths = want.slice();
|
|
248
|
+
widths[HISTORY_FLEX] = room;
|
|
249
|
+
return widths;
|
|
250
|
+
}
|
|
251
|
+
const widths = want.slice();
|
|
252
|
+
widths[HISTORY_FLEX] = 1;
|
|
253
|
+
let extra = 1 + fixed + gaps - budget;
|
|
254
|
+
for (let index = widths.length - 1; index >= 0 && extra > 0; index--) {
|
|
255
|
+
if (index === HISTORY_FLEX) continue;
|
|
256
|
+
const drop = Math.min(extra, widths[index]);
|
|
257
|
+
widths[index] -= drop;
|
|
258
|
+
extra -= drop;
|
|
259
|
+
}
|
|
260
|
+
return widths;
|
|
209
261
|
};
|
|
210
262
|
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
263
|
+
const historyWidths = (rows, budget, frame) =>
|
|
264
|
+
fitColumns(columnWants(rows, frame), budget);
|
|
265
|
+
|
|
266
|
+
const alignCell = (text, width, align) => {
|
|
267
|
+
const shown = trimVisible(`${text ?? ''}`, width);
|
|
268
|
+
const pad = ' '.repeat(Math.max(0, width - visibleWidth(shown)));
|
|
269
|
+
return align === 'r' ? `${pad}${shown}` : `${shown}${pad}`;
|
|
217
270
|
};
|
|
218
271
|
|
|
219
|
-
const
|
|
220
|
-
|
|
221
|
-
if (
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
});
|
|
272
|
+
const cellTone = (row, index, statusTone) => {
|
|
273
|
+
if (index === 1) return 'text';
|
|
274
|
+
if (index === 2) return row.okN ? 'add' : 'muted';
|
|
275
|
+
if (index === 3) return row.failN ? 'error' : 'muted';
|
|
276
|
+
if (index === 4) return row.exitLabel ? statusTone : 'text';
|
|
277
|
+
if (index === 5 && row.live) return 'warn';
|
|
278
|
+
return 'muted';
|
|
227
279
|
};
|
|
228
280
|
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
const namePad = ' '.repeat(Math.max(0, part.keyW - visibleWidth(name)));
|
|
233
|
-
const shown = trimVisible(part.value, part.valueW);
|
|
234
|
-
const pad = ' '.repeat(Math.max(0, part.valueW - visibleWidth(shown)));
|
|
235
|
-
const edge = ' '.repeat(part.edge);
|
|
236
|
-
const gap = part.gap.slice(0, part.gapW);
|
|
237
|
-
return `${edge}${name}${namePad}${gap}${shown}${pad}${edge}`;
|
|
281
|
+
const paintPiece = (text, tone, bg, color, selected) => {
|
|
282
|
+
if (!color || text === '') return text;
|
|
283
|
+
return paint(text, toneRgb(tone, selected), bg, true);
|
|
238
284
|
};
|
|
239
285
|
|
|
240
|
-
const
|
|
241
|
-
const
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
const
|
|
245
|
-
const
|
|
246
|
-
const
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
return out + fill(part.edge, ink, tone.frame, true);
|
|
286
|
+
const paintCommand = (row, frame, width, bg, color, selected) => {
|
|
287
|
+
const icon = historyIcon(row, frame);
|
|
288
|
+
if (width <= 0) return '';
|
|
289
|
+
if (width === 1) return paintPiece(icon.text, icon.tone, bg, color, selected);
|
|
290
|
+
const lead = `${icon.text} `;
|
|
291
|
+
const nameW = Math.max(0, width - visibleWidth(lead));
|
|
292
|
+
const name = trimVisible(`${row.name ?? ''}`, nameW);
|
|
293
|
+
const pad = ' '.repeat(Math.max(0, nameW - visibleWidth(name)));
|
|
294
|
+
const nameTone = selected ? icon.tone : 'text';
|
|
295
|
+
const mark = paintPiece(lead, icon.tone, bg, color, selected);
|
|
296
|
+
const label = paintPiece(`${name}${pad}`, nameTone, bg, color, selected);
|
|
297
|
+
return `${mark}${label}`;
|
|
253
298
|
};
|
|
254
299
|
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
300
|
+
const historyParts = (cells, widths, tones, bg, color, selected, command) => {
|
|
301
|
+
const parts = [];
|
|
302
|
+
for (let i = 0; i < cells.length; i++) {
|
|
303
|
+
if (!widths[i]) continue;
|
|
304
|
+
if (i === 0 && command) {
|
|
305
|
+
parts.push(command);
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
const shown = alignCell(cells[i], widths[i], HISTORY_ALIGN[i]);
|
|
309
|
+
parts.push(paintPiece(shown, tones[i], bg, color, selected));
|
|
261
310
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
}
|
|
265
|
-
if (/^(Stack|Related failures|Stderr)$/.test(line)) {
|
|
266
|
-
return paint(line, THEME.chromeFg, THEME.ctxBg, true, true);
|
|
267
|
-
}
|
|
268
|
-
if (!/^\s+(at|↳)\s/.test(line)) return line;
|
|
269
|
-
const source = line.replace(
|
|
270
|
-
/([^\s()|]+)(:\d+:\d+)(?=[\s)|]|$)/g,
|
|
271
|
-
(match, file, position) => {
|
|
272
|
-
const path = `${fg(THEME.shaFg)}${file}`;
|
|
273
|
-
const point = `${fg(THEME.mutedFg)}${position}`;
|
|
274
|
-
return `${path}${point}${fg(THEME.ctxFg)}`;
|
|
275
|
-
},
|
|
276
|
-
);
|
|
277
|
-
const frame = /^(\s+at\s+)(.*?)(\s+\(.+\))$/.exec(source);
|
|
278
|
-
if (!frame) return source;
|
|
279
|
-
return (
|
|
280
|
-
`${fg(THEME.mutedFg)}${frame[1]}${fg(CODE_FG.function)}${frame[2]}` +
|
|
281
|
-
`${fg(THEME.ctxFg)}${frame[3]}`
|
|
282
|
-
);
|
|
311
|
+
const gap = paintPiece(' ', 'muted', bg, color, selected);
|
|
312
|
+
return parts.join(gap);
|
|
283
313
|
};
|
|
284
314
|
|
|
285
|
-
const
|
|
286
|
-
const
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
const
|
|
291
|
-
return
|
|
315
|
+
const historyLine = (row, widths, color, selected, frame) => {
|
|
316
|
+
const gaps = Math.max(0, widths.filter((n) => n > 0).length - 1);
|
|
317
|
+
const budget = widths.reduce((sum, n) => sum + n, 0) + gaps;
|
|
318
|
+
const bg = selected ? THEME.checkBg : THEME.ctxBg;
|
|
319
|
+
if (row.empty) {
|
|
320
|
+
const none = trimVisible('none', budget);
|
|
321
|
+
return paintPiece(none, 'muted', bg, color, selected);
|
|
292
322
|
}
|
|
293
|
-
const
|
|
294
|
-
const
|
|
295
|
-
const
|
|
296
|
-
const
|
|
297
|
-
|
|
298
|
-
if (pad) out += `${RESET}${base}${' '.repeat(pad)}`;
|
|
299
|
-
return `${out}${RESET}`;
|
|
323
|
+
const status = historyIcon(row, frame).tone;
|
|
324
|
+
const cells = historyCells(row, frame);
|
|
325
|
+
const tones = cells.map((_, index) => cellTone(row, index, status));
|
|
326
|
+
const command = paintCommand(row, frame, widths[0] ?? 0, bg, color, selected);
|
|
327
|
+
return historyParts(cells, widths, tones, bg, color, selected, command);
|
|
300
328
|
};
|
|
301
329
|
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
330
|
+
const paintHistoryLine = (mid, width, color, bg) => {
|
|
331
|
+
const prefix = HISTORY_PREFIX;
|
|
332
|
+
const tail = HISTORY_TAIL;
|
|
333
|
+
const budget = Math.max(0, width - prefix.length - tail.length);
|
|
334
|
+
const pad = ' '.repeat(Math.max(0, budget - visibleWidth(mid)));
|
|
335
|
+
if (!color) return `${prefix}${mid}${pad}${tail}`;
|
|
336
|
+
const edge = paintPiece(prefix, 'muted', bg, true, false);
|
|
337
|
+
const rest = paintPiece(`${pad}${tail}`, 'muted', bg, true, false);
|
|
338
|
+
return `${edge}${mid}${rest}`;
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
const paintSessionRow = (row, width, color, selected, widths, frame) => {
|
|
342
|
+
const bg = selected ? THEME.checkBg : THEME.ctxBg;
|
|
343
|
+
const mid = historyLine(row, widths, color, selected, frame);
|
|
344
|
+
const line = paintHistoryLine(mid, width, color, bg);
|
|
345
|
+
return { row: line, hit: !row.empty };
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
const paintColumnHeader = (widths, width, color) => {
|
|
349
|
+
const bg = THEME.ctxBg;
|
|
350
|
+
const tones = HISTORY_HEADER.map(() => 'caption');
|
|
351
|
+
const mid = historyParts(HISTORY_HEADER, widths, tones, bg, color, false);
|
|
352
|
+
return paintHistoryLine(mid, width, color, bg);
|
|
314
353
|
};
|
|
315
354
|
|
|
316
|
-
const
|
|
317
|
-
const
|
|
318
|
-
const
|
|
319
|
-
const
|
|
320
|
-
const
|
|
321
|
-
const top = padY ? 1 : 0;
|
|
322
|
-
const start = logStart(view, count, rows);
|
|
323
|
-
const blank = fill(width, THEME.ctxFg, THEME.ctxBg, color);
|
|
355
|
+
const joinNpm = (left, right, width, color, bodyH) => {
|
|
356
|
+
const { leftW, rightW } = sessionSplit(width);
|
|
357
|
+
const blankL = leftFill(leftW, color);
|
|
358
|
+
const blankR = rightFill(rightW, color);
|
|
359
|
+
const count = Math.max(left.body.length, right.body.length, bodyH);
|
|
324
360
|
const body = [];
|
|
325
|
-
for (let i = 0; i <
|
|
326
|
-
|
|
327
|
-
|
|
361
|
+
for (let i = 0; i < count; i++) {
|
|
362
|
+
const sideL = left.body[i] ?? blankL;
|
|
363
|
+
const sideR = right.body[i] ?? blankR;
|
|
364
|
+
body.push(`${sideL}${sideR}`);
|
|
328
365
|
}
|
|
329
|
-
|
|
330
|
-
|
|
366
|
+
const fileHits = [
|
|
367
|
+
...placeHits(left.fileHits, 0, leftW, 'commands'),
|
|
368
|
+
...placeHits(right.fileHits, leftW, rightW, 'runs'),
|
|
369
|
+
];
|
|
370
|
+
const { editHits, cursor, listScroll } = left;
|
|
371
|
+
return paneResult({ body, fileHits, editHits, cursor, listScroll });
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
const historyHead = (header, width, color, bodyH) => {
|
|
375
|
+
const blank = rightFill(width, color);
|
|
376
|
+
const lines = [blank, header || blank, blank];
|
|
377
|
+
return lines.slice(0, bodyH);
|
|
378
|
+
};
|
|
379
|
+
|
|
380
|
+
const historyBar = (lines, count, start, width, fullWidth, color, head) => {
|
|
381
|
+
const rows = lines.length;
|
|
382
|
+
const barred = lines.map((line, index) => {
|
|
383
|
+
const mark = scrollMark(index, count, rows, start);
|
|
384
|
+
return withLogScroller(line, mark, width, color);
|
|
385
|
+
});
|
|
386
|
+
const scrollBar = {
|
|
387
|
+
col: fullWidth,
|
|
388
|
+
row: head,
|
|
389
|
+
height: rows,
|
|
390
|
+
track: 0,
|
|
391
|
+
rows,
|
|
392
|
+
count,
|
|
393
|
+
start,
|
|
394
|
+
};
|
|
395
|
+
return { body: barred, scrollBar };
|
|
396
|
+
};
|
|
397
|
+
|
|
398
|
+
const paintNpmSessions = (view, width, color, bodyH, headLines, full) => {
|
|
399
|
+
const runs = view.npmRuns ?? [];
|
|
400
|
+
const frame = view.progressFrame ?? 0;
|
|
401
|
+
const listRoom = Math.max(0, bodyH - 3);
|
|
402
|
+
const overflow = runs.length > listRoom && listRoom > 0;
|
|
403
|
+
const inner = overflow ? Math.max(1, width - 1) : width;
|
|
404
|
+
const edge = HISTORY_PREFIX.length + HISTORY_TAIL.length;
|
|
405
|
+
const budget = Math.max(0, inner - edge);
|
|
406
|
+
const widths = historyWidths(runs, budget, frame);
|
|
407
|
+
const header = paintColumnHeader(widths, inner, color);
|
|
408
|
+
const pad = rightFill(width - inner, color);
|
|
409
|
+
const padded = overflow ? `${header}${pad}` : header;
|
|
410
|
+
const head = historyHead(padded, width, color, bodyH);
|
|
411
|
+
const listH = Math.max(0, bodyH - head.length);
|
|
412
|
+
const rows = runs.length ? runs : [{ empty: true }];
|
|
413
|
+
const cursor = view.npmRunCursor ?? 0;
|
|
414
|
+
const onRuns = view.npmFocus === 'runs';
|
|
415
|
+
const paintRun = (entry, selected) =>
|
|
416
|
+
paintSessionRow(entry, inner, color, onRuns && selected, widths, frame);
|
|
417
|
+
const painted = paintCursorList(
|
|
418
|
+
rows,
|
|
419
|
+
cursor,
|
|
420
|
+
{
|
|
421
|
+
width: inner,
|
|
422
|
+
color,
|
|
423
|
+
bodyH: listH,
|
|
424
|
+
headerLines: headLines + head.length,
|
|
425
|
+
offset: view.npmRunScroll ?? 0,
|
|
426
|
+
blank: rightFill(inner, color),
|
|
427
|
+
pad: 0,
|
|
428
|
+
},
|
|
429
|
+
paintRun,
|
|
430
|
+
);
|
|
431
|
+
const list = painted.body.slice();
|
|
432
|
+
while (list.length < listH) list.push(rightFill(inner, color));
|
|
433
|
+
let scrolled = { body: list, scrollBar: null };
|
|
434
|
+
if (overflow) {
|
|
435
|
+
const at = painted.listScroll;
|
|
436
|
+
const rows = runs.length;
|
|
437
|
+
const lead = head.length;
|
|
438
|
+
scrolled = historyBar(list, rows, at, width, full, color, lead);
|
|
439
|
+
}
|
|
440
|
+
const body = [...head, ...scrolled.body].slice(0, bodyH);
|
|
441
|
+
const { fileHits, listScroll } = painted;
|
|
442
|
+
const { scrollBar } = scrolled;
|
|
443
|
+
return { body, fileHits, listScroll, scrollBar };
|
|
331
444
|
};
|
|
332
445
|
|
|
333
446
|
const paintBodyNpm = (view, width, color, bodyH, headerLines) => {
|
|
334
447
|
if (view.npmView) return paintNpmLog(view, width, color, bodyH);
|
|
335
|
-
|
|
448
|
+
const { leftW, rightW } = sessionSplit(width);
|
|
449
|
+
const left = paintNpmList(view, leftW, color, bodyH, headerLines);
|
|
450
|
+
const right = paintNpmSessions(
|
|
451
|
+
view,
|
|
452
|
+
rightW,
|
|
453
|
+
color,
|
|
454
|
+
bodyH,
|
|
455
|
+
headerLines,
|
|
456
|
+
width,
|
|
457
|
+
);
|
|
458
|
+
const joined = joinNpm(left, right, width, color, bodyH);
|
|
459
|
+
joined.runScroll = right.listScroll;
|
|
460
|
+
if (right.scrollBar) joined.scrollBar = right.scrollBar;
|
|
461
|
+
return joined;
|
|
336
462
|
};
|
|
337
463
|
|
|
338
|
-
module.exports = { paintBodyNpm
|
|
464
|
+
module.exports = { paintBodyNpm };
|
package/lib/render/packages.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const {
|
|
5
|
-
const
|
|
6
|
-
const { paintSegments } = tiles;
|
|
7
|
-
const blocks = require('./dash-blocks.js');
|
|
8
|
-
const { npmContent } = blocks;
|
|
3
|
+
const { THEME, paint, visibleWidth } = require('../term/ansi.js');
|
|
4
|
+
const { paintSegments } = require('./tiles.js');
|
|
5
|
+
const { npmContent } = require('./dashboard/blocks.js');
|
|
9
6
|
const primitives = require('./primitives.js');
|
|
10
7
|
const { MARK_W, markPrefix, paintCursorList, fieldWindow, editSpan } =
|
|
11
8
|
primitives;
|
|
@@ -65,13 +62,12 @@ const paintBodyPackages = (view, width, color, bodyH, headerLines) => {
|
|
|
65
62
|
const paintRow = (line, selected) =>
|
|
66
63
|
paintMarginRow(line, width, color, selected);
|
|
67
64
|
const editing = view.compose && view.compose.kind === 'package';
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
: null;
|
|
65
|
+
let extra = null;
|
|
66
|
+
if (editing) {
|
|
67
|
+
const painted = paintPackageEdit(view.compose, width, color);
|
|
68
|
+
const at = 'index';
|
|
69
|
+
extra = { ...painted, at, index: cursor };
|
|
70
|
+
}
|
|
75
71
|
const painted = paintCursorList(rows, cursor, pane, paintRow, extra);
|
|
76
72
|
if (!headed) return painted;
|
|
77
73
|
const head = paintMarginRow(content.lines[0], width, color, false);
|