reslop 0.2.5 → 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.
Files changed (114) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/LICENSE +1 -1
  3. package/README.md +11 -11
  4. package/bin/reslop.js +3 -8
  5. package/lib/ansi.js +72 -19
  6. package/lib/api.js +1 -1
  7. package/lib/capabilities.js +8 -8
  8. package/lib/cli.js +61 -75
  9. package/lib/clipboard.js +39 -47
  10. package/lib/dashboard/git.js +128 -0
  11. package/lib/dashboard/model.js +357 -0
  12. package/lib/dashboard/npm.js +290 -0
  13. package/lib/dashboard/tree.js +278 -0
  14. package/lib/deps-diff.js +197 -402
  15. package/lib/deps.js +113 -240
  16. package/lib/detect.js +8 -18
  17. package/lib/diff/align.js +41 -113
  18. package/lib/diff/diff.js +12 -43
  19. package/lib/diff/display.js +25 -36
  20. package/lib/diff/edit.js +6 -20
  21. package/lib/diff/inline.js +76 -144
  22. package/lib/diff/items.js +33 -47
  23. package/lib/diff/parse.js +28 -56
  24. package/lib/diff/patch.js +12 -33
  25. package/lib/diff/unit.js +79 -178
  26. package/lib/editor.js +52 -69
  27. package/lib/files.js +79 -91
  28. package/lib/find.js +61 -0
  29. package/lib/git-branches.js +254 -416
  30. package/lib/git-deps.js +148 -272
  31. package/lib/git-reword-todo.js +5 -13
  32. package/lib/git-worktree.js +161 -214
  33. package/lib/git.js +21 -49
  34. package/lib/github.js +67 -181
  35. package/lib/gitlab.js +40 -90
  36. package/lib/highlight/bash.js +55 -177
  37. package/lib/highlight/core.js +155 -141
  38. package/lib/highlight/css.js +25 -58
  39. package/lib/highlight/csv.js +19 -37
  40. package/lib/highlight/dart.js +72 -213
  41. package/lib/highlight/dot.js +14 -14
  42. package/lib/highlight/html.js +42 -63
  43. package/lib/highlight/js.js +177 -506
  44. package/lib/highlight/json.js +17 -37
  45. package/lib/highlight/log.js +19 -25
  46. package/lib/highlight/txt.js +7 -10
  47. package/lib/highlight.js +17 -46
  48. package/lib/keys.js +75 -83
  49. package/lib/manifest.js +67 -126
  50. package/lib/npm-commands.js +120 -169
  51. package/lib/remote.js +140 -190
  52. package/lib/render/branches.js +63 -61
  53. package/lib/render/chrome.js +412 -347
  54. package/lib/render/commits.js +160 -361
  55. package/lib/render/dash-activity.js +212 -0
  56. package/lib/render/dash-blocks.js +496 -0
  57. package/lib/render/dash-table.js +295 -0
  58. package/lib/render/dashboard.js +62 -0
  59. package/lib/render/diff.js +123 -258
  60. package/lib/render/files.js +60 -86
  61. package/lib/render/frame.js +82 -117
  62. package/lib/render/notes.js +150 -210
  63. package/lib/render/npm.js +213 -177
  64. package/lib/render/packages.js +93 -0
  65. package/lib/render/present.js +4 -11
  66. package/lib/render/primitives.js +77 -172
  67. package/lib/render/render.js +5 -14
  68. package/lib/render/report.js +43 -0
  69. package/lib/render/repos.js +226 -0
  70. package/lib/render/search.js +25 -0
  71. package/lib/render/tiles.js +355 -0
  72. package/lib/render/unit.js +15 -31
  73. package/lib/report-model.js +110 -33
  74. package/lib/report-parse.js +56 -37
  75. package/lib/report-render.js +102 -59
  76. package/lib/report-run.js +87 -77
  77. package/lib/report-test.js +221 -99
  78. package/lib/report-tools.js +96 -154
  79. package/lib/review-merge.js +33 -41
  80. package/lib/review.js +69 -129
  81. package/lib/runs.js +225 -0
  82. package/lib/select.js +53 -91
  83. package/lib/session/accessors.js +14 -21
  84. package/lib/session/actions.js +189 -65
  85. package/lib/session/branches.js +164 -222
  86. package/lib/session/change-actions.js +49 -119
  87. package/lib/session/commit.js +298 -352
  88. package/lib/session/compose.js +572 -715
  89. package/lib/session/dashboard.js +530 -0
  90. package/lib/session/dispatch.js +197 -171
  91. package/lib/session/files-pane.js +92 -45
  92. package/lib/session/find.js +94 -0
  93. package/lib/session/items.js +6 -17
  94. package/lib/session/lifecycle.js +420 -466
  95. package/lib/session/load.js +1 -14
  96. package/lib/session/navigation.js +4 -2
  97. package/lib/session/npm.js +403 -420
  98. package/lib/session/ops.js +5 -13
  99. package/lib/session/packages.js +143 -0
  100. package/lib/session/pointer.js +30 -14
  101. package/lib/session/progress.js +39 -30
  102. package/lib/session/review.js +1 -3
  103. package/lib/session/tasks.js +277 -236
  104. package/lib/session/templates.js +51 -59
  105. package/lib/session/terminal.js +85 -132
  106. package/lib/session/view.js +59 -80
  107. package/lib/session/watch.js +201 -212
  108. package/lib/session/workspace.js +455 -0
  109. package/lib/session.js +95 -161
  110. package/lib/update.js +44 -111
  111. package/lib/utilities.js +46 -88
  112. package/lib/workspace.js +166 -0
  113. package/lib/wrap.js +29 -55
  114. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const LIST_PANES = ['files', 'branches', 'commits', 'npm'];
3
+ const LIST_PANES = ['files', 'branches', 'commits', 'npm', 'packages'];
4
4
 
5
5
  const ACTIONS = {
6
6
  add: ['a'],
@@ -10,66 +10,121 @@ const ACTIONS = {
10
10
  commit: ['c'],
11
11
  prev: ['left', 'p', 'k'],
12
12
  next: ['right', 'n', 'j'],
13
- check: ['x', ' '],
13
+ check: [' '],
14
14
  layout: ['m'],
15
- feedback: ['f'],
15
+ feedback: [],
16
16
  tasks: ['t'],
17
17
  code: ['e'],
18
18
  branch: ['b'],
19
19
  file: ['f'],
20
20
  diff: ['d'],
21
- quit: ['q', 'ctrl-c'],
21
+ quit: ['ctrl-c'],
22
22
  };
23
23
  const ACTION_IDS = Object.keys(ACTIONS);
24
24
 
25
25
  const BRANCH_ACTIONS = {
26
- newBranch: ['n'],
27
- rebase: ['r'],
28
- drop: ['d'],
26
+ newBranch: ['insert'],
27
+ rebase: ['e'],
28
+ drop: ['delete'],
29
29
  pull: ['p'],
30
30
  push: ['s'],
31
31
  };
32
32
 
33
33
  const COMMIT_ACTIONS = {
34
- amend: ['a'],
35
- apply: ['a'],
36
- reword: ['r'],
37
- fixup: ['f'],
38
- drop: ['d'],
34
+ newCommit: ['insert'],
35
+ apply: ['p'],
36
+ reword: ['e'],
37
+ drop: ['delete'],
39
38
  view: ['v'],
40
- pull: ['p'],
41
- push: ['s'],
39
+ };
40
+
41
+ const PACKAGE_ACTIONS = {
42
+ packageNew: ['insert'],
43
+ packageDrop: ['delete'],
44
+ packageWanted: ['w'],
45
+ packageLatest: ['l'],
42
46
  };
43
47
 
44
48
  const NPM_ACTIONS = {
45
49
  npm: ['n'],
46
50
  npmEdit: ['e'],
47
- npmNew: ['n'],
48
- npmDrop: ['d'],
49
- npmLogs: ['c'],
51
+ npmNew: ['insert'],
52
+ npmDrop: ['delete'],
53
+ npmLogs: ['l'],
50
54
  npmStop: ['escape'],
51
55
  npmVerbose: ['v'],
52
56
  npmRerun: ['r'],
53
57
  };
54
58
 
59
+ const DASH_ACTIONS = {
60
+ dashFiles: ['f'],
61
+ dashDiffs: ['d'],
62
+ dashTasks: ['t'],
63
+ dashBranches: ['b'],
64
+ dashCommits: ['c'],
65
+ dashRun: ['r'],
66
+ dashNpm: ['n'],
67
+ };
68
+ const DASH_IDS = Object.keys(DASH_ACTIONS);
69
+ const DASH_BLOCKS = {
70
+ dashFiles: 'files',
71
+ dashDiffs: 'diffs',
72
+ dashCommits: 'commits',
73
+ dashBranches: 'branches',
74
+ dashNpm: 'npm',
75
+ dashRun: 'run',
76
+ dashTasks: 'tasks',
77
+ };
78
+ const DASH_ALLOWED = [...DASH_IDS, 'pull', 'push', 'quit', 'theme'];
79
+ const REPOS_ALLOWED = [
80
+ 'repoLeft',
81
+ 'repoRight',
82
+ 'repoUp',
83
+ 'repoDown',
84
+ 'open',
85
+ 'quit',
86
+ 'theme',
87
+ ];
88
+ const DASH_HIDDEN = ACTION_IDS.filter((id) => id !== 'quit');
89
+
55
90
  const ACTION_HOT = {
56
91
  prev: '←',
57
92
  next: '→',
93
+ drop: 'del',
94
+ newBranch: 'ins',
95
+ newCommit: 'ins',
96
+ feedback: 'q',
97
+ check: 'space',
98
+ theme: 'l',
99
+ npmNew: 'ins',
100
+ npmDrop: 'del',
58
101
  npmStop: 'esc',
102
+ packageNew: 'ins',
103
+ packageDrop: 'del',
59
104
  };
60
105
 
61
106
  const ACTION_LABEL = {
107
+ ...DASH_BLOCKS,
62
108
  revert: 'drop',
63
- check: 'x',
109
+ check: 'space',
110
+ theme: 'light',
64
111
  layout: 'mode',
65
112
  tasks: 'tasks',
66
113
  view: 'view',
67
114
  code: 'edit',
68
- newBranch: 'new',
115
+ reword: 'edit',
116
+ drop: 'delete',
117
+ newBranch: 'insert',
118
+ newCommit: 'insert',
119
+ feedback: 'quote',
69
120
  npmEdit: 'edit',
70
- npmNew: 'new',
121
+ npmNew: 'insert',
71
122
  npmDrop: 'delete',
72
123
  npmLogs: 'cleanup',
124
+ packageNew: 'insert',
125
+ packageDrop: 'delete',
126
+ packageWanted: 'wanted',
127
+ packageLatest: 'latest',
73
128
  npmStop: 'esc',
74
129
  npmVerbose: 'verbose',
75
130
  npmRerun: 're-run',
@@ -86,10 +141,9 @@ const DIFF_DISABLED = [
86
141
  'push',
87
142
  'file',
88
143
  'diff',
89
- 'ignore',
90
144
  ];
91
- const UNIT_DISABLED = [...DIFF_DISABLED, 'layout'];
92
- const FILES_DISABLED = ['layout', 'feedback', 'code'];
145
+ const UNIT_DISABLED = [...DIFF_DISABLED, 'layout', 'ignore'];
146
+ const FILES_DISABLED = ['layout', 'feedback'];
93
147
  const FILES_HIDDEN = [
94
148
  ...FILES_DISABLED,
95
149
  'check',
@@ -98,9 +152,11 @@ const FILES_HIDDEN = [
98
152
  'commit',
99
153
  'file',
100
154
  'diff',
155
+ 'tasks',
156
+ 'branch',
101
157
  ];
102
158
  const FILES_GIT_DISABLED = ['add', 'unstage', 'revert', 'ignore'];
103
- const FILES_TASKS_DISABLED = [...FILES_GIT_DISABLED, ...FILES_DISABLED];
159
+ const FILES_TASKS_DISABLED = [...FILES_GIT_DISABLED, ...FILES_DISABLED, 'code'];
104
160
  const TASKS_DISABLED = [
105
161
  'add',
106
162
  'unstage',
@@ -140,19 +196,44 @@ const NPM_DISABLED = [...BRANCHES_DISABLED, 'pull', 'push'];
140
196
  const isTasksTarget = (item) =>
141
197
  !!(item && (item.kind === 'tasks' || item.origin === 'task'));
142
198
 
199
+ const DIFF_MOVE_IDS = ['add', 'unstage', 'revert'];
200
+
201
+ const entryHasDiff = (entry) => {
202
+ if (!entry || entry.kind === 'tasks') return false;
203
+ const keys = [
204
+ 'added',
205
+ 'removed',
206
+ 'stagedAdded',
207
+ 'stagedRemoved',
208
+ 'unstagedAdded',
209
+ 'unstagedRemoved',
210
+ 'remaining',
211
+ ];
212
+ let total = 0;
213
+ for (const key of keys) total += entry[key] ?? 0;
214
+ return total > 0;
215
+ };
216
+
217
+ const lineHasDiff = (line) =>
218
+ !!line && (line.type === 'add' || line.type === 'del');
219
+
220
+ const withoutMoves = (off, hasDiff) => {
221
+ if (hasDiff) return off;
222
+ const next = off.slice();
223
+ for (const id of DIFF_MOVE_IDS) {
224
+ if (!next.includes(id)) next.push(id);
225
+ }
226
+ return next;
227
+ };
228
+
143
229
  const diffGitDisabled = (item) => {
144
230
  if (!item || isTasksTarget(item)) return [];
145
231
  if (item.origin === 'staged') return ['add'];
146
232
  return ['unstage'];
147
233
  };
148
234
 
149
- const BRANCH_REMOTE = ['pull', 'push'];
150
-
151
- const branchGitDisabled = (item) => {
152
- const off = item && !item.current ? [] : ['rebase', 'drop'];
153
- if (!item || !item.current) return [...off, ...BRANCH_REMOTE];
154
- return off;
155
- };
235
+ const branchGitDisabled = (item) =>
236
+ item && !item.current ? [] : ['rebase', 'drop'];
156
237
 
157
238
  const isFixupCommit = (item) =>
158
239
  `${item && item.subject ? item.subject : ''}`.startsWith('fixup!');
@@ -170,25 +251,43 @@ const commitWriteDisabled = (item) => {
170
251
  return ['amend', 'apply'];
171
252
  };
172
253
 
254
+ const commitChord = (item) => {
255
+ if (!item || item.pending || !item.sha) return 'commit';
256
+ if (item.head) return 'amend';
257
+ return 'fixup';
258
+ };
259
+
173
260
  const commitGitDisabled = (item) => {
174
261
  const off = [...commitWriteDisabled(item)];
175
262
  if (!isFixupCommit(item)) off.push('apply');
176
- if (item && item.canCommit === true) return off;
177
- return [...off, 'commit', 'fixup'];
263
+ const chord = commitChord(item);
264
+ const ready = item && item.canCommit === true;
265
+ if (chord === 'amend') return off;
266
+ if (!ready) off.push('commit');
267
+ return off;
178
268
  };
179
269
 
180
270
  const disabledActions = (pane, item) => {
181
271
  const onTodos = isTasksTarget(item);
182
- if (pane === 'files') return onTodos ? FILES_TASKS_DISABLED : FILES_DISABLED;
183
- if (pane === 'unit') return [...UNIT_DISABLED, ...diffGitDisabled(item)];
272
+ if (pane === 'dashboard' || pane === 'repos') return [];
273
+ if (pane === 'files') {
274
+ const base = onTodos ? FILES_TASKS_DISABLED : FILES_DISABLED;
275
+ if (onTodos) return base;
276
+ return withoutMoves(base, entryHasDiff(item));
277
+ }
278
+ if (pane === 'unit') {
279
+ const off = [...UNIT_DISABLED, ...diffGitDisabled(item)];
280
+ const onDiff = !item || item.lineDiff !== false;
281
+ return withoutMoves(off, onDiff);
282
+ }
184
283
  if (pane === 'branches') {
185
284
  return [...BRANCHES_DISABLED, ...branchGitDisabled(item)];
186
285
  }
187
286
  if (pane === 'commits') {
188
287
  return [...COMMITS_DISABLED, ...commitWriteDisabled(item)];
189
288
  }
190
- if (pane === 'npm') return NPM_DISABLED;
191
- if (onTodos) return TASKS_DISABLED;
289
+ if (pane === 'npm' || pane === 'packages') return NPM_DISABLED;
290
+ if (pane === 'tasks' || onTodos) return TASKS_DISABLED;
192
291
  return [...DIFF_DISABLED, ...diffGitDisabled(item)];
193
292
  };
194
293
 
@@ -223,25 +322,38 @@ const keysForActions = (actions) => {
223
322
  };
224
323
 
225
324
  const PANE_ONLY = ['branch', 'file', 'diff'];
226
- const FILES_KEYS = keysForActions({
227
- branch: ACTIONS.branch,
228
- pull: BRANCH_ACTIONS.pull,
229
- push: BRANCH_ACTIONS.push,
230
- npm: NPM_ACTIONS.npm,
231
- });
325
+ const REVIEW_DROP = { d: 'revert' };
326
+ const DIFF_KEYS = { ...REVIEW_DROP, q: 'feedback' };
232
327
  const BRANCH_KEYS = keysForActions(BRANCH_ACTIONS);
233
- const COMMIT_KEYS = keysForActions(COMMIT_ACTIONS);
328
+ const COMMIT_KEYS = { ...keysForActions(COMMIT_ACTIONS), s: 'push' };
234
329
  const NPM_KEYS = {
235
330
  e: 'npmEdit',
236
- n: 'npmNew',
237
- d: 'npmDrop',
238
- c: 'npmLogs',
331
+ insert: 'npmNew',
332
+ delete: 'npmDrop',
333
+ l: 'npmLogs',
239
334
  };
335
+ const DASH_KEYS = keysForActions(DASH_ACTIONS);
336
+ const SCREEN_KEYS = DASH_KEYS;
240
337
  const PANE_KEYS = {
241
- files: FILES_KEYS,
338
+ dashboard: { ...DASH_KEYS, p: 'pull', s: 'push' },
339
+ files: REVIEW_DROP,
340
+ diff: DIFF_KEYS,
341
+ unit: DIFF_KEYS,
242
342
  branches: BRANCH_KEYS,
243
343
  commits: COMMIT_KEYS,
244
344
  npm: NPM_KEYS,
345
+ packages: keysForActions(PACKAGE_ACTIONS),
346
+ tasks: { delete: 'drop' },
347
+ repos: {
348
+ left: 'repoLeft',
349
+ right: 'repoRight',
350
+ up: 'repoUp',
351
+ down: 'repoDown',
352
+ k: 'repoUp',
353
+ j: 'repoDown',
354
+ p: 'repoLeft',
355
+ n: 'repoRight',
356
+ },
245
357
  };
246
358
 
247
359
  const KEY_TO_ACTION = {
@@ -254,16 +366,13 @@ const KEY_TO_ACTION = {
254
366
  ...HIDDEN_KEYS,
255
367
  };
256
368
 
257
- const actionFromKey = (key, pane, fileScope) => {
369
+ const actionFromKey = (key, pane) => {
258
370
  if (LIST_PANES.includes(pane) && (key === 'left' || key === 'right')) {
259
371
  return null;
260
372
  }
261
373
  const paneKeys = PANE_KEYS[pane];
262
374
  if (paneKeys && paneKeys[key]) return paneKeys[key];
263
- if (pane === 'files') {
264
- if (key === 'f' && fileScope !== 'file') return 'file';
265
- if (key === 'd' && fileScope === 'file') return 'diff';
266
- }
375
+ if (pane && SCREEN_KEYS[key]) return SCREEN_KEYS[key];
267
376
  return KEY_TO_ACTION[key] ?? null;
268
377
  };
269
378
 
@@ -272,11 +381,11 @@ const actionKeys = (id) =>
272
381
  BRANCH_ACTIONS[id] ??
273
382
  COMMIT_ACTIONS[id] ??
274
383
  NPM_ACTIONS[id] ??
384
+ PACKAGE_ACTIONS[id] ??
385
+ DASH_ACTIONS[id] ??
275
386
  [];
276
387
 
277
- const actionHot = (id) => ACTION_HOT[id] ?? actionKeys(id)[0];
278
-
279
- const actionLetter = actionHot;
388
+ const actionLetter = (id) => ACTION_HOT[id] ?? actionKeys(id)[0];
280
389
 
281
390
  const buttonWord = (id) => {
282
391
  const word = ACTION_LABEL[id] ?? ACTION_HOT[id] ?? id;
@@ -333,6 +442,22 @@ const CONFIRM = {
333
442
  escape: 'cancel',
334
443
  },
335
444
  },
445
+ confirmCommit: {
446
+ choices: [
447
+ { letter: 'esc', label: 'esc cancel', lead: ' ' },
448
+ { letter: 'c', label: 'commit', lead: ' ' },
449
+ { letter: 'a', label: 'amend', lead: ' ' },
450
+ { letter: 'f', label: 'fixup', lead: ' ' },
451
+ ],
452
+ prefix: ' what do you want to do?',
453
+ keys: {
454
+ esc: 'cancel',
455
+ escape: 'cancel',
456
+ c: 'commit',
457
+ a: 'amend',
458
+ f: 'fixup',
459
+ },
460
+ },
336
461
  };
337
462
 
338
463
  const CONFIRM_MODE = Object.keys(CONFIRM);
@@ -344,13 +469,6 @@ const confirmKey = (mode, key) => {
344
469
  return spec.keys[norm] ?? null;
345
470
  };
346
471
 
347
- const applyConfirm = (mode, key, handlers) => {
348
- const action = confirmKey(mode, key);
349
- if (!action) return;
350
- const handler = handlers[action];
351
- if (handler) handler();
352
- };
353
-
354
472
  const confirmPrefix = (spec, view) => {
355
473
  if (typeof spec.prefix === 'function') return spec.prefix(view);
356
474
  return spec.prefix ?? '';
@@ -361,6 +479,11 @@ const promptFromChoices = (choices) =>
361
479
 
362
480
  module.exports = {
363
481
  LIST_PANES,
482
+ DASH_IDS,
483
+ DASH_BLOCKS,
484
+ DASH_ALLOWED,
485
+ DASH_HIDDEN,
486
+ REPOS_ALLOWED,
364
487
  ACTIONS,
365
488
  ACTION_IDS,
366
489
  BRANCH_ACTIONS,
@@ -376,18 +499,19 @@ module.exports = {
376
499
  COMMITS_DISABLED,
377
500
  NPM_DISABLED,
378
501
  disabledActions,
502
+ entryHasDiff,
503
+ lineHasDiff,
504
+ withoutMoves,
379
505
  diffGitDisabled,
380
506
  branchGitDisabled,
381
507
  commitGitDisabled,
382
508
  isFixupCommit,
383
509
  actionFromKey,
384
- actionHot,
385
510
  actionLetter,
386
511
  buttonWord,
387
512
  CONFIRM,
388
513
  CONFIRM_MODE,
389
514
  confirmKey,
390
- applyConfirm,
391
515
  confirmPrefix,
392
516
  promptFromChoices,
393
517
  };