reslop 0.2.6 → 0.2.7
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 +11 -1
- package/lib/ansi.js +42 -2
- package/lib/api.js +1 -1
- package/lib/cli.js +21 -1
- package/lib/dashboard/model.js +28 -3
- package/lib/dashboard/npm.js +116 -19
- package/lib/files.js +13 -7
- package/lib/find.js +61 -0
- package/lib/git-deps.js +1 -0
- package/lib/git-worktree.js +22 -4
- package/lib/keys.js +26 -1
- package/lib/render/chrome.js +257 -79
- package/lib/render/dash-blocks.js +297 -46
- package/lib/render/dash-table.js +6 -1
- package/lib/render/files.js +23 -4
- package/lib/render/frame.js +4 -0
- package/lib/render/notes.js +13 -2
- package/lib/render/packages.js +93 -0
- package/lib/render/primitives.js +13 -6
- package/lib/render/repos.js +226 -0
- package/lib/render/search.js +25 -0
- package/lib/render/tiles.js +107 -12
- package/lib/review.js +5 -4
- package/lib/session/actions.js +136 -30
- package/lib/session/branches.js +3 -5
- package/lib/session/commit.js +31 -4
- package/lib/session/compose.js +19 -4
- package/lib/session/dashboard.js +160 -15
- package/lib/session/dispatch.js +38 -4
- package/lib/session/files-pane.js +17 -2
- package/lib/session/find.js +94 -0
- package/lib/session/lifecycle.js +27 -0
- package/lib/session/navigation.js +2 -0
- package/lib/session/packages.js +143 -0
- package/lib/session/pointer.js +14 -0
- package/lib/session/tasks.js +3 -3
- package/lib/session/view.js +15 -2
- package/lib/session/watch.js +5 -0
- package/lib/session/workspace.js +455 -0
- package/lib/session.js +14 -0
- package/lib/workspace.js +166 -0
- package/package.json +1 -1
package/lib/render/chrome.js
CHANGED
|
@@ -4,6 +4,8 @@ const ansi = require('../ansi.js');
|
|
|
4
4
|
const keys = require('../keys.js');
|
|
5
5
|
const files = require('../files.js');
|
|
6
6
|
const primitives = require('./primitives.js');
|
|
7
|
+
const blocks = require('./dash-blocks.js');
|
|
8
|
+
const { npmStatus } = blocks;
|
|
7
9
|
|
|
8
10
|
const { itemPath, REPO_TASKS_LABEL, isTasksEntry, fileTotals } = files;
|
|
9
11
|
const { ACTION_IDS, actionLetter } = keys;
|
|
@@ -12,10 +14,15 @@ const { FILES_HIDDEN, FILES_GIT_DISABLED, BRANCHES_DISABLED } = keys;
|
|
|
12
14
|
const { COMMITS_DISABLED, TASKS_DISABLED, DIFF_DISABLED, UNIT_DISABLED } = keys;
|
|
13
15
|
const { NPM_DISABLED } = keys;
|
|
14
16
|
const { diffGitDisabled, branchGitDisabled, commitGitDisabled } = keys;
|
|
17
|
+
const { entryHasDiff, lineHasDiff, withoutMoves } = keys;
|
|
15
18
|
const { CONFIRM, confirmPrefix, promptFromChoices } = keys;
|
|
16
19
|
const { THEME, paint, visibleWidth } = ansi;
|
|
17
20
|
const { truncateVisible, fg, RESET, EL, seq } = ansi;
|
|
18
21
|
const { fill, branchLabel, isTaskView } = primitives;
|
|
22
|
+
const searchPaint = require('./search.js');
|
|
23
|
+
const { paintPathText } = searchPaint;
|
|
24
|
+
const locate = require('../find.js');
|
|
25
|
+
const { activeHit, spansFor, fileMatches } = locate;
|
|
19
26
|
|
|
20
27
|
const WAVE = '·•●•·';
|
|
21
28
|
const BUSY_BAR = Array.from(WAVE, (_, frame) => {
|
|
@@ -57,6 +64,7 @@ const INFO_STATUS = [
|
|
|
57
64
|
'dropped',
|
|
58
65
|
'already staged',
|
|
59
66
|
'read only',
|
|
67
|
+
'transitive',
|
|
60
68
|
'nothing to review',
|
|
61
69
|
'nothing to commit',
|
|
62
70
|
'unified',
|
|
@@ -112,7 +120,6 @@ const BUTTON_LEAD = ' ';
|
|
|
112
120
|
const BUTTON_GAP = ' ';
|
|
113
121
|
const BUTTON_EDGE = 1;
|
|
114
122
|
const BACK_ARROW = '🢐';
|
|
115
|
-
const STOP_MARK = '⊗';
|
|
116
123
|
const BACK_KEY = 'esc';
|
|
117
124
|
|
|
118
125
|
const BUTTON_MARK = {
|
|
@@ -160,8 +167,10 @@ const headerScreen = (view) => {
|
|
|
160
167
|
const { pane } = view;
|
|
161
168
|
if (
|
|
162
169
|
pane === 'dashboard' ||
|
|
170
|
+
pane === 'repos' ||
|
|
163
171
|
pane === 'branches' ||
|
|
164
172
|
pane === 'npm' ||
|
|
173
|
+
pane === 'packages' ||
|
|
165
174
|
pane === 'tasks'
|
|
166
175
|
) {
|
|
167
176
|
return pane;
|
|
@@ -205,44 +214,74 @@ const headerText = (view) => {
|
|
|
205
214
|
return `${piecesText(pieces)}${label}`;
|
|
206
215
|
};
|
|
207
216
|
|
|
217
|
+
const headerFind = (view, label, clipped) => {
|
|
218
|
+
const query = view.find && view.find.query ? view.find.query : '';
|
|
219
|
+
const target = headerTarget(view);
|
|
220
|
+
if (!query || label !== target || !label) return [];
|
|
221
|
+
const hit = activeHit(view.files ?? [], view.find);
|
|
222
|
+
return spansFor(clipped, label, query, hit);
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
const paintHeaderRoles = (pieces) => {
|
|
226
|
+
let out = `${seq(THEME.headerChromeFg, THEME.headerBg)}${EL}`;
|
|
227
|
+
for (const piece of pieces) {
|
|
228
|
+
out += `${fg(HEADER_ROLE_FG[piece.role])}${piece.text}`;
|
|
229
|
+
}
|
|
230
|
+
return out;
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
const paintHeaderHits = (clipped, spans, color) => {
|
|
234
|
+
let out = '';
|
|
235
|
+
let offset = 0;
|
|
236
|
+
for (const seg of pathSegments(clipped)) {
|
|
237
|
+
const local = [];
|
|
238
|
+
const end = offset + seg.text.length;
|
|
239
|
+
for (const span of spans) {
|
|
240
|
+
const start = Math.max(span.start, offset);
|
|
241
|
+
const stop = Math.min(span.end, end);
|
|
242
|
+
if (start >= stop) continue;
|
|
243
|
+
local.push({
|
|
244
|
+
start: start - offset,
|
|
245
|
+
end: stop - offset,
|
|
246
|
+
on: span.on === true,
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
const roleFg = HEADER_ROLE_FG[seg.role];
|
|
250
|
+
out += paintPathText(seg.text, roleFg, THEME.headerBg, color, false, local);
|
|
251
|
+
offset = end;
|
|
252
|
+
}
|
|
253
|
+
return out;
|
|
254
|
+
};
|
|
255
|
+
|
|
208
256
|
const paintHeader = (view, width, color) => {
|
|
209
257
|
const { pieces, label } = headerLead(view);
|
|
210
258
|
const right = ' ';
|
|
211
259
|
const used = visibleWidth(piecesText(pieces)) + visibleWidth(right);
|
|
212
260
|
const room = Math.max(0, width - used);
|
|
213
261
|
const clipped = truncateVisible(label, room);
|
|
214
|
-
const pad = Math.max(0, room - visibleWidth(clipped));
|
|
215
|
-
|
|
216
|
-
if (
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
262
|
+
const pad = ' '.repeat(Math.max(0, room - visibleWidth(clipped)));
|
|
263
|
+
const spans = headerFind(view, label, clipped);
|
|
264
|
+
if (!color || !spans.length) {
|
|
265
|
+
pieces.push(...pathSegments(clipped));
|
|
266
|
+
if (pad) pieces.push({ text: pad, role: 'chrome' });
|
|
267
|
+
pieces.push({ text: right, role: 'chrome' });
|
|
268
|
+
if (!color) return piecesText(pieces);
|
|
269
|
+
return `${paintHeaderRoles(pieces)}${RESET}`;
|
|
222
270
|
}
|
|
271
|
+
let out = paintHeaderRoles(pieces);
|
|
272
|
+
out += paintHeaderHits(clipped, spans, color);
|
|
273
|
+
out += `${fg(HEADER_ROLE_FG.chrome)}${pad}${right}`;
|
|
223
274
|
return `${out}${RESET}`;
|
|
224
275
|
};
|
|
225
276
|
|
|
226
|
-
const backFooterId = (view) =>
|
|
227
|
-
|
|
228
|
-
if (pane === 'branches' || pane === 'commits' || pane === 'tasks') {
|
|
229
|
-
return 'back';
|
|
230
|
-
}
|
|
231
|
-
if (pane === 'npm') return view.npmView ? 'npmStop' : 'back';
|
|
232
|
-
return isTaskView(view) ? 'back' : '';
|
|
233
|
-
};
|
|
277
|
+
const backFooterId = (view) =>
|
|
278
|
+
view.pane === 'npm' && view.npmView ? 'npmStop' : 'back';
|
|
234
279
|
|
|
235
|
-
const backHintMark = (
|
|
236
|
-
if (view.pane === 'npm' && view.npmView && view.npmRunning) return STOP_MARK;
|
|
237
|
-
return BACK_ARROW;
|
|
238
|
-
};
|
|
280
|
+
const backHintMark = () => BACK_ARROW;
|
|
239
281
|
|
|
240
282
|
const buttonGap = (index) => (index ? BUTTON_GAP : BUTTON_LEAD);
|
|
241
283
|
|
|
242
|
-
const hintBody = (mark) => {
|
|
243
|
-
const gap = mark === STOP_MARK ? ' ' : '';
|
|
244
|
-
return `${mark}${gap}${BACK_KEY}`;
|
|
245
|
-
};
|
|
284
|
+
const hintBody = (mark) => `${mark}${BACK_KEY}`;
|
|
246
285
|
|
|
247
286
|
const buttonLabel = (id, short) => (short ? actionLetter(id) : buttonWord(id));
|
|
248
287
|
|
|
@@ -266,38 +305,125 @@ const paintMarkedWord = (label, letter, color, mark) => {
|
|
|
266
305
|
return out + paint(after, mark.fgRgb, mark.bgRgb, color);
|
|
267
306
|
};
|
|
268
307
|
|
|
269
|
-
const footerIds = (hidden, extra, backId) => {
|
|
308
|
+
const footerIds = (hidden, extra, backId, globals, tail, after) => {
|
|
270
309
|
const ids = backId ? [backId] : [];
|
|
271
|
-
|
|
272
|
-
if (!ids.includes(
|
|
273
|
-
}
|
|
274
|
-
for (const
|
|
275
|
-
|
|
276
|
-
|
|
310
|
+
const push = (id) => {
|
|
311
|
+
if (!ids.includes(id)) ids.push(id);
|
|
312
|
+
};
|
|
313
|
+
for (const add of extra) push(add);
|
|
314
|
+
for (const id of globals) push(id);
|
|
315
|
+
if (tail) {
|
|
316
|
+
for (const id of ACTION_IDS) {
|
|
317
|
+
if (id === 'quit' || hidden.includes(id) || ids.includes(id)) continue;
|
|
318
|
+
ids.push(id);
|
|
319
|
+
}
|
|
277
320
|
}
|
|
321
|
+
for (const id of after) push(id);
|
|
278
322
|
return ids;
|
|
279
323
|
};
|
|
280
324
|
|
|
325
|
+
const buttonPiece = (id, index, short, backId, mark) => {
|
|
326
|
+
const back = id === backId;
|
|
327
|
+
const letter = back ? BACK_KEY : actionLetter(id);
|
|
328
|
+
const label = back ? hintBody(mark) : buttonLabel(id, short);
|
|
329
|
+
const gap = buttonGap(index);
|
|
330
|
+
return {
|
|
331
|
+
id,
|
|
332
|
+
piece: `${gap}${label}`,
|
|
333
|
+
gap,
|
|
334
|
+
letter,
|
|
335
|
+
label,
|
|
336
|
+
back,
|
|
337
|
+
mark: back ? mark : '',
|
|
338
|
+
};
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
const packGroup = (ids, short, start, backId, mark) => {
|
|
342
|
+
const parts = [];
|
|
343
|
+
for (let i = 0; i < ids.length; i++) {
|
|
344
|
+
parts.push(buttonPiece(ids[i], start + i, short, backId, mark));
|
|
345
|
+
}
|
|
346
|
+
return parts;
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
const groupWidth = (parts) => {
|
|
350
|
+
let width = 0;
|
|
351
|
+
for (const part of parts) width += visibleWidth(part.piece);
|
|
352
|
+
return width;
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
const placeGroup = (parts, hits, disabled, x) => {
|
|
356
|
+
const placed = [];
|
|
357
|
+
let cursor = x;
|
|
358
|
+
for (const part of parts) {
|
|
359
|
+
const w = visibleWidth(part.piece);
|
|
360
|
+
const off = disabled.includes(part.id);
|
|
361
|
+
if (!off) hits.push({ id: part.id, x0: cursor, x1: cursor + w });
|
|
362
|
+
placed.push({ ...part, disabled: off });
|
|
363
|
+
cursor += w;
|
|
364
|
+
}
|
|
365
|
+
return { placed, cursor };
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
const splitFooter = (ids, options, limit) => {
|
|
369
|
+
const { disabled = [], backId = '', mark = BACK_ARROW } = options;
|
|
370
|
+
const { globals = [], after = [] } = options;
|
|
371
|
+
const rightIds = [];
|
|
372
|
+
for (const id of [...globals, ...after]) {
|
|
373
|
+
if (ids.includes(id) && !rightIds.includes(id)) rightIds.push(id);
|
|
374
|
+
}
|
|
375
|
+
const leftIds = ids.filter((id) => !rightIds.includes(id));
|
|
376
|
+
const pack = (leftShort, rightShort) => {
|
|
377
|
+
const left = packGroup(leftIds, leftShort, 0, backId, mark);
|
|
378
|
+
const start = left.length ? 1 : 0;
|
|
379
|
+
const right = packGroup(rightIds, rightShort, start, backId, mark);
|
|
380
|
+
return { left, right };
|
|
381
|
+
};
|
|
382
|
+
const wide = (packed) =>
|
|
383
|
+
groupWidth(packed.left) + groupWidth(packed.right) > limit;
|
|
384
|
+
let packed = pack(false, false);
|
|
385
|
+
if (wide(packed)) packed = pack(false, true);
|
|
386
|
+
if (wide(packed)) packed = pack(true, true);
|
|
387
|
+
const left = packed.left.slice();
|
|
388
|
+
const right = packed.right.slice();
|
|
389
|
+
while (groupWidth(left) + groupWidth(right) > limit && left.length) {
|
|
390
|
+
left.pop();
|
|
391
|
+
}
|
|
392
|
+
while (groupWidth(left) + groupWidth(right) > limit && right.length) {
|
|
393
|
+
right.pop();
|
|
394
|
+
}
|
|
395
|
+
const hits = [];
|
|
396
|
+
const leftPlace = placeGroup(left, hits, disabled, 0);
|
|
397
|
+
const parts = leftPlace.placed;
|
|
398
|
+
let x = leftPlace.cursor;
|
|
399
|
+
const gap = Math.max(0, limit - x - groupWidth(right));
|
|
400
|
+
if (gap && right.length) {
|
|
401
|
+
parts.push({ spacer: true, piece: ' '.repeat(gap) });
|
|
402
|
+
x += gap;
|
|
403
|
+
}
|
|
404
|
+
const rightPlace = placeGroup(right, hits, disabled, x);
|
|
405
|
+
parts.push(...rightPlace.placed);
|
|
406
|
+
return { hits, parts };
|
|
407
|
+
};
|
|
408
|
+
|
|
281
409
|
const layoutButtons = (width, options = {}) => {
|
|
282
410
|
const { compact = false, hidden = [], extra = [], disabled = [] } = options;
|
|
283
|
-
const { backId = '', mark = BACK_ARROW } = options;
|
|
284
|
-
const
|
|
411
|
+
const { backId = '', mark = BACK_ARROW, globals = [] } = options;
|
|
412
|
+
const { tail = true, after = [] } = options;
|
|
413
|
+
const ids = footerIds(hidden, extra, backId, globals, tail, after);
|
|
285
414
|
const limit = Math.max(0, width - BUTTON_EDGE);
|
|
415
|
+
if (globals.length) return splitFooter(ids, options, limit);
|
|
286
416
|
const build = (short) => {
|
|
287
417
|
const hits = [];
|
|
288
418
|
const parts = [];
|
|
289
419
|
let x = 0;
|
|
290
420
|
for (const id of ids) {
|
|
291
|
-
const
|
|
292
|
-
const
|
|
293
|
-
const label = back ? hintBody(mark) : buttonLabel(id, short);
|
|
294
|
-
const piece = `${buttonGap(parts.length)}${label}`;
|
|
295
|
-
const w = visibleWidth(piece);
|
|
421
|
+
const part = buttonPiece(id, parts.length, short, backId, mark);
|
|
422
|
+
const w = visibleWidth(part.piece);
|
|
296
423
|
if (x + w > limit && parts.length) break;
|
|
297
424
|
const off = disabled.includes(id);
|
|
298
425
|
if (!off) hits.push({ id, x0: x, x1: x + w });
|
|
299
|
-
|
|
300
|
-
parts.push({ id, piece, letter, label, disabled: off, back, mark: hint });
|
|
426
|
+
parts.push({ ...part, disabled: off });
|
|
301
427
|
x += w;
|
|
302
428
|
}
|
|
303
429
|
return { hits, parts };
|
|
@@ -315,7 +441,13 @@ const paintButtons = (layout, width, color) => {
|
|
|
315
441
|
let used = 0;
|
|
316
442
|
for (let i = 0; i < layout.parts.length; i++) {
|
|
317
443
|
const part = layout.parts[i];
|
|
318
|
-
|
|
444
|
+
if (part.spacer) {
|
|
445
|
+
out += paint(part.piece, fgRgb, bgRgb, color);
|
|
446
|
+
used += visibleWidth(part.piece);
|
|
447
|
+
continue;
|
|
448
|
+
}
|
|
449
|
+
const gap = part.gap ?? buttonGap(i);
|
|
450
|
+
out += paint(gap, fgRgb, bgRgb, color);
|
|
319
451
|
if (part.back) out += paintBackHint(color, part.mark);
|
|
320
452
|
else if (part.disabled) out += paint(part.label, fgRgb, bgRgb, color);
|
|
321
453
|
else out += paintMarkedWord(part.label, part.letter, color, BUTTON_MARK);
|
|
@@ -339,13 +471,19 @@ const isWorktree = (view) =>
|
|
|
339
471
|
countsKind(view.sourceKind, view.revShort) === 'worktree';
|
|
340
472
|
|
|
341
473
|
const notesLine = (counts) => {
|
|
342
|
-
const
|
|
343
|
-
const
|
|
344
|
-
|
|
345
|
-
return `feedback ${feedback} tasks ${tasks} code ${code}`;
|
|
474
|
+
const done = counts.tasksDone ?? 0;
|
|
475
|
+
const total = counts.tasks ?? 0;
|
|
476
|
+
return `tasks ${done}/${total}`;
|
|
346
477
|
};
|
|
347
478
|
|
|
348
479
|
const statusLead = (view) => {
|
|
480
|
+
if (view.pane === 'repos') {
|
|
481
|
+
const tiles = view.repos && view.repos.tiles ? view.repos.tiles : [];
|
|
482
|
+
const count = tiles.length;
|
|
483
|
+
if (!count) return 'repos';
|
|
484
|
+
const at = (view.repos.cursor ?? 0) + 1;
|
|
485
|
+
return `${at}/${count}`;
|
|
486
|
+
}
|
|
349
487
|
const counts = view.counts ?? {};
|
|
350
488
|
const kind = countsKind(view.sourceKind, view.revShort);
|
|
351
489
|
if (kind === 'worktree') return branchLabel(view.branch);
|
|
@@ -356,8 +494,13 @@ const statusLead = (view) => {
|
|
|
356
494
|
return `${kind} ${label} ${counts.pr ?? 0}`;
|
|
357
495
|
};
|
|
358
496
|
|
|
359
|
-
const
|
|
360
|
-
|
|
497
|
+
const STATUS_QUIET = new Set(['npm', 'packages', 'branches']);
|
|
498
|
+
|
|
499
|
+
const statusLeft = (view) => {
|
|
500
|
+
if (view.pane === 'repos') return ` ${statusLead(view)}`;
|
|
501
|
+
const notes = STATUS_QUIET.has(view.pane) ? '' : notesLine(view.counts ?? {});
|
|
502
|
+
return ` ${joinStatus([statusLead(view), notes])}`;
|
|
503
|
+
};
|
|
361
504
|
|
|
362
505
|
const statusDelta = (total) => {
|
|
363
506
|
const stagedAdd = total.stagedAdded ?? 0;
|
|
@@ -372,6 +515,8 @@ const statusDelta = (total) => {
|
|
|
372
515
|
return `${plus} ${minus}`;
|
|
373
516
|
};
|
|
374
517
|
|
|
518
|
+
const DIFF_QUIET = new Set(['npm', 'packages', 'tasks', 'branches']);
|
|
519
|
+
|
|
375
520
|
const statusStats = (view) => {
|
|
376
521
|
const counts = view.counts ?? {};
|
|
377
522
|
const staged = counts.staged ?? 0;
|
|
@@ -380,7 +525,10 @@ const statusStats = (view) => {
|
|
|
380
525
|
total.remaining || total.staged || total.added || total.removed;
|
|
381
526
|
const n = hasGit ? total.staged : staged;
|
|
382
527
|
const m = hasGit ? total.remaining : staged + (counts.unstaged ?? 0);
|
|
383
|
-
|
|
528
|
+
const delta = DIFF_QUIET.has(view.pane) ? '' : statusDelta(total);
|
|
529
|
+
const ratio = STATUS_QUIET.has(view.pane) ? '' : `${n}/${m}`;
|
|
530
|
+
const packages = view.pane === 'packages' ? npmStatus(view.packages) : '';
|
|
531
|
+
return joinStatus([view.npmLogs, delta, ratio, packages]);
|
|
384
532
|
};
|
|
385
533
|
|
|
386
534
|
const statusLayout = (view, status, width) => {
|
|
@@ -491,7 +639,26 @@ const paintFooter = (view, layout, width, color) => {
|
|
|
491
639
|
|
|
492
640
|
const footerHits = (view, layout) => (commitSaveHint(view) ? [] : layout.hits);
|
|
493
641
|
|
|
642
|
+
const paintFindStatus = (view, width, color) => {
|
|
643
|
+
const query = view.find.query ?? '';
|
|
644
|
+
const hits = fileMatches(view.files ?? [], query);
|
|
645
|
+
const miss = query.length > 0 && hits.length === 0;
|
|
646
|
+
const lead = ' /';
|
|
647
|
+
const caret = 1;
|
|
648
|
+
const room = Math.max(0, width - lead.length - caret);
|
|
649
|
+
const shown = truncateVisible(query, room);
|
|
650
|
+
const pad = Math.max(0, width - lead.length - visibleWidth(shown) - caret);
|
|
651
|
+
if (!color) return `${lead}${shown}${' '.repeat(caret + pad)}`;
|
|
652
|
+
const bgRgb = THEME.chromeBg;
|
|
653
|
+
const tone = miss ? THEME.errorFg : THEME.chromeFg;
|
|
654
|
+
let out = paint(lead, THEME.warnFg, bgRgb, color, true);
|
|
655
|
+
out += paint(shown, tone, bgRgb, color);
|
|
656
|
+
out += paint(' ', THEME.searchOnFg, THEME.searchOnBg, color);
|
|
657
|
+
return out + fill(pad, THEME.mutedFg, bgRgb, color);
|
|
658
|
+
};
|
|
659
|
+
|
|
494
660
|
const paintStatusLine = (view, status, width, color) => {
|
|
661
|
+
if (view.find) return paintFindStatus(view, width, color);
|
|
495
662
|
const confirm = CONFIRM[view.mode];
|
|
496
663
|
if (confirm) {
|
|
497
664
|
const prefix = confirmPrefix(confirm, view);
|
|
@@ -524,7 +691,7 @@ const statusChoiceHits = (view, y) => {
|
|
|
524
691
|
};
|
|
525
692
|
|
|
526
693
|
const statusBranchHit = (view, width, y) => {
|
|
527
|
-
if (CONFIRM[view.mode]) return null;
|
|
694
|
+
if (view.find || CONFIRM[view.mode]) return null;
|
|
528
695
|
const name = branchLabel(view.branch);
|
|
529
696
|
if (!name || !isWorktree(view)) return null;
|
|
530
697
|
const layout = statusLayout(view, view.status ?? '', width);
|
|
@@ -537,7 +704,7 @@ const withHidden = (ids, more) => [...ids, ...more];
|
|
|
537
704
|
|
|
538
705
|
const hiddenActions = (view) => {
|
|
539
706
|
const { pane } = view;
|
|
540
|
-
if (pane === 'dashboard') return DASH_HIDDEN;
|
|
707
|
+
if (pane === 'dashboard' || pane === 'repos') return DASH_HIDDEN;
|
|
541
708
|
if (pane === 'files') return FILES_HIDDEN;
|
|
542
709
|
if (pane === 'unit') return withHidden(UNIT_DISABLED, ['feedback', 'tasks']);
|
|
543
710
|
if (pane === 'branches') return BRANCHES_DISABLED;
|
|
@@ -552,9 +719,18 @@ const hiddenActions = (view) => {
|
|
|
552
719
|
const dimFooterActions = (view) => {
|
|
553
720
|
const pane = view.pane ?? 'diff';
|
|
554
721
|
if (pane === 'files') {
|
|
555
|
-
|
|
722
|
+
const entry = selectedFile(view);
|
|
723
|
+
if (isTasksEntry(entry)) return FILES_GIT_DISABLED;
|
|
724
|
+
return withoutMoves([], entryHasDiff(entry));
|
|
556
725
|
}
|
|
557
|
-
if (pane === '
|
|
726
|
+
if (pane === 'unit') {
|
|
727
|
+
const off = [...diffGitDisabled(view.item)];
|
|
728
|
+
const lines = view.unitLines;
|
|
729
|
+
if (!lines || !lines.length) return off;
|
|
730
|
+
const line = lines[view.unitLine ?? 0];
|
|
731
|
+
return withoutMoves(off, lineHasDiff(line));
|
|
732
|
+
}
|
|
733
|
+
if (pane === 'diff') return diffGitDisabled(view.item);
|
|
558
734
|
if (pane === 'branches') return branchGitDisabled(selectedBranch(view));
|
|
559
735
|
if (pane === 'commits') {
|
|
560
736
|
return commitGitDisabled({
|
|
@@ -563,46 +739,46 @@ const dimFooterActions = (view) => {
|
|
|
563
739
|
unstagedCurrent: !view.rev && !view.revShort,
|
|
564
740
|
});
|
|
565
741
|
}
|
|
742
|
+
if (pane === 'packages') {
|
|
743
|
+
const listed = view.packages && view.packages.modules;
|
|
744
|
+
const rows = listed && listed.packages ? listed.packages : [];
|
|
745
|
+
const cursor = view.packagesCursor ?? 0;
|
|
746
|
+
const onRow = rows.length > 0 && cursor < rows.length;
|
|
747
|
+
if (!onRow) return ['packageDrop', 'packageWanted', 'packageLatest'];
|
|
748
|
+
if (rows[cursor] && rows[cursor].transitive) {
|
|
749
|
+
return ['packageNew', 'packageDrop'];
|
|
750
|
+
}
|
|
751
|
+
return [];
|
|
752
|
+
}
|
|
566
753
|
if (pane !== 'npm') return [];
|
|
567
754
|
if (view.npmView) return view.npmRunning ? ['npmRerun'] : [];
|
|
568
755
|
return view.npmLogs ? [] : ['npmLogs'];
|
|
569
756
|
};
|
|
570
757
|
|
|
571
|
-
const
|
|
758
|
+
const GIT_FOOTER = ['add', 'unstage', 'revert', 'ignore'];
|
|
572
759
|
|
|
573
760
|
const extraFooterActions = (view) => {
|
|
574
761
|
const { pane } = view;
|
|
575
|
-
if (pane === '
|
|
762
|
+
if (pane === 'repos') return ['theme'];
|
|
763
|
+
if (pane === 'dashboard') return ['theme', 'pull', 'push'];
|
|
764
|
+
if (pane === 'unit') return ['add', 'unstage', 'revert', 'feedback', 'code'];
|
|
765
|
+
if (pane === 'files') return [...GIT_FOOTER, 'code'];
|
|
766
|
+
if (pane === 'diff') return [...GIT_FOOTER, 'feedback', 'code', 'layout'];
|
|
576
767
|
if (pane === 'branches') {
|
|
577
|
-
return [
|
|
578
|
-
...navExcept(['dashNpm']),
|
|
579
|
-
'newBranch',
|
|
580
|
-
'rebase',
|
|
581
|
-
'drop',
|
|
582
|
-
'pull',
|
|
583
|
-
'push',
|
|
584
|
-
];
|
|
768
|
+
return ['newBranch', 'rebase', 'drop', 'pull', 'push'];
|
|
585
769
|
}
|
|
586
770
|
if (pane === 'commits') {
|
|
587
|
-
return [
|
|
588
|
-
...navExcept(['dashCommits']),
|
|
589
|
-
'commit',
|
|
590
|
-
'amend',
|
|
591
|
-
'apply',
|
|
592
|
-
'reword',
|
|
593
|
-
'fixup',
|
|
594
|
-
'drop',
|
|
595
|
-
'view',
|
|
596
|
-
];
|
|
771
|
+
return ['newCommit', 'apply', 'reword', 'drop', 'view', 'pull', 'push'];
|
|
597
772
|
}
|
|
598
773
|
if (pane === 'npm') {
|
|
599
|
-
if (view.npmView)
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
774
|
+
if (view.npmView) return ['npmVerbose', 'npmRerun'];
|
|
775
|
+
return ['npmEdit', 'npmNew', 'npmDrop', 'npmLogs'];
|
|
776
|
+
}
|
|
777
|
+
if (pane === 'packages') {
|
|
778
|
+
return ['packageNew', 'packageDrop', 'packageWanted', 'packageLatest'];
|
|
603
779
|
}
|
|
604
|
-
if (pane === 'tasks' || isTaskView(view)) return [
|
|
605
|
-
return
|
|
780
|
+
if (pane === 'tasks' || isTaskView(view)) return ['drop', 'check'];
|
|
781
|
+
return GIT_FOOTER;
|
|
606
782
|
};
|
|
607
783
|
|
|
608
784
|
const footerLayout = (view, width) =>
|
|
@@ -612,6 +788,8 @@ const footerLayout = (view, width) =>
|
|
|
612
788
|
disabled: dimFooterActions(view),
|
|
613
789
|
backId: backFooterId(view),
|
|
614
790
|
mark: backHintMark(view),
|
|
791
|
+
globals: view.pane === 'repos' ? [] : DASH_IDS,
|
|
792
|
+
tail: false,
|
|
615
793
|
});
|
|
616
794
|
|
|
617
795
|
module.exports = {
|