reslop 0.2.3 → 0.2.5
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 +27 -1
- package/README.md +8 -4
- package/bin/reslop.js +4 -2
- package/lib/api.js +2 -1
- package/lib/capabilities.js +0 -4
- package/lib/cli.js +19 -10
- package/lib/clipboard.js +45 -4
- package/lib/deps-diff.js +61 -118
- package/lib/deps.js +166 -235
- package/lib/detect.js +4 -2
- package/lib/diff/align.js +2 -1
- package/lib/diff/diff.js +6 -3
- package/lib/diff/display.js +2 -1
- package/lib/diff/inline.js +68 -2
- package/lib/diff/patch.js +2 -1
- package/lib/diff/unit.js +15 -30
- package/lib/editor.js +91 -13
- package/lib/files.js +54 -27
- package/lib/git-branches.js +107 -154
- package/lib/git-deps.js +78 -155
- package/lib/git-worktree.js +508 -0
- package/lib/git.js +23 -580
- package/lib/github.js +9 -8
- package/lib/gitlab.js +5 -4
- package/lib/highlight/bash.js +2 -1
- package/lib/highlight/core.js +11 -0
- package/lib/highlight/css.js +2 -1
- package/lib/highlight/csv.js +2 -1
- package/lib/highlight/dot.js +3 -12
- package/lib/highlight/html.js +2 -1
- package/lib/highlight/json.js +2 -1
- package/lib/highlight/log.js +5 -11
- package/lib/highlight/txt.js +3 -12
- package/lib/highlight.js +2 -1
- package/lib/keys.js +22 -12
- package/lib/manifest.js +4 -6
- package/lib/npm-commands.js +82 -24
- package/lib/remote.js +21 -20
- package/lib/render/branches.js +9 -27
- package/lib/render/chrome.js +109 -35
- package/lib/render/commits.js +216 -216
- package/lib/render/diff.js +160 -47
- package/lib/render/files.js +9 -26
- package/lib/render/frame.js +97 -118
- package/lib/render/notes.js +74 -26
- package/lib/render/npm.js +104 -30
- package/lib/render/present.js +2 -1
- package/lib/render/primitives.js +128 -52
- package/lib/render/render.js +2 -1
- package/lib/render/unit.js +17 -11
- package/lib/report-model.js +6 -4
- package/lib/report-parse.js +8 -14
- package/lib/report-render.js +38 -21
- package/lib/report-run.js +12 -11
- package/lib/report-test.js +45 -51
- package/lib/report-tools.js +44 -25
- package/lib/review-merge.js +102 -131
- package/lib/review.js +69 -78
- package/lib/select.js +52 -0
- package/lib/session/actions.js +72 -87
- package/lib/session/branches.js +18 -52
- package/lib/session/change-actions.js +175 -147
- package/lib/session/commit.js +65 -61
- package/lib/session/compose.js +152 -83
- package/lib/session/dispatch.js +53 -46
- package/lib/session/edit-click.js +57 -0
- package/lib/session/files-pane.js +30 -51
- package/lib/session/items.js +73 -90
- package/lib/session/lifecycle.js +37 -98
- package/lib/session/load.js +52 -57
- package/lib/session/navigation.js +105 -95
- package/lib/session/npm.js +205 -71
- package/lib/session/ops.js +200 -45
- package/lib/session/pointer.js +33 -8
- package/lib/session/progress.js +9 -6
- package/lib/session/review.js +35 -53
- package/lib/session/tasks.js +292 -0
- package/lib/session/terminal.js +17 -19
- package/lib/session/unit.js +3 -4
- package/lib/session/update.js +76 -96
- package/lib/session/view.js +45 -16
- package/lib/session/watch.js +47 -27
- package/lib/session.js +66 -97
- package/lib/source.js +6 -3
- package/lib/update.js +5 -13
- package/lib/utilities.js +25 -3
- package/lib/wrap.js +18 -1
- package/package.json +1 -1
- package/lib/session/todos.js +0 -293
package/lib/render/chrome.js
CHANGED
|
@@ -5,11 +5,11 @@ const keys = require('../keys.js');
|
|
|
5
5
|
const files = require('../files.js');
|
|
6
6
|
const primitives = require('./primitives.js');
|
|
7
7
|
|
|
8
|
-
const { itemPath,
|
|
8
|
+
const { itemPath, REPO_TASKS_LABEL, isTasksEntry, fileTotals } = files;
|
|
9
9
|
const { ACTION_IDS, BRANCH_ACTIONS, COMMIT_ACTIONS, actionLetter } = keys;
|
|
10
10
|
const { buttonWord } = keys;
|
|
11
11
|
const { FILES_HIDDEN, FILES_GIT_DISABLED, BRANCHES_DISABLED } = keys;
|
|
12
|
-
const { COMMITS_DISABLED,
|
|
12
|
+
const { COMMITS_DISABLED, TASKS_DISABLED, DIFF_DISABLED, UNIT_DISABLED } = keys;
|
|
13
13
|
const { NPM_DISABLED } = keys;
|
|
14
14
|
const { diffGitDisabled, branchGitDisabled, commitGitDisabled } = keys;
|
|
15
15
|
const { CONFIRM, confirmPrefix, promptFromChoices } = keys;
|
|
@@ -122,6 +122,9 @@ const BUTTON_LEAD = ' ';
|
|
|
122
122
|
const BUTTON_GAP = ' ';
|
|
123
123
|
const BUTTON_EDGE = 1;
|
|
124
124
|
const buttonGap = (index) => (index ? BUTTON_GAP : BUTTON_LEAD);
|
|
125
|
+
const BACK_ARROW = '🢐';
|
|
126
|
+
const STOP_MARK = '⊗';
|
|
127
|
+
const BACK_KEY = 'esc';
|
|
125
128
|
const LOGO = '👁️';
|
|
126
129
|
|
|
127
130
|
const pathSegments = (rel) => {
|
|
@@ -152,10 +155,10 @@ const headerScreen = (view) => {
|
|
|
152
155
|
if (pane === 'files') {
|
|
153
156
|
const files = view.files ?? [];
|
|
154
157
|
const entry = files[view.fileCursor ?? 0];
|
|
155
|
-
if (
|
|
158
|
+
if (isTasksEntry(entry)) return REPO_TASKS_LABEL;
|
|
156
159
|
return '';
|
|
157
160
|
}
|
|
158
|
-
if (view.item && view.item.origin === '
|
|
161
|
+
if (view.item && view.item.origin === 'task') return REPO_TASKS_LABEL;
|
|
159
162
|
return '';
|
|
160
163
|
};
|
|
161
164
|
|
|
@@ -163,11 +166,11 @@ const headerTarget = (view) => {
|
|
|
163
166
|
const pane = view.pane ?? 'diff';
|
|
164
167
|
if (pane === 'files') {
|
|
165
168
|
const entry = (view.files ?? [])[view.fileCursor ?? 0];
|
|
166
|
-
if (!entry ||
|
|
169
|
+
if (!entry || isTasksEntry(entry)) return '';
|
|
167
170
|
return entry.path;
|
|
168
171
|
}
|
|
169
172
|
if (pane === 'unit') return view.reviewPath ?? '';
|
|
170
|
-
if (!view.item || view.item.origin === '
|
|
173
|
+
if (!view.item || view.item.origin === 'task') return '';
|
|
171
174
|
return itemPath(view.item);
|
|
172
175
|
};
|
|
173
176
|
|
|
@@ -251,6 +254,38 @@ const QUIT_MARK = {
|
|
|
251
254
|
missBold: false,
|
|
252
255
|
};
|
|
253
256
|
|
|
257
|
+
const backFooterId = (view) => {
|
|
258
|
+
const pane = view.pane ?? 'diff';
|
|
259
|
+
if (pane === 'branches' || pane === 'commits') return 'back';
|
|
260
|
+
if (pane === 'npm') return view.npmView ? 'npmStop' : 'back';
|
|
261
|
+
if (view.item && view.item.origin === 'task') return 'back';
|
|
262
|
+
return '';
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
const backHintMark = (view) => {
|
|
266
|
+
if (view.pane === 'npm' && view.npmView && view.npmRunning) return STOP_MARK;
|
|
267
|
+
return BACK_ARROW;
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
const hintBody = (mark) => {
|
|
271
|
+
const gap = mark === STOP_MARK ? ' ' : '';
|
|
272
|
+
return `${mark}${gap}${BACK_KEY}`;
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
const buttonLabel = (id, short, backId, mark) => {
|
|
276
|
+
if (id === backId) return hintBody(mark);
|
|
277
|
+
if (short) return actionLetter(id);
|
|
278
|
+
return buttonWord(id);
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
const paintBackHint = (color, mark) => {
|
|
282
|
+
const bgRgb = THEME.buttonBg;
|
|
283
|
+
const body = hintBody(mark);
|
|
284
|
+
const arrow = paint(mark, THEME.buttonHotFg, bgRgb, color, true);
|
|
285
|
+
const rest = paint(body.slice(mark.length), THEME.buttonFg, bgRgb, color);
|
|
286
|
+
return arrow + rest;
|
|
287
|
+
};
|
|
288
|
+
|
|
254
289
|
const paintMarkedWord = (label, letter, color, mark) => {
|
|
255
290
|
const at = label.indexOf(letter);
|
|
256
291
|
if (at < 0) {
|
|
@@ -266,37 +301,49 @@ const paintMarkedWord = (label, letter, color, mark) => {
|
|
|
266
301
|
return out;
|
|
267
302
|
};
|
|
268
303
|
|
|
269
|
-
const
|
|
270
|
-
const
|
|
271
|
-
const extraIds = extra ?? [];
|
|
272
|
-
const disabledIds = disabled ?? [];
|
|
273
|
-
const ids = [];
|
|
304
|
+
const footerIds = (hidden, extra, backId) => {
|
|
305
|
+
const ids = backId ? [backId] : [];
|
|
274
306
|
for (const id of ACTION_IDS) {
|
|
275
|
-
if (id
|
|
276
|
-
|
|
277
|
-
if (!ids.includes(add)) ids.push(add);
|
|
278
|
-
}
|
|
307
|
+
if (id !== 'quit') {
|
|
308
|
+
if (!hidden.includes(id)) ids.push(id);
|
|
279
309
|
continue;
|
|
280
310
|
}
|
|
281
|
-
|
|
282
|
-
|
|
311
|
+
for (const add of extra) {
|
|
312
|
+
if (!ids.includes(add)) ids.push(add);
|
|
313
|
+
}
|
|
283
314
|
}
|
|
315
|
+
return ids;
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
const layoutButtons = (width, options = {}) => {
|
|
319
|
+
const { compact = false, hidden = [], extra = [] } = options;
|
|
320
|
+
const { disabled: disabledIds = [], backId = '', mark = '' } = options;
|
|
321
|
+
const hint = mark || BACK_ARROW;
|
|
322
|
+
const ids = footerIds(hidden, extra, backId);
|
|
284
323
|
const build = (short) => {
|
|
285
324
|
const hits = [];
|
|
286
325
|
const parts = [];
|
|
287
326
|
let x = 0;
|
|
288
327
|
const limit = Math.max(0, width - BUTTON_EDGE);
|
|
289
328
|
for (const id of ids) {
|
|
290
|
-
const
|
|
291
|
-
const
|
|
292
|
-
const label = short
|
|
329
|
+
const back = id === backId;
|
|
330
|
+
const letter = back ? BACK_KEY : actionLetter(id);
|
|
331
|
+
const label = buttonLabel(id, short, backId, hint);
|
|
293
332
|
const gap = buttonGap(parts.length);
|
|
294
333
|
const piece = `${gap}${label}`;
|
|
295
334
|
const w = visibleWidth(piece);
|
|
296
335
|
if (x + w > limit && parts.length) break;
|
|
297
336
|
const off = disabledIds.includes(id);
|
|
298
337
|
if (!off) hits.push({ id, x0: x, x1: x + w });
|
|
299
|
-
parts.push({
|
|
338
|
+
parts.push({
|
|
339
|
+
action: { id },
|
|
340
|
+
piece,
|
|
341
|
+
letter,
|
|
342
|
+
label,
|
|
343
|
+
disabled: off,
|
|
344
|
+
back,
|
|
345
|
+
mark: back ? hint : '',
|
|
346
|
+
});
|
|
300
347
|
x += w;
|
|
301
348
|
}
|
|
302
349
|
return { hits, parts, width: x };
|
|
@@ -316,7 +363,8 @@ const paintButtons = (layout, width, color) => {
|
|
|
316
363
|
const part = layout.parts[i];
|
|
317
364
|
const gap = buttonGap(i);
|
|
318
365
|
out += paint(gap, fgRgb, bgRgb, color);
|
|
319
|
-
if (part.
|
|
366
|
+
if (part.back) out += paintBackHint(color, part.mark);
|
|
367
|
+
else if (part.disabled) out += paint(part.label, fgRgb, bgRgb, color);
|
|
320
368
|
else out += paintMarkedWord(part.label, part.letter, color, BUTTON_MARK);
|
|
321
369
|
used += visibleWidth(part.piece);
|
|
322
370
|
}
|
|
@@ -351,9 +399,9 @@ const countsKind = (sourceKind, revShort) => {
|
|
|
351
399
|
|
|
352
400
|
const notesLine = (counts) => {
|
|
353
401
|
const feedback = counts.feedback ?? 0;
|
|
354
|
-
const
|
|
402
|
+
const tasks = counts.tasks ?? 0;
|
|
355
403
|
const code = counts.code ?? 0;
|
|
356
|
-
return `feedback ${feedback}
|
|
404
|
+
return `feedback ${feedback} tasks ${tasks} code ${code}`;
|
|
357
405
|
};
|
|
358
406
|
|
|
359
407
|
const statusLead = (view) => {
|
|
@@ -397,7 +445,9 @@ const statusStats = (view) => {
|
|
|
397
445
|
const fallbackN = counts.staged ?? 0;
|
|
398
446
|
const n = hasGit ? total.staged : fallbackN;
|
|
399
447
|
const m = hasGit ? total.remaining : counted;
|
|
400
|
-
|
|
448
|
+
const git = joinStatus([statusDelta(total), `${n}/${m}`]);
|
|
449
|
+
if (!view.npmLogs) return git;
|
|
450
|
+
return joinStatus([view.npmLogs, git]);
|
|
401
451
|
};
|
|
402
452
|
|
|
403
453
|
const statusLayout = (view, status, width) => {
|
|
@@ -454,6 +504,7 @@ const paintChoicePrompt = (choices, width, color, prefix = '') => {
|
|
|
454
504
|
};
|
|
455
505
|
|
|
456
506
|
const STATUS_MARK = /(\+[0-9]+(?:\/[0-9]+)?|-[0-9]+(?:\/[0-9]+)?)/g;
|
|
507
|
+
const OLD_LOGS = /old logs \S+/;
|
|
457
508
|
|
|
458
509
|
const paintStatusMark = (token, color) => {
|
|
459
510
|
const bgRgb = THEME.chromeBg;
|
|
@@ -467,6 +518,18 @@ const paintStatusLeft = (text, color) => {
|
|
|
467
518
|
const bgRgb = THEME.chromeBg;
|
|
468
519
|
const muted = THEME.mutedFg;
|
|
469
520
|
if (!color) return text;
|
|
521
|
+
const found = text.match(OLD_LOGS);
|
|
522
|
+
if (found) {
|
|
523
|
+
const at = found.index;
|
|
524
|
+
const token = found[0];
|
|
525
|
+
const before = text.slice(0, at);
|
|
526
|
+
const after = text.slice(at + token.length);
|
|
527
|
+
return (
|
|
528
|
+
paintStatusLeft(before, color) +
|
|
529
|
+
paint(token, THEME.shaFg, bgRgb, color) +
|
|
530
|
+
paintStatusLeft(after, color)
|
|
531
|
+
);
|
|
532
|
+
}
|
|
470
533
|
let out = '';
|
|
471
534
|
let last = 0;
|
|
472
535
|
for (const match of text.matchAll(STATUS_MARK)) {
|
|
@@ -604,7 +667,7 @@ const hiddenActions = (view) => {
|
|
|
604
667
|
if (pane === 'branches') return BRANCHES_DISABLED;
|
|
605
668
|
if (pane === 'commits') return COMMITS_DISABLED;
|
|
606
669
|
if (pane === 'npm') return NPM_DISABLED;
|
|
607
|
-
if (view.item && view.item.origin === '
|
|
670
|
+
if (view.item && view.item.origin === 'task') return TASKS_DISABLED;
|
|
608
671
|
return DIFF_DISABLED;
|
|
609
672
|
};
|
|
610
673
|
|
|
@@ -613,7 +676,7 @@ const dimFooterActions = (view) => {
|
|
|
613
676
|
if (pane === 'files') {
|
|
614
677
|
const files = view.files ?? [];
|
|
615
678
|
const entry = files[view.fileCursor ?? 0];
|
|
616
|
-
if (!entry || entry.kind !== '
|
|
679
|
+
if (!entry || entry.kind !== 'tasks') return [];
|
|
617
680
|
return FILES_GIT_DISABLED;
|
|
618
681
|
}
|
|
619
682
|
if (pane === 'diff' || pane === 'unit') return diffGitDisabled(view.item);
|
|
@@ -621,13 +684,18 @@ const dimFooterActions = (view) => {
|
|
|
621
684
|
if (pane === 'commits') {
|
|
622
685
|
const entry = selectedCommit(view);
|
|
623
686
|
const staged = (view.counts?.staged ?? 0) > 0;
|
|
624
|
-
|
|
625
|
-
return commitGitDisabled({
|
|
687
|
+
const unstagedCurrent = !view.rev && !view.revShort;
|
|
688
|
+
return commitGitDisabled({
|
|
689
|
+
...entry,
|
|
690
|
+
canCommit: staged,
|
|
691
|
+
unstagedCurrent,
|
|
692
|
+
});
|
|
626
693
|
}
|
|
627
694
|
if (pane === 'npm' && view.npmView) {
|
|
628
695
|
if (view.npmRunning) return ['npmRerun'];
|
|
629
696
|
return [];
|
|
630
697
|
}
|
|
698
|
+
if (pane === 'npm' && !view.npmLogs) return ['npmLogs'];
|
|
631
699
|
return [];
|
|
632
700
|
};
|
|
633
701
|
|
|
@@ -640,12 +708,21 @@ const extraFooterActions = (view) => {
|
|
|
640
708
|
if (pane === 'branches') return Object.keys(BRANCH_ACTIONS);
|
|
641
709
|
if (pane === 'commits') return Object.keys(COMMIT_ACTIONS);
|
|
642
710
|
if (pane === 'npm') {
|
|
643
|
-
if (view.npmView) return ['
|
|
644
|
-
return ['npmEdit', 'npmNew'];
|
|
711
|
+
if (view.npmView) return ['npmVerbose', 'npmRerun'];
|
|
712
|
+
return ['npmEdit', 'npmNew', 'npmDrop', 'npmLogs'];
|
|
645
713
|
}
|
|
646
714
|
return [];
|
|
647
715
|
};
|
|
648
716
|
|
|
717
|
+
const footerLayout = (view, width) =>
|
|
718
|
+
layoutButtons(width, {
|
|
719
|
+
hidden: hiddenActions(view),
|
|
720
|
+
extra: extraFooterActions(view),
|
|
721
|
+
disabled: dimFooterActions(view),
|
|
722
|
+
backId: backFooterId(view),
|
|
723
|
+
mark: backHintMark(view),
|
|
724
|
+
});
|
|
725
|
+
|
|
649
726
|
module.exports = {
|
|
650
727
|
QUIT_PROMPT,
|
|
651
728
|
PUSH_PROMPT,
|
|
@@ -655,13 +732,10 @@ module.exports = {
|
|
|
655
732
|
headerText,
|
|
656
733
|
paintHeader,
|
|
657
734
|
layoutButtons,
|
|
658
|
-
|
|
735
|
+
footerLayout,
|
|
659
736
|
paintFooter,
|
|
660
737
|
footerHits,
|
|
661
738
|
paintStatusLine,
|
|
662
739
|
statusChoiceHits,
|
|
663
740
|
statusBranchHit,
|
|
664
|
-
hiddenActions,
|
|
665
|
-
dimFooterActions,
|
|
666
|
-
extraFooterActions,
|
|
667
741
|
};
|