reslop 0.1.9 → 0.2.0

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 (94) hide show
  1. package/CHANGELOG.md +12 -1
  2. package/README.md +2 -1
  3. package/bin/reslop.js +2 -2
  4. package/lib/ansi.js +4 -2
  5. package/lib/api.js +2 -2
  6. package/lib/capabilities.js +7 -14
  7. package/lib/cli.js +28 -47
  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} +6 -5
  21. package/lib/{git/dependencies.js → git-deps.js} +111 -38
  22. package/lib/git.js +589 -68
  23. package/lib/github.js +28 -197
  24. package/lib/gitlab.js +24 -195
  25. package/lib/highlight/bash.js +1 -3
  26. package/lib/highlight/css.js +1 -3
  27. package/lib/highlight/js.js +11 -14
  28. package/lib/highlight.js +6 -9
  29. package/lib/keys.js +14 -8
  30. package/lib/manifest.js +330 -0
  31. package/lib/remote.js +374 -0
  32. package/lib/render/branches.js +14 -68
  33. package/lib/render/chrome.js +24 -9
  34. package/lib/render/commits.js +6 -59
  35. package/lib/render/diff.js +16 -16
  36. package/lib/render/files.js +6 -34
  37. package/lib/render/frame.js +23 -12
  38. package/lib/render/notes.js +4 -3
  39. package/lib/render/primitives.js +45 -0
  40. package/lib/{render.js → render/render.js} +5 -5
  41. package/lib/render/unit.js +41 -0
  42. package/lib/review.js +750 -14
  43. package/lib/select.js +5 -10
  44. package/lib/session/accessors.js +9 -1
  45. package/lib/session/actions.js +32 -16
  46. package/lib/session/branches.js +116 -128
  47. package/lib/session/change-actions.js +202 -123
  48. package/lib/session/commit.js +105 -112
  49. package/lib/session/compose.js +158 -13
  50. package/lib/session/dispatch.js +104 -60
  51. package/lib/session/files-pane.js +142 -148
  52. package/lib/session/items.js +22 -30
  53. package/lib/session/lifecycle.js +44 -44
  54. package/lib/session/load.js +19 -33
  55. package/lib/session/navigation.js +12 -1
  56. package/lib/session/ops.js +28 -41
  57. package/lib/session/pointer.js +54 -57
  58. package/lib/session/review.js +23 -37
  59. package/lib/session/terminal.js +6 -12
  60. package/lib/session/todos.js +8 -12
  61. package/lib/session/unit.js +208 -0
  62. package/lib/session/update.js +33 -46
  63. package/lib/session/view.js +78 -9
  64. package/lib/session/watch.js +11 -19
  65. package/lib/session.js +21 -246
  66. package/lib/source.js +3 -3
  67. package/lib/update.js +40 -75
  68. package/lib/{git/proc.js → utilities.js} +75 -11
  69. package/lib/wrap.js +1 -3
  70. package/package.json +1 -1
  71. package/lib/deps/items.js +0 -134
  72. package/lib/deps/manifest.js +0 -152
  73. package/lib/deps/merge.js +0 -120
  74. package/lib/deps/proposals.js +0 -164
  75. package/lib/deps/reports.js +0 -180
  76. package/lib/deps/rows.js +0 -176
  77. package/lib/deps/scan.js +0 -138
  78. package/lib/deps/usage.js +0 -68
  79. package/lib/deps/versions.js +0 -119
  80. package/lib/diff.js +0 -33
  81. package/lib/git/changes.js +0 -164
  82. package/lib/git/read.js +0 -253
  83. package/lib/git/run.js +0 -100
  84. package/lib/npm/commands.js +0 -100
  85. package/lib/remote/changes.js +0 -37
  86. package/lib/remote/headers.js +0 -36
  87. package/lib/remote/http.js +0 -122
  88. package/lib/remote/notes.js +0 -94
  89. package/lib/review/format.js +0 -434
  90. package/lib/review/storage.js +0 -150
  91. package/lib/review/store.js +0 -178
  92. package/lib/review/templates.js +0 -49
  93. package/lib/session/origins.js +0 -7
  94. package/lib/sys.js +0 -84
@@ -1,6 +1,8 @@
1
1
  'use strict';
2
2
 
3
- const { isReadOnlyOrigin } = require('./origins.js');
3
+ const { stateView } = require('./accessors.js');
4
+
5
+ const { isReadOnlyOrigin } = require('../files.js');
4
6
  const { pickRepoWrite } = require('./ops.js');
5
7
 
6
8
  const COMMIT_STATUS = {
@@ -9,48 +11,48 @@ const COMMIT_STATUS = {
9
11
  fixup: 'fixup',
10
12
  };
11
13
 
12
- const canCommit = (options) => {
13
- const caps = options.capabilities();
14
+ const canCommit = (ui) => {
15
+ const caps = ui.capabilities;
14
16
  if (!caps.branches) {
15
- options.setStatus('read only');
17
+ ui.status = 'read only';
16
18
  return false;
17
19
  }
18
- for (const item of options.getItems()) {
20
+ for (const item of ui.items) {
19
21
  if (isReadOnlyOrigin(item.origin)) {
20
- options.setStatus('read only');
22
+ ui.status = 'read only';
21
23
  return false;
22
24
  }
23
25
  }
24
26
  return true;
25
27
  };
26
28
 
27
- const hasStagedChanges = (options) => {
28
- const repo = options.repo();
29
- if (repo.hasStaged) return repo.hasStaged(options.top());
30
- for (const item of options.getItems()) {
29
+ const hasStagedChanges = (ui) => {
30
+ const repo = ui.repo;
31
+ if (repo.hasStaged) return repo.hasStaged(ui.top);
32
+ for (const item of ui.items) {
31
33
  if (item.origin === 'staged') return true;
32
34
  }
33
35
  return false;
34
36
  };
35
37
 
36
38
  const selectedCommit = (api) => {
37
- const cursor = api.options.nav.commitCursor;
39
+ const cursor = api.ui.nav.commitCursor;
38
40
  return api.state.commits[cursor] ?? null;
39
41
  };
40
42
 
41
43
  const clampCommitCursor = (api) => {
42
44
  const last = api.state.commits.length - 1;
43
- const nav = api.options.nav;
45
+ const nav = api.ui.nav;
44
46
  if (nav.commitCursor > last) nav.commitCursor = Math.max(0, last);
45
47
  };
46
48
 
47
49
  const refreshCommitList = (api) => {
48
- const repo = api.options.repo();
50
+ const repo = api.ui.repo;
49
51
  if (!repo.listCommits) return;
50
52
  try {
51
- api.state.commits = repo.listCommits(api.options.top());
53
+ api.state.commits = repo.listCommits(api.ui.top);
52
54
  } catch (error) {
53
- api.options.setStatus(error.message);
55
+ api.ui.status = error.message;
54
56
  return;
55
57
  }
56
58
  clampCommitCursor(api);
@@ -58,185 +60,183 @@ const refreshCommitList = (api) => {
58
60
 
59
61
  const refreshAfterWrite = (api, extra = {}) => {
60
62
  refreshCommitList(api);
61
- api.options.refreshFromRepo({ keepEmpty: true, ...extra });
63
+ api.ui.refreshFromRepo({ keepEmpty: true, ...extra });
62
64
  };
63
65
 
64
66
  const showCommits = (api) => {
65
- if (api.options.getMode() === 'compose') return;
66
- if (!canCommit(api.options)) return;
67
- const repo = api.options.repo();
67
+ if (api.ui.mode === 'compose') return;
68
+ if (!canCommit(api.ui)) return;
69
+ const repo = api.ui.repo;
68
70
  if (!repo.listCommits) {
69
- api.options.setStatus('read only');
71
+ api.ui.status = 'read only';
70
72
  return;
71
73
  }
72
74
  try {
73
- api.state.commits = repo.listCommits(api.options.top());
75
+ api.state.commits = repo.listCommits(api.ui.top);
74
76
  } catch (error) {
75
- api.options.setStatus(error.message);
77
+ api.ui.status = error.message;
76
78
  return;
77
79
  }
78
- api.options.nav.commitCursor = 0;
79
- api.options.nav.pane = 'commits';
80
- api.options.setStatus('');
81
- api.options.nav.clearSelection();
80
+ api.ui.nav.commitCursor = 0;
81
+ api.ui.nav.pane = 'commits';
82
+ api.ui.status = '';
83
+ api.ui.nav.clearSelection();
82
84
  };
83
85
 
84
86
  const onCommitMove = (api, delta) => {
85
87
  const commits = api.state.commits;
86
88
  if (!commits.length) {
87
- api.options.setStatus('nothing to review');
89
+ api.ui.status = 'nothing to review';
88
90
  return;
89
91
  }
90
92
  const next = Math.min(
91
93
  commits.length - 1,
92
- Math.max(0, api.options.nav.commitCursor + delta),
94
+ Math.max(0, api.ui.nav.commitCursor + delta),
93
95
  );
94
- if (next === api.options.nav.commitCursor) return;
95
- api.options.nav.commitCursor = next;
96
- api.options.setStatus('');
96
+ if (next === api.ui.nav.commitCursor) return;
97
+ api.ui.nav.commitCursor = next;
98
+ api.ui.status = '';
97
99
  };
98
100
 
99
101
  const startGitCommit = (api, kind) => {
100
- const options = api.options;
101
- if (kind !== 'amend' && !hasStagedChanges(options)) {
102
- options.setMode('review');
103
- options.composer.state.commitKind = null;
104
- options.setStatus('nothing to commit');
102
+ const ui = api.ui;
103
+ if (kind !== 'amend' && !hasStagedChanges(ui)) {
104
+ ui.mode = 'review';
105
+ ui.composer.state.commitKind = null;
106
+ ui.status = 'nothing to commit';
105
107
  return;
106
108
  }
107
- options.composer.state.commitKind = kind;
109
+ ui.composer.state.commitKind = kind;
108
110
  let text = '';
109
111
  if (kind === 'fixup') {
110
112
  const entry = selectedCommit(api);
111
113
  text = entry ? entry.shortSha || entry.sha : 'HEAD';
112
114
  }
113
- if (kind === 'amend' && options.repo().lastMessage) {
114
- text = options.repo().lastMessage(options.top()) ?? '';
115
+ if (kind === 'amend' && ui.repo.lastMessage) {
116
+ text = ui.repo.lastMessage(ui.top) ?? '';
115
117
  }
116
- options.composer.openCompose('commit', text);
118
+ ui.composer.openCompose('commit', text);
117
119
  };
118
120
 
119
121
  const onCommit = (api) => {
120
- if (api.options.nav.pane !== 'commits') return void showCommits(api);
121
- if (!canCommit(api.options)) return;
122
+ if (api.ui.nav.pane !== 'commits') return void showCommits(api);
123
+ if (!canCommit(api.ui)) return;
122
124
  startGitCommit(api, 'commit');
123
125
  };
124
126
 
125
127
  const onAmend = (api) => {
126
- if (api.options.nav.pane !== 'commits') return;
127
- if (!canCommit(api.options)) return;
128
+ if (api.ui.nav.pane !== 'commits') return;
129
+ if (!canCommit(api.ui)) return;
128
130
  startGitCommit(api, 'amend');
129
131
  };
130
132
 
131
133
  const onFixup = (api) => {
132
- if (api.options.nav.pane !== 'commits') return;
133
- if (!canCommit(api.options)) return;
134
+ if (api.ui.nav.pane !== 'commits') return;
135
+ if (!canCommit(api.ui)) return;
134
136
  startGitCommit(api, 'fixup');
135
137
  };
136
138
 
137
139
  const cancelCommit = (api) => {
138
- api.options.setMode('review');
139
- api.options.composer.state.commitKind = null;
140
- api.options.setStatus('');
140
+ api.ui.mode = 'review';
141
+ api.ui.composer.state.commitKind = null;
142
+ api.ui.status = '';
141
143
  };
142
144
 
143
145
  const finishAsyncCommit = (api, kind, message, done, write) => {
144
- const options = api.options;
145
- options.composer.closeCompose();
146
+ const ui = api.ui;
147
+ ui.composer.closeCompose();
146
148
  const run = (top) => write(top, kind, message);
147
149
  const after = () => refreshAfterWrite(api, { doneStatus: done });
148
- return void options.runner.runBusy('committing', done, run, after);
150
+ return void ui.ops.runBusy('committing', done, run, after);
149
151
  };
150
152
 
151
153
  const finishSyncCommit = (api, kind, message, done) => {
152
- const options = api.options;
154
+ const ui = api.ui;
153
155
  try {
154
- options.repo().commit(options.top(), kind, message);
156
+ ui.repo.commit(ui.top, kind, message);
155
157
  } catch (error) {
156
- options.setStatus(error.message);
158
+ ui.status = error.message;
157
159
  return;
158
160
  }
159
- options.composer.closeCompose();
160
- options.collection.clearDismissed();
161
+ ui.composer.closeCompose();
162
+ ui.collection.clearDismissed();
161
163
  refreshAfterWrite(api);
162
- if (!options.isDone() && !options.pendingExtras()) {
163
- options.setStatus(done);
164
+ if (!ui.done && !ui.pendingExtras) {
165
+ ui.status = done;
164
166
  }
165
167
  };
166
168
 
167
169
  const finishGitCommit = (api) => {
168
- const options = api.options;
169
- const kind = options.composer.state.commitKind;
170
- const editor = options.composer.state.editor;
170
+ const ui = api.ui;
171
+ const kind = ui.composer.state.commitKind;
172
+ const editor = ui.composer.state.editor;
171
173
  const message = editor ? editor.text : '';
172
174
  if (kind !== 'fixup' && !message.trim()) {
173
- options.setStatus('empty commit message');
175
+ ui.status = 'empty commit message';
174
176
  return;
175
177
  }
176
- if (kind !== 'amend' && !hasStagedChanges(options)) {
177
- options.composer.closeCompose();
178
- options.setStatus('nothing to commit');
178
+ if (kind !== 'amend' && !hasStagedChanges(ui)) {
179
+ ui.composer.closeCompose();
180
+ ui.status = 'nothing to commit';
179
181
  return;
180
182
  }
181
183
  const done = COMMIT_STATUS[kind] ?? 'committed';
182
- const uiOpen = options.uiOpen();
183
- const picked = pickRepoWrite(options.repo(), 'commit', uiOpen);
184
+ const uiOpen = ui.uiOpen;
185
+ const picked = pickRepoWrite(ui.repo, 'commit', uiOpen);
184
186
  if (picked.async) {
185
- finishAsyncCommit(api, kind, message, done, picked.write);
186
- return;
187
+ return void finishAsyncCommit(api, kind, message, done, picked.write);
187
188
  }
188
189
  finishSyncCommit(api, kind, message, done);
189
190
  };
190
191
 
191
192
  const onDropCommit = (api) => {
192
- if (api.options.nav.pane !== 'commits') return;
193
- if (!canCommit(api.options)) return;
193
+ if (api.ui.nav.pane !== 'commits') return;
194
+ if (!canCommit(api.ui)) return;
194
195
  const entry = selectedCommit(api);
195
196
  if (!entry) return;
196
197
  api.state.dropName = entry.shortSha || entry.sha;
197
198
  api.state.dropSha = entry.sha;
198
- api.options.setMode('confirmDrop');
199
- api.options.setStatus('');
199
+ api.ui.mode = 'confirmDrop';
200
+ api.ui.status = '';
200
201
  };
201
202
 
202
203
  const cancelDropCommit = (api) => {
203
- api.options.setMode('review');
204
+ api.ui.mode = 'review';
204
205
  api.state.dropName = '';
205
206
  api.state.dropSha = '';
206
- api.options.setStatus('');
207
+ api.ui.status = '';
207
208
  };
208
209
 
209
210
  const dropAsync = (api, sha, done, write) => {
210
211
  const run = (top) => write(top, sha);
211
212
  const after = () => refreshAfterWrite(api, { doneStatus: done });
212
- return void api.options.runner.runBusy('dropping', done, run, after);
213
+ return void api.ui.ops.runBusy('dropping', done, run, after);
213
214
  };
214
215
 
215
216
  const confirmDropCommit = (api) => {
216
217
  const sha = api.state.dropSha;
217
218
  const name = api.state.dropName;
218
- api.options.setMode('review');
219
+ api.ui.mode = 'review';
219
220
  api.state.dropName = '';
220
221
  api.state.dropSha = '';
221
222
  if (!sha) return;
222
223
  const done = `dropped ${name}`;
223
- const repo = api.options.repo();
224
+ const repo = api.ui.repo;
224
225
  if (!repo.dropCommit) {
225
- api.options.setStatus('read only');
226
+ api.ui.status = 'read only';
226
227
  return;
227
228
  }
228
- const uiOpen = api.options.uiOpen();
229
+ const uiOpen = api.ui.uiOpen;
229
230
  const picked = pickRepoWrite(repo, 'dropCommit', uiOpen);
230
231
  if (picked.async) {
231
- dropAsync(api, sha, done, picked.write);
232
- return;
232
+ return void dropAsync(api, sha, done, picked.write);
233
233
  }
234
- const ok = api.options.runner.runRepo(done, (top) => {
234
+ const ok = api.ui.ops.runRepo(done, (top) => {
235
235
  repo.dropCommit(top, sha);
236
236
  });
237
237
  if (!ok) return;
238
238
  refreshAfterWrite(api);
239
- if (!api.options.getStatus()) api.options.setStatus(done);
239
+ if (!api.ui.status) api.ui.status = done;
240
240
  };
241
241
 
242
242
  const reset = (state) => {
@@ -245,39 +245,32 @@ const reset = (state) => {
245
245
  state.dropSha = '';
246
246
  };
247
247
 
248
- const createCommitController = (options) => {
248
+ const createCommitController = (ui) => {
249
249
  const state = {
250
250
  commits: [],
251
251
  dropName: '',
252
252
  dropSha: '',
253
253
  };
254
- const api = { options, state };
255
- return {
256
- get commits() {
257
- return state.commits;
258
- },
259
- set commits(value) {
260
- state.commits = value;
254
+ const api = { ui, state };
255
+ return stateView(
256
+ state,
257
+ {
258
+ reset: () => reset(state),
259
+ canCommit: () => canCommit(ui),
260
+ onCommit: () => onCommit(api),
261
+ onAmend: () => onAmend(api),
262
+ onFixup: () => onFixup(api),
263
+ onCommitMove: (delta) => onCommitMove(api, delta),
264
+ cancelCommit: () => cancelCommit(api),
265
+ startGitCommit: (kind) => startGitCommit(api, kind),
266
+ finishGitCommit: () => finishGitCommit(api),
267
+ refresh: () => refreshCommitList(api),
268
+ onDropCommit: () => onDropCommit(api),
269
+ cancelDropCommit: () => cancelDropCommit(api),
270
+ confirmDropCommit: () => confirmDropCommit(api),
261
271
  },
262
- get dropName() {
263
- return state.dropName;
264
- },
265
- set dropName(value) {
266
- state.dropName = value;
267
- },
268
- reset: () => reset(state),
269
- canCommit: () => canCommit(options),
270
- onCommit: () => onCommit(api),
271
- onAmend: () => onAmend(api),
272
- onFixup: () => onFixup(api),
273
- onCommitMove: (delta) => onCommitMove(api, delta),
274
- cancelCommit: () => cancelCommit(api),
275
- startGitCommit: (kind) => startGitCommit(api, kind),
276
- finishGitCommit: () => finishGitCommit(api),
277
- onDropCommit: () => onDropCommit(api),
278
- cancelDropCommit: () => cancelDropCommit(api),
279
- confirmDropCommit: () => confirmDropCommit(api),
280
- };
272
+ ['commits', 'dropName'],
273
+ );
281
274
  };
282
275
 
283
276
  module.exports = {