reslop 0.1.9 → 0.2.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.
Files changed (96) hide show
  1. package/CHANGELOG.md +25 -1
  2. package/README.md +3 -1
  3. package/bin/reslop.js +2 -2
  4. package/lib/ansi.js +148 -5
  5. package/lib/api.js +4 -2
  6. package/lib/capabilities.js +13 -14
  7. package/lib/cli.js +38 -49
  8. package/lib/clipboard.js +1 -1
  9. package/lib/{deps/changes.js → deps-diff.js} +309 -19
  10. package/lib/deps.js +498 -29
  11. package/lib/detect.js +1 -7
  12. package/lib/diff/align.js +7 -10
  13. package/lib/diff/diff.js +53 -0
  14. package/lib/diff/display.js +5 -4
  15. package/lib/diff/inline.js +26 -21
  16. package/lib/diff/items.js +6 -4
  17. package/lib/diff/patch.js +1 -3
  18. package/lib/diff/unit.js +392 -0
  19. package/lib/files.js +5 -8
  20. package/lib/{git/branches.js → git-branches.js} +191 -11
  21. package/lib/{git/dependencies.js → git-deps.js} +111 -38
  22. package/lib/git-reword-todo.js +20 -0
  23. package/lib/git.js +606 -68
  24. package/lib/github.js +28 -197
  25. package/lib/gitlab.js +24 -195
  26. package/lib/highlight/bash.js +1 -3
  27. package/lib/highlight/css.js +1 -3
  28. package/lib/highlight/js.js +11 -14
  29. package/lib/highlight.js +6 -9
  30. package/lib/keys.js +14 -8
  31. package/lib/manifest.js +330 -0
  32. package/lib/remote.js +374 -0
  33. package/lib/render/branches.js +18 -100
  34. package/lib/render/chrome.js +71 -14
  35. package/lib/render/commits.js +69 -60
  36. package/lib/render/diff.js +20 -20
  37. package/lib/render/files.js +6 -34
  38. package/lib/render/frame.js +36 -13
  39. package/lib/render/notes.js +26 -8
  40. package/lib/render/primitives.js +99 -11
  41. package/lib/{render.js → render/render.js} +8 -8
  42. package/lib/render/unit.js +41 -0
  43. package/lib/review-merge.js +270 -0
  44. package/lib/review.js +782 -14
  45. package/lib/select.js +5 -10
  46. package/lib/session/accessors.js +9 -1
  47. package/lib/session/actions.js +61 -18
  48. package/lib/session/branches.js +116 -128
  49. package/lib/session/change-actions.js +202 -123
  50. package/lib/session/commit.js +201 -115
  51. package/lib/session/compose.js +181 -15
  52. package/lib/session/dispatch.js +110 -60
  53. package/lib/session/files-pane.js +156 -148
  54. package/lib/session/items.js +22 -30
  55. package/lib/session/lifecycle.js +151 -54
  56. package/lib/session/load.js +19 -33
  57. package/lib/session/navigation.js +12 -1
  58. package/lib/session/ops.js +28 -41
  59. package/lib/session/pointer.js +57 -57
  60. package/lib/session/review.js +23 -37
  61. package/lib/session/terminal.js +6 -12
  62. package/lib/session/todos.js +37 -13
  63. package/lib/session/unit.js +208 -0
  64. package/lib/session/update.js +33 -46
  65. package/lib/session/view.js +78 -9
  66. package/lib/session/watch.js +128 -24
  67. package/lib/session.js +22 -246
  68. package/lib/source.js +3 -3
  69. package/lib/update.js +40 -75
  70. package/lib/{git/proc.js → utilities.js} +75 -11
  71. package/lib/wrap.js +1 -3
  72. package/package.json +2 -2
  73. package/lib/deps/items.js +0 -134
  74. package/lib/deps/manifest.js +0 -152
  75. package/lib/deps/merge.js +0 -120
  76. package/lib/deps/proposals.js +0 -164
  77. package/lib/deps/reports.js +0 -180
  78. package/lib/deps/rows.js +0 -176
  79. package/lib/deps/scan.js +0 -138
  80. package/lib/deps/usage.js +0 -68
  81. package/lib/deps/versions.js +0 -119
  82. package/lib/diff.js +0 -33
  83. package/lib/git/changes.js +0 -164
  84. package/lib/git/read.js +0 -253
  85. package/lib/git/run.js +0 -100
  86. package/lib/npm/commands.js +0 -100
  87. package/lib/remote/changes.js +0 -37
  88. package/lib/remote/headers.js +0 -36
  89. package/lib/remote/http.js +0 -122
  90. package/lib/remote/notes.js +0 -94
  91. package/lib/review/format.js +0 -434
  92. package/lib/review/storage.js +0 -150
  93. package/lib/review/store.js +0 -178
  94. package/lib/review/templates.js +0 -49
  95. package/lib/session/origins.js +0 -7
  96. package/lib/sys.js +0 -84
@@ -1,261 +1,257 @@
1
1
  'use strict';
2
2
 
3
+ const { stateView } = require('./accessors.js');
4
+
3
5
  const { pickRepoWrite } = require('./ops.js');
4
6
 
5
7
  const selectedBranch = (api) => {
6
- const cursor = api.options.nav.branchCursor;
8
+ const cursor = api.ui.nav.branchCursor;
7
9
  return api.state.branches[cursor];
8
10
  };
9
11
 
10
12
  const refreshBranchList = (api) => {
11
- const repo = api.options.repo();
13
+ const repo = api.ui.repo;
12
14
  if (!repo.listBranches) return;
13
15
  try {
14
- api.state.branches = repo.listBranches(api.options.top());
16
+ api.state.branches = repo.listBranches(api.ui.top);
15
17
  } catch (error) {
16
- api.options.setStatus(error.message);
18
+ api.ui.status = error.message;
17
19
  return;
18
20
  }
19
21
  const last = api.state.branches.length - 1;
20
- const nav = api.options.nav;
22
+ const nav = api.ui.nav;
21
23
  if (nav.branchCursor > last) nav.branchCursor = Math.max(0, last);
22
24
  };
23
25
 
24
26
  const refreshAfterWrite = (api, extra = {}) => {
25
27
  refreshBranchList(api);
26
- api.options.refreshFromRepo({ keepEmpty: true, ...extra });
28
+ api.ui.commits.refresh();
29
+ api.ui.refreshFromRepo({ keepEmpty: true, ...extra });
27
30
  };
28
31
 
29
32
  const onBranch = (api) => {
30
- if (api.options.getMode() === 'compose') return;
31
- if (!api.options.canCommit()) return;
32
- const repo = api.options.repo();
33
- const caps = api.options.capabilities();
33
+ if (api.ui.mode === 'compose') return;
34
+ if (!api.ui.commits.canCommit()) return;
35
+ const repo = api.ui.repo;
36
+ const caps = api.ui.capabilities;
34
37
  if (!caps.branches || !repo.listBranches) {
35
- api.options.setStatus('read only');
38
+ api.ui.status = 'read only';
36
39
  return;
37
40
  }
38
41
  try {
39
- api.state.branches = repo.listBranches(api.options.top());
42
+ api.state.branches = repo.listBranches(api.ui.top);
40
43
  } catch (error) {
41
- api.options.setStatus(error.message);
44
+ api.ui.status = error.message;
42
45
  return;
43
46
  }
44
47
  const current = api.state.branches.findIndex((entry) => entry.current);
45
- api.options.nav.branchCursor = current < 0 ? 0 : current;
46
- api.options.nav.pane = 'branches';
47
- api.options.setStatus('');
48
- api.options.nav.clearSelection();
48
+ api.ui.nav.branchCursor = current < 0 ? 0 : current;
49
+ api.ui.nav.pane = 'branches';
50
+ api.ui.status = '';
51
+ api.ui.nav.clearSelection();
49
52
  };
50
53
 
51
54
  const onBranchMove = (api, delta) => {
52
55
  const branches = api.state.branches;
53
56
  if (!branches.length) {
54
- api.options.setStatus('nothing to review');
57
+ api.ui.status = 'nothing to review';
55
58
  return;
56
59
  }
57
60
  const next = Math.min(
58
61
  branches.length - 1,
59
- Math.max(0, api.options.nav.branchCursor + delta),
62
+ Math.max(0, api.ui.nav.branchCursor + delta),
60
63
  );
61
- if (next === api.options.nav.branchCursor) return;
62
- api.options.nav.branchCursor = next;
63
- api.options.setStatus('');
64
+ if (next === api.ui.nav.branchCursor) return;
65
+ api.ui.nav.branchCursor = next;
66
+ api.ui.status = '';
64
67
  };
65
68
 
66
69
  const checkoutAsync = (api, name, done, write) => {
67
- api.options.showFiles();
70
+ api.ui.showFiles();
68
71
  const run = (top) => write(top, name);
69
72
  const after = () =>
70
- api.options.refreshFromRepo({ keepEmpty: true, doneStatus: done });
71
- return void api.options.runner.runBusy('checking out', done, run, after);
73
+ api.ui.refreshFromRepo({ keepEmpty: true, doneStatus: done });
74
+ return void api.ui.ops.runBusy('checking out', done, run, after);
72
75
  };
73
76
 
74
77
  const onCheckoutBranch = (api) => {
75
- if (!api.options.canCommit()) return;
78
+ if (!api.ui.commits.canCommit()) return;
76
79
  const entry = selectedBranch(api);
77
80
  if (!entry) return;
78
- if (entry.current) {
79
- api.options.showFiles();
80
- return;
81
- }
81
+ if (entry.current) return void api.ui.showFiles();
82
82
  const name = entry.name;
83
83
  const done = `checked out ${name}`;
84
- const uiOpen = api.options.uiOpen();
85
- const picked = pickRepoWrite(api.options.repo(), 'checkout', uiOpen);
84
+ const uiOpen = api.ui.uiOpen;
85
+ const picked = pickRepoWrite(api.ui.repo, 'checkout', uiOpen);
86
86
  if (picked.async) {
87
- checkoutAsync(api, name, done, picked.write);
88
- return;
87
+ return void checkoutAsync(api, name, done, picked.write);
89
88
  }
90
- const ok = api.options.runner.runRepo(done, (top) => {
91
- api.options.repo().checkout(top, name);
89
+ const ok = api.ui.ops.runRepo(done, (top) => {
90
+ api.ui.repo.checkout(top, name);
92
91
  });
93
92
  if (!ok) return;
94
- api.options.showFiles();
95
- api.options.refreshFromRepo({ keepEmpty: true });
96
- if (!api.options.getStatus()) api.options.setStatus(done);
93
+ api.ui.showFiles();
94
+ api.ui.refreshFromRepo({ keepEmpty: true });
95
+ if (!api.ui.status) api.ui.status = done;
97
96
  };
98
97
 
99
98
  const rebaseAsync = (api, onto, done, write) => {
100
99
  const run = (top) => write(top, onto);
101
100
  const after = () => refreshAfterWrite(api, { doneStatus: done });
102
- return void api.options.runner.runBusy('rebasing', done, run, after);
101
+ return void api.ui.ops.runBusy('rebasing', done, run, after);
103
102
  };
104
103
 
105
104
  const onRebaseBranch = (api) => {
106
- if (api.options.nav.pane !== 'branches') return;
107
- if (!api.options.canCommit()) return;
105
+ if (api.ui.nav.pane !== 'branches') return;
106
+ if (!api.ui.commits.canCommit()) return;
108
107
  const entry = selectedBranch(api);
109
108
  if (!entry || entry.current) return;
110
109
  const onto = entry.name;
111
110
  const done = `rebased onto ${onto}`;
112
- const uiOpen = api.options.uiOpen();
113
- const picked = pickRepoWrite(api.options.repo(), 'rebase', uiOpen);
111
+ const uiOpen = api.ui.uiOpen;
112
+ const picked = pickRepoWrite(api.ui.repo, 'rebase', uiOpen);
114
113
  if (picked.async) {
115
- rebaseAsync(api, onto, done, picked.write);
116
- return;
114
+ return void rebaseAsync(api, onto, done, picked.write);
117
115
  }
118
- const ok = api.options.runner.runRepo(done, (top) => {
119
- api.options.repo().rebase(top, onto);
116
+ const ok = api.ui.ops.runRepo(done, (top) => {
117
+ api.ui.repo.rebase(top, onto);
120
118
  });
121
119
  if (!ok) return;
122
120
  refreshAfterWrite(api);
123
- if (!api.options.getStatus()) api.options.setStatus(done);
121
+ if (!api.ui.status) api.ui.status = done;
124
122
  };
125
123
 
126
124
  const onDropBranch = (api) => {
127
- if (api.options.nav.pane !== 'branches') return;
128
- if (!api.options.canCommit()) return;
125
+ if (api.ui.nav.pane !== 'branches') return;
126
+ if (!api.ui.commits.canCommit()) return;
129
127
  const entry = selectedBranch(api);
130
128
  if (!entry || entry.current) return;
131
129
  api.state.dropName = entry.name;
132
- api.options.setMode('confirmDrop');
133
- api.options.setStatus('');
130
+ api.ui.mode = 'confirmDrop';
131
+ api.ui.status = '';
134
132
  };
135
133
 
136
134
  const cancelDropBranch = (api) => {
137
- api.options.setMode('review');
135
+ api.ui.mode = 'review';
138
136
  api.state.dropName = '';
139
- api.options.setStatus('');
137
+ api.ui.status = '';
140
138
  };
141
139
 
142
140
  const dropAsync = (api, name, done, write) => {
143
141
  const run = (top) => write(top, name);
144
142
  const after = () => refreshAfterWrite(api, { doneStatus: done });
145
- return void api.options.runner.runBusy('dropping', done, run, after);
143
+ return void api.ui.ops.runBusy('dropping', done, run, after);
146
144
  };
147
145
 
148
146
  const confirmDropBranch = (api) => {
149
147
  const name = api.state.dropName;
150
- api.options.setMode('review');
148
+ api.ui.mode = 'review';
151
149
  api.state.dropName = '';
152
150
  if (!name) return;
153
151
  const done = `dropped ${name}`;
154
- const uiOpen = api.options.uiOpen();
155
- const picked = pickRepoWrite(api.options.repo(), 'drop', uiOpen);
152
+ const uiOpen = api.ui.uiOpen;
153
+ const picked = pickRepoWrite(api.ui.repo, 'drop', uiOpen);
156
154
  if (picked.async) {
157
- dropAsync(api, name, done, picked.write);
158
- return;
155
+ return void dropAsync(api, name, done, picked.write);
159
156
  }
160
- const ok = api.options.runner.runRepo(done, (top) => {
161
- api.options.repo().drop(top, name);
157
+ const ok = api.ui.ops.runRepo(done, (top) => {
158
+ api.ui.repo.drop(top, name);
162
159
  });
163
160
  if (!ok) return;
164
161
  refreshAfterWrite(api);
165
- if (!api.options.getStatus()) api.options.setStatus(done);
162
+ if (!api.ui.status) api.ui.status = done;
166
163
  };
167
164
 
168
165
  const onNewBranch = (api) => {
169
- if (api.options.nav.pane !== 'branches') return;
170
- if (!api.options.canCommit()) return;
171
- api.options.composer.openCompose('branch', '');
166
+ if (api.ui.nav.pane !== 'branches') return;
167
+ if (!api.ui.commits.canCommit()) return;
168
+ api.ui.composer.openCompose('branch', '');
172
169
  };
173
170
 
174
171
  const createAsync = (api, name, done, write) => {
175
- api.options.composer.closeCompose();
176
- api.options.showFiles();
172
+ api.ui.composer.closeCompose();
173
+ api.ui.showFiles();
177
174
  const run = (top) => write(top, name);
178
175
  const after = () => refreshAfterWrite(api, { doneStatus: done });
179
- return void api.options.runner.runBusy('creating branch', done, run, after);
176
+ return void api.ui.ops.runBusy('creating branch', done, run, after);
180
177
  };
181
178
 
182
179
  const finishCreateBranch = (api) => {
183
- const editor = api.options.composer.state.editor;
180
+ const editor = api.ui.composer.state.editor;
184
181
  const name = editor ? editor.text.trim() : '';
185
182
  if (!name) {
186
- api.options.setStatus('empty branch name');
183
+ api.ui.status = 'empty branch name';
187
184
  return;
188
185
  }
189
186
  const done = `created ${name}`;
190
- const uiOpen = api.options.uiOpen();
191
- const picked = pickRepoWrite(api.options.repo(), 'createBranch', uiOpen);
187
+ const uiOpen = api.ui.uiOpen;
188
+ const picked = pickRepoWrite(api.ui.repo, 'createBranch', uiOpen);
192
189
  if (picked.async) {
193
- createAsync(api, name, done, picked.write);
194
- return;
190
+ return void createAsync(api, name, done, picked.write);
195
191
  }
196
- const ok = api.options.runner.runRepo(done, (top) => {
197
- api.options.repo().createBranch(top, name);
192
+ const ok = api.ui.ops.runRepo(done, (top) => {
193
+ api.ui.repo.createBranch(top, name);
198
194
  });
199
195
  if (!ok) return;
200
- api.options.composer.closeCompose();
201
- api.options.showFiles();
196
+ api.ui.composer.closeCompose();
197
+ api.ui.showFiles();
202
198
  refreshAfterWrite(api);
203
- if (!api.options.getStatus()) api.options.setStatus(done);
199
+ if (!api.ui.status) api.ui.status = done;
204
200
  };
205
201
 
206
202
  const onPull = (api) => {
207
- if (!api.options.canCommit()) return;
208
- const repo = api.options.repo();
209
- const picked = pickRepoWrite(repo, 'pull', api.options.uiOpen());
203
+ if (!api.ui.commits.canCommit()) return;
204
+ const repo = api.ui.repo;
205
+ const picked = pickRepoWrite(repo, 'pull', api.ui.uiOpen);
210
206
  if (picked.async) {
211
207
  const after = () => refreshAfterWrite(api);
212
208
  const write = (top) => picked.write(top);
213
- return void api.options.runner.runBusy('pulling', 'pulled', write, after);
209
+ return void api.ui.ops.runBusy('pulling', 'pulled', write, after);
214
210
  }
215
- const ok = api.options.runner.runRepo('pulled', (top) => {
211
+ const ok = api.ui.ops.runRepo('pulled', (top) => {
216
212
  repo.pull(top);
217
213
  });
218
214
  if (!ok) return;
219
215
  refreshAfterWrite(api);
220
- if (!api.options.getStatus()) api.options.setStatus('pulled');
216
+ if (!api.ui.status) api.ui.status = 'pulled';
221
217
  };
222
218
 
223
219
  const startPush = (api, force) => {
224
- if (!api.options.canCommit()) return;
220
+ if (!api.ui.commits.canCommit()) return;
225
221
  const done = force ? 'force pushed' : 'pushed';
226
222
  const kind = force ? 'force pushing' : 'pushing';
227
- const repo = api.options.repo();
228
- const picked = pickRepoWrite(repo, 'push', api.options.uiOpen());
223
+ const repo = api.ui.repo;
224
+ const picked = pickRepoWrite(repo, 'push', api.ui.uiOpen);
229
225
  if (picked.async) {
230
226
  const write = (top) => picked.write(top, force);
231
227
  const after = () => refreshAfterWrite(api);
232
- return void api.options.runner.runBusy(kind, done, write, after);
228
+ return void api.ui.ops.runBusy(kind, done, write, after);
233
229
  }
234
230
  try {
235
- repo.push(api.options.top(), force);
231
+ repo.push(api.ui.top, force);
236
232
  } catch (error) {
237
233
  if (error.rejected && !force) {
238
- api.options.setMode('confirmPush');
239
- api.options.setStatus('');
234
+ api.ui.mode = 'confirmPush';
235
+ api.ui.status = '';
240
236
  return;
241
237
  }
242
- api.options.setStatus(error.message);
238
+ api.ui.status = error.message;
243
239
  return;
244
240
  }
245
241
  refreshAfterWrite(api);
246
- api.options.setStatus(done);
242
+ api.ui.status = done;
247
243
  };
248
244
 
249
245
  const onPush = (api) => startPush(api, false);
250
246
 
251
247
  const onForcePush = (api) => {
252
- api.options.setMode('review');
248
+ api.ui.mode = 'review';
253
249
  startPush(api, true);
254
250
  };
255
251
 
256
252
  const cancelPush = (api) => {
257
- api.options.setMode('review');
258
- api.options.setStatus('');
253
+ api.ui.mode = 'review';
254
+ api.ui.status = '';
259
255
  };
260
256
 
261
257
  const reset = (state) => {
@@ -263,40 +259,32 @@ const reset = (state) => {
263
259
  state.dropName = '';
264
260
  };
265
261
 
266
- const createBranchController = (options) => {
262
+ const createBranchController = (ui) => {
267
263
  const state = {
268
264
  branches: [],
269
265
  dropName: '',
270
266
  };
271
- const api = { options, state };
272
- return {
273
- get branches() {
274
- return state.branches;
275
- },
276
- set branches(value) {
277
- state.branches = value;
278
- },
279
- get dropName() {
280
- return state.dropName;
267
+ const api = { ui, state };
268
+ return stateView(
269
+ state,
270
+ {
271
+ reset: () => reset(state),
272
+ onBranch: () => onBranch(api),
273
+ onBranchMove: (delta) => onBranchMove(api, delta),
274
+ onCheckoutBranch: () => onCheckoutBranch(api),
275
+ onRebaseBranch: () => onRebaseBranch(api),
276
+ onDropBranch: () => onDropBranch(api),
277
+ cancelDropBranch: () => cancelDropBranch(api),
278
+ confirmDropBranch: () => confirmDropBranch(api),
279
+ onNewBranch: () => onNewBranch(api),
280
+ finishCreateBranch: () => finishCreateBranch(api),
281
+ onPull: () => onPull(api),
282
+ onPush: () => onPush(api),
283
+ onForcePush: () => onForcePush(api),
284
+ cancelPush: () => cancelPush(api),
281
285
  },
282
- set dropName(value) {
283
- state.dropName = value;
284
- },
285
- reset: () => reset(state),
286
- onBranch: () => onBranch(api),
287
- onBranchMove: (delta) => onBranchMove(api, delta),
288
- onCheckoutBranch: () => onCheckoutBranch(api),
289
- onRebaseBranch: () => onRebaseBranch(api),
290
- onDropBranch: () => onDropBranch(api),
291
- cancelDropBranch: () => cancelDropBranch(api),
292
- confirmDropBranch: () => confirmDropBranch(api),
293
- onNewBranch: () => onNewBranch(api),
294
- finishCreateBranch: () => finishCreateBranch(api),
295
- onPull: () => onPull(api),
296
- onPush: () => onPush(api),
297
- onForcePush: () => onForcePush(api),
298
- cancelPush: () => cancelPush(api),
299
- };
286
+ ['branches', 'dropName'],
287
+ );
300
288
  };
301
289
 
302
290
  module.exports = { createBranchController };