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.
Files changed (89) hide show
  1. package/CHANGELOG.md +27 -1
  2. package/README.md +8 -4
  3. package/bin/reslop.js +4 -2
  4. package/lib/api.js +2 -1
  5. package/lib/capabilities.js +0 -4
  6. package/lib/cli.js +19 -10
  7. package/lib/clipboard.js +45 -4
  8. package/lib/deps-diff.js +61 -118
  9. package/lib/deps.js +166 -235
  10. package/lib/detect.js +4 -2
  11. package/lib/diff/align.js +2 -1
  12. package/lib/diff/diff.js +6 -3
  13. package/lib/diff/display.js +2 -1
  14. package/lib/diff/inline.js +68 -2
  15. package/lib/diff/patch.js +2 -1
  16. package/lib/diff/unit.js +15 -30
  17. package/lib/editor.js +91 -13
  18. package/lib/files.js +54 -27
  19. package/lib/git-branches.js +107 -154
  20. package/lib/git-deps.js +78 -155
  21. package/lib/git-worktree.js +508 -0
  22. package/lib/git.js +23 -580
  23. package/lib/github.js +9 -8
  24. package/lib/gitlab.js +5 -4
  25. package/lib/highlight/bash.js +2 -1
  26. package/lib/highlight/core.js +11 -0
  27. package/lib/highlight/css.js +2 -1
  28. package/lib/highlight/csv.js +2 -1
  29. package/lib/highlight/dot.js +3 -12
  30. package/lib/highlight/html.js +2 -1
  31. package/lib/highlight/json.js +2 -1
  32. package/lib/highlight/log.js +5 -11
  33. package/lib/highlight/txt.js +3 -12
  34. package/lib/highlight.js +2 -1
  35. package/lib/keys.js +22 -12
  36. package/lib/manifest.js +4 -6
  37. package/lib/npm-commands.js +82 -24
  38. package/lib/remote.js +21 -20
  39. package/lib/render/branches.js +9 -27
  40. package/lib/render/chrome.js +109 -35
  41. package/lib/render/commits.js +216 -216
  42. package/lib/render/diff.js +160 -47
  43. package/lib/render/files.js +9 -26
  44. package/lib/render/frame.js +97 -118
  45. package/lib/render/notes.js +74 -26
  46. package/lib/render/npm.js +104 -30
  47. package/lib/render/present.js +2 -1
  48. package/lib/render/primitives.js +128 -52
  49. package/lib/render/render.js +2 -1
  50. package/lib/render/unit.js +17 -11
  51. package/lib/report-model.js +6 -4
  52. package/lib/report-parse.js +8 -14
  53. package/lib/report-render.js +38 -21
  54. package/lib/report-run.js +12 -11
  55. package/lib/report-test.js +45 -51
  56. package/lib/report-tools.js +44 -25
  57. package/lib/review-merge.js +102 -131
  58. package/lib/review.js +69 -78
  59. package/lib/select.js +52 -0
  60. package/lib/session/actions.js +72 -87
  61. package/lib/session/branches.js +18 -52
  62. package/lib/session/change-actions.js +175 -147
  63. package/lib/session/commit.js +65 -61
  64. package/lib/session/compose.js +152 -83
  65. package/lib/session/dispatch.js +53 -46
  66. package/lib/session/edit-click.js +57 -0
  67. package/lib/session/files-pane.js +30 -51
  68. package/lib/session/items.js +73 -90
  69. package/lib/session/lifecycle.js +37 -98
  70. package/lib/session/load.js +52 -57
  71. package/lib/session/navigation.js +105 -95
  72. package/lib/session/npm.js +205 -71
  73. package/lib/session/ops.js +200 -45
  74. package/lib/session/pointer.js +33 -8
  75. package/lib/session/progress.js +9 -6
  76. package/lib/session/review.js +35 -53
  77. package/lib/session/tasks.js +292 -0
  78. package/lib/session/terminal.js +17 -19
  79. package/lib/session/unit.js +3 -4
  80. package/lib/session/update.js +76 -96
  81. package/lib/session/view.js +45 -16
  82. package/lib/session/watch.js +47 -27
  83. package/lib/session.js +66 -97
  84. package/lib/source.js +6 -3
  85. package/lib/update.js +5 -13
  86. package/lib/utilities.js +25 -3
  87. package/lib/wrap.js +18 -1
  88. package/package.json +1 -1
  89. package/lib/session/todos.js +0 -293
@@ -1,16 +1,19 @@
1
1
  'use strict';
2
2
 
3
+ const LIST_PANES = ['files', 'branches', 'commits', 'npm'];
4
+
3
5
  const ACTIONS = {
4
6
  add: ['a'],
5
7
  unstage: ['u'],
6
8
  revert: ['d'],
9
+ ignore: ['i'],
7
10
  commit: ['c'],
8
11
  prev: ['left', 'p', 'k'],
9
12
  next: ['right', 'n', 'j'],
10
13
  check: ['x', ' '],
11
14
  layout: ['m'],
12
15
  feedback: ['f'],
13
- todo: ['t'],
16
+ tasks: ['t'],
14
17
  code: ['e'],
15
18
  branch: ['b'],
16
19
  file: ['f'],
@@ -42,7 +45,10 @@ const NPM_ACTIONS = {
42
45
  npm: ['n'],
43
46
  npmEdit: ['e'],
44
47
  npmNew: ['n'],
48
+ npmDrop: ['d'],
49
+ npmLogs: ['c'],
45
50
  npmStop: ['escape'],
51
+ npmVerbose: ['v'],
46
52
  npmRerun: ['r'],
47
53
  };
48
54
 
@@ -56,12 +62,16 @@ const ACTION_LABEL = {
56
62
  revert: 'drop',
57
63
  check: 'x',
58
64
  layout: 'mode',
65
+ tasks: 'tasks',
59
66
  view: 'view',
60
67
  code: 'edit',
61
68
  newBranch: 'new',
62
69
  npmEdit: 'edit',
63
70
  npmNew: 'new',
71
+ npmDrop: 'delete',
72
+ npmLogs: 'cleanup',
64
73
  npmStop: 'esc',
74
+ npmVerbose: 'verbose',
65
75
  npmRerun: 're-run',
66
76
  quit: 'q',
67
77
  prev: '←',
@@ -76,6 +86,7 @@ const DIFF_DISABLED = [
76
86
  'push',
77
87
  'file',
78
88
  'diff',
89
+ 'ignore',
79
90
  ];
80
91
  const UNIT_DISABLED = [...DIFF_DISABLED, 'layout'];
81
92
  const FILES_DISABLED = ['layout', 'feedback', 'code'];
@@ -88,16 +99,17 @@ const FILES_HIDDEN = [
88
99
  'file',
89
100
  'diff',
90
101
  ];
91
- const FILES_GIT_DISABLED = ['add', 'unstage', 'revert'];
92
- const FILES_TODO_DISABLED = [...FILES_GIT_DISABLED, ...FILES_DISABLED];
93
- const TODO_DISABLED = [
102
+ const FILES_GIT_DISABLED = ['add', 'unstage', 'revert', 'ignore'];
103
+ const FILES_TASKS_DISABLED = [...FILES_GIT_DISABLED, ...FILES_DISABLED];
104
+ const TASKS_DISABLED = [
94
105
  'add',
95
106
  'unstage',
96
107
  'revert',
108
+ 'ignore',
97
109
  'commit',
98
110
  'layout',
99
111
  'feedback',
100
- 'todo',
112
+ 'tasks',
101
113
  'code',
102
114
  'branch',
103
115
  'file',
@@ -109,10 +121,11 @@ const BRANCHES_DISABLED = [
109
121
  'add',
110
122
  'unstage',
111
123
  'revert',
124
+ 'ignore',
112
125
  'commit',
113
126
  'layout',
114
127
  'feedback',
115
- 'todo',
128
+ 'tasks',
116
129
  'code',
117
130
  'check',
118
131
  'branch',
@@ -121,45 +134,14 @@ const BRANCHES_DISABLED = [
121
134
  'prev',
122
135
  'next',
123
136
  ];
124
- const COMMITS_DISABLED = [
125
- 'add',
126
- 'unstage',
127
- 'revert',
128
- 'layout',
129
- 'feedback',
130
- 'todo',
131
- 'code',
132
- 'check',
133
- 'branch',
134
- 'file',
135
- 'diff',
136
- 'prev',
137
- 'next',
138
- ];
139
- const NPM_DISABLED = [
140
- 'add',
141
- 'unstage',
142
- 'revert',
143
- 'commit',
144
- 'layout',
145
- 'feedback',
146
- 'todo',
147
- 'code',
148
- 'check',
149
- 'branch',
150
- 'file',
151
- 'diff',
152
- 'prev',
153
- 'next',
154
- 'pull',
155
- 'push',
156
- ];
137
+ const COMMITS_DISABLED = BRANCHES_DISABLED.filter((id) => id !== 'commit');
138
+ const NPM_DISABLED = [...BRANCHES_DISABLED, 'pull', 'push'];
157
139
 
158
- const isTodosTarget = (item) =>
159
- !!(item && (item.kind === 'todos' || item.origin === 'todo'));
140
+ const isTasksTarget = (item) =>
141
+ !!(item && (item.kind === 'tasks' || item.origin === 'task'));
160
142
 
161
143
  const diffGitDisabled = (item) => {
162
- if (!item || isTodosTarget(item)) return [];
144
+ if (!item || isTasksTarget(item)) return [];
163
145
  if (item.origin === 'staged') return ['add'];
164
146
  return ['unstage'];
165
147
  };
@@ -176,8 +158,16 @@ const isFixupCommit = (item) =>
176
158
  `${item && item.subject ? item.subject : ''}`.startsWith('fixup!');
177
159
 
178
160
  const commitWriteDisabled = (item) => {
179
- if (!item || !item.sha) return ['amend', 'apply', 'reword', 'fixup', 'drop'];
180
- return [];
161
+ const pending = Boolean(item && item.pending);
162
+ const unstaged = Boolean(item && item.unstagedCurrent);
163
+ if (!item || !item.sha) {
164
+ const off = ['reword', 'fixup', 'drop'];
165
+ if (pending) return off;
166
+ return ['amend', 'apply', ...off];
167
+ }
168
+ if (unstaged) return [];
169
+ if (isFixupCommit(item)) return ['amend'];
170
+ return ['amend', 'apply'];
181
171
  };
182
172
 
183
173
  const commitGitDisabled = (item) => {
@@ -188,8 +178,8 @@ const commitGitDisabled = (item) => {
188
178
  };
189
179
 
190
180
  const disabledActions = (pane, item) => {
191
- const onTodos = isTodosTarget(item);
192
- if (pane === 'files') return onTodos ? FILES_TODO_DISABLED : FILES_DISABLED;
181
+ const onTodos = isTasksTarget(item);
182
+ if (pane === 'files') return onTodos ? FILES_TASKS_DISABLED : FILES_DISABLED;
193
183
  if (pane === 'unit') return [...UNIT_DISABLED, ...diffGitDisabled(item)];
194
184
  if (pane === 'branches') {
195
185
  return [...BRANCHES_DISABLED, ...branchGitDisabled(item)];
@@ -198,7 +188,7 @@ const disabledActions = (pane, item) => {
198
188
  return [...COMMITS_DISABLED, ...commitWriteDisabled(item)];
199
189
  }
200
190
  if (pane === 'npm') return NPM_DISABLED;
201
- if (onTodos) return TODO_DISABLED;
191
+ if (onTodos) return TASKS_DISABLED;
202
192
  return [...DIFF_DISABLED, ...diffGitDisabled(item)];
203
193
  };
204
194
 
@@ -220,30 +210,33 @@ const SCROLL = {
220
210
  home: 'home',
221
211
  end: 'end',
222
212
  enter: 'open',
223
- backspace: 'removeTodo',
224
- delete: 'removeTodo',
213
+ backspace: 'removeTask',
214
+ delete: 'removeTask',
215
+ };
216
+
217
+ const keysForActions = (actions) => {
218
+ const keys = {};
219
+ for (const [id, shortcuts] of Object.entries(actions)) {
220
+ for (const key of shortcuts) keys[key] = id;
221
+ }
222
+ return keys;
225
223
  };
226
224
 
227
- const KEY_TO_ACTION = {};
228
225
  const PANE_ONLY = ['branch', 'file', 'diff'];
229
- const FILES_KEYS = {};
230
- for (const key of ACTIONS.branch) FILES_KEYS[key] = 'branch';
231
- for (const id of BRANCH_REMOTE) {
232
- for (const key of BRANCH_ACTIONS[id]) FILES_KEYS[key] = id;
233
- }
234
- const BRANCH_KEYS = {};
235
- for (const id of Object.keys(BRANCH_ACTIONS)) {
236
- for (const key of BRANCH_ACTIONS[id]) BRANCH_KEYS[key] = id;
237
- }
238
- const COMMIT_KEYS = {};
239
- for (const id of Object.keys(COMMIT_ACTIONS)) {
240
- for (const key of COMMIT_ACTIONS[id]) COMMIT_KEYS[key] = id;
241
- }
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
+ });
232
+ const BRANCH_KEYS = keysForActions(BRANCH_ACTIONS);
233
+ const COMMIT_KEYS = keysForActions(COMMIT_ACTIONS);
242
234
  const NPM_KEYS = {
243
235
  e: 'npmEdit',
244
236
  n: 'npmNew',
237
+ d: 'npmDrop',
238
+ c: 'npmLogs',
245
239
  };
246
- FILES_KEYS.n = 'npm';
247
240
  const PANE_KEYS = {
248
241
  files: FILES_KEYS,
249
242
  branches: BRANCH_KEYS,
@@ -251,23 +244,20 @@ const PANE_KEYS = {
251
244
  npm: NPM_KEYS,
252
245
  };
253
246
 
254
- for (const id of ACTION_IDS) {
255
- if (PANE_ONLY.includes(id)) continue;
256
- for (const key of ACTIONS[id]) KEY_TO_ACTION[key] = id;
257
- }
258
-
259
- for (const key of Object.keys(SCROLL)) KEY_TO_ACTION[key] = SCROLL[key];
260
- for (const key of Object.keys(HIDDEN_KEYS)) {
261
- KEY_TO_ACTION[key] = HIDDEN_KEYS[key];
262
- }
247
+ const KEY_TO_ACTION = {
248
+ ...keysForActions(
249
+ Object.fromEntries(
250
+ Object.entries(ACTIONS).filter(([id]) => !PANE_ONLY.includes(id)),
251
+ ),
252
+ ),
253
+ ...SCROLL,
254
+ ...HIDDEN_KEYS,
255
+ };
263
256
 
264
257
  const actionFromKey = (key, pane, fileScope) => {
265
- const listPane =
266
- pane === 'files' ||
267
- pane === 'branches' ||
268
- pane === 'commits' ||
269
- pane === 'npm';
270
- if (listPane && (key === 'left' || key === 'right')) return null;
258
+ if (LIST_PANES.includes(pane) && (key === 'left' || key === 'right')) {
259
+ return null;
260
+ }
271
261
  const paneKeys = PANE_KEYS[pane];
272
262
  if (paneKeys && paneKeys[key]) return paneKeys[key];
273
263
  if (pane === 'files') {
@@ -370,32 +360,27 @@ const promptFromChoices = (choices) =>
370
360
  choices.map((choice) => `${choice.lead}${choice.label}`).join('');
371
361
 
372
362
  module.exports = {
363
+ LIST_PANES,
373
364
  ACTIONS,
374
365
  ACTION_IDS,
375
366
  BRANCH_ACTIONS,
376
367
  COMMIT_ACTIONS,
377
- NPM_ACTIONS,
378
- ACTION_HOT,
379
- ACTION_LABEL,
380
368
  DIFF_DISABLED,
381
369
  UNIT_DISABLED,
382
370
  FILES_DISABLED,
383
371
  FILES_HIDDEN,
384
372
  FILES_GIT_DISABLED,
385
- FILES_TODO_DISABLED,
386
- TODO_DISABLED,
373
+ FILES_TASKS_DISABLED,
374
+ TASKS_DISABLED,
387
375
  BRANCHES_DISABLED,
388
376
  COMMITS_DISABLED,
389
377
  NPM_DISABLED,
390
- SCROLL,
391
- PANE_ONLY,
392
378
  disabledActions,
393
379
  diffGitDisabled,
394
380
  branchGitDisabled,
395
381
  commitGitDisabled,
396
382
  isFixupCommit,
397
383
  actionFromKey,
398
- actionKeys,
399
384
  actionHot,
400
385
  actionLetter,
401
386
  buttonWord,
@@ -1,8 +1,10 @@
1
1
  'use strict';
2
2
 
3
- const { stateView } = require('./accessors.js');
3
+ const accessors = require('./accessors.js');
4
+ const { stateView } = accessors;
4
5
 
5
- const { pickRepoWrite } = require('./ops.js');
6
+ const ops = require('./ops.js');
7
+ const { pickRepoWrite } = ops;
6
8
 
7
9
  const selectedBranch = (api) => {
8
10
  const cursor = api.ui.nav.branchCursor;
@@ -45,10 +47,12 @@ const onBranch = (api) => {
45
47
  return;
46
48
  }
47
49
  const current = api.state.branches.findIndex((entry) => entry.current);
48
- api.ui.nav.branchCursor = current < 0 ? 0 : current;
49
- api.ui.nav.pane = 'branches';
50
+ const nav = api.ui.nav;
51
+ nav.branchCursor = current < 0 ? 0 : current;
52
+ nav.pane = 'branches';
53
+ nav.resetListScroll('branches');
50
54
  api.ui.status = '';
51
- api.ui.nav.clearSelection();
55
+ nav.clearSelection();
52
56
  };
53
57
 
54
58
  const onBranchMove = (api, delta) => {
@@ -95,12 +99,6 @@ const onCheckoutBranch = (api) => {
95
99
  if (!api.ui.status) api.ui.status = done;
96
100
  };
97
101
 
98
- const rebaseAsync = (api, onto, done, write) => {
99
- const run = (top) => write(top, onto);
100
- const after = () => refreshAfterWrite(api, { doneStatus: done });
101
- return void api.ui.ops.runBusy('rebasing', done, run, after);
102
- };
103
-
104
102
  const onRebaseBranch = (api) => {
105
103
  if (api.ui.nav.pane !== 'branches') return;
106
104
  if (!api.ui.commits.canCommit()) return;
@@ -108,17 +106,9 @@ const onRebaseBranch = (api) => {
108
106
  if (!entry || entry.current) return;
109
107
  const onto = entry.name;
110
108
  const done = `rebased onto ${onto}`;
111
- const uiOpen = api.ui.uiOpen;
112
- const picked = pickRepoWrite(api.ui.repo, 'rebase', uiOpen);
113
- if (picked.async) {
114
- return void rebaseAsync(api, onto, done, picked.write);
115
- }
116
- const ok = api.ui.ops.runRepo(done, (top) => {
117
- api.ui.repo.rebase(top, onto);
118
- });
119
- if (!ok) return;
120
- refreshAfterWrite(api);
121
- if (!api.ui.status) api.ui.status = done;
109
+ api.ui.ops.runWrite('rebase', [onto], 'rebasing', done, (extra) =>
110
+ refreshAfterWrite(api, extra),
111
+ );
122
112
  };
123
113
 
124
114
  const onDropBranch = (api) => {
@@ -137,29 +127,15 @@ const cancelDropBranch = (api) => {
137
127
  api.ui.status = '';
138
128
  };
139
129
 
140
- const dropAsync = (api, name, done, write) => {
141
- const run = (top) => write(top, name);
142
- const after = () => refreshAfterWrite(api, { doneStatus: done });
143
- return void api.ui.ops.runBusy('dropping', done, run, after);
144
- };
145
-
146
130
  const confirmDropBranch = (api) => {
147
131
  const name = api.state.dropName;
148
132
  api.ui.mode = 'review';
149
133
  api.state.dropName = '';
150
134
  if (!name) return;
151
135
  const done = `dropped ${name}`;
152
- const uiOpen = api.ui.uiOpen;
153
- const picked = pickRepoWrite(api.ui.repo, 'drop', uiOpen);
154
- if (picked.async) {
155
- return void dropAsync(api, name, done, picked.write);
156
- }
157
- const ok = api.ui.ops.runRepo(done, (top) => {
158
- api.ui.repo.drop(top, name);
159
- });
160
- if (!ok) return;
161
- refreshAfterWrite(api);
162
- if (!api.ui.status) api.ui.status = done;
136
+ api.ui.ops.runWrite('drop', [name], 'dropping', done, (extra) =>
137
+ refreshAfterWrite(api, extra),
138
+ );
163
139
  };
164
140
 
165
141
  const onNewBranch = (api) => {
@@ -201,19 +177,9 @@ const finishCreateBranch = (api) => {
201
177
 
202
178
  const onPull = (api) => {
203
179
  if (!api.ui.commits.canCommit()) return;
204
- const repo = api.ui.repo;
205
- const picked = pickRepoWrite(repo, 'pull', api.ui.uiOpen);
206
- if (picked.async) {
207
- const after = () => refreshAfterWrite(api);
208
- const write = (top) => picked.write(top);
209
- return void api.ui.ops.runBusy('pulling', 'pulled', write, after);
210
- }
211
- const ok = api.ui.ops.runRepo('pulled', (top) => {
212
- repo.pull(top);
213
- });
214
- if (!ok) return;
215
- refreshAfterWrite(api);
216
- if (!api.ui.status) api.ui.status = 'pulled';
180
+ api.ui.ops.runWrite('pull', [], 'pulling', 'pulled', (extra) =>
181
+ refreshAfterWrite(api, extra),
182
+ );
217
183
  };
218
184
 
219
185
  const startPush = (api, force) => {