reslop 0.2.4 → 0.2.6

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 (109) hide show
  1. package/CHANGELOG.md +25 -1
  2. package/LICENSE +1 -1
  3. package/README.md +12 -13
  4. package/bin/reslop.js +3 -8
  5. package/lib/ansi.js +32 -19
  6. package/lib/capabilities.js +8 -12
  7. package/lib/cli.js +40 -74
  8. package/lib/clipboard.js +48 -18
  9. package/lib/dashboard/git.js +128 -0
  10. package/lib/dashboard/model.js +332 -0
  11. package/lib/dashboard/npm.js +193 -0
  12. package/lib/dashboard/tree.js +278 -0
  13. package/lib/deps-diff.js +196 -404
  14. package/lib/deps.js +240 -399
  15. package/lib/detect.js +8 -18
  16. package/lib/diff/align.js +41 -113
  17. package/lib/diff/diff.js +12 -43
  18. package/lib/diff/display.js +25 -36
  19. package/lib/diff/edit.js +6 -20
  20. package/lib/diff/inline.js +138 -141
  21. package/lib/diff/items.js +33 -47
  22. package/lib/diff/parse.js +28 -56
  23. package/lib/diff/patch.js +12 -33
  24. package/lib/diff/unit.js +90 -206
  25. package/lib/editor.js +98 -55
  26. package/lib/files.js +86 -103
  27. package/lib/git-branches.js +254 -416
  28. package/lib/git-deps.js +182 -344
  29. package/lib/git-reword-todo.js +5 -13
  30. package/lib/git-worktree.js +141 -212
  31. package/lib/git.js +21 -49
  32. package/lib/github.js +67 -181
  33. package/lib/gitlab.js +40 -90
  34. package/lib/highlight/bash.js +55 -177
  35. package/lib/highlight/core.js +157 -132
  36. package/lib/highlight/css.js +25 -58
  37. package/lib/highlight/csv.js +19 -37
  38. package/lib/highlight/dart.js +72 -213
  39. package/lib/highlight/dot.js +16 -26
  40. package/lib/highlight/html.js +42 -63
  41. package/lib/highlight/js.js +177 -506
  42. package/lib/highlight/json.js +17 -37
  43. package/lib/highlight/log.js +22 -35
  44. package/lib/highlight/txt.js +9 -22
  45. package/lib/highlight.js +17 -46
  46. package/lib/keys.js +62 -85
  47. package/lib/manifest.js +67 -130
  48. package/lib/npm-commands.js +119 -189
  49. package/lib/remote.js +141 -197
  50. package/lib/render/branches.js +66 -73
  51. package/lib/render/chrome.js +264 -323
  52. package/lib/render/commits.js +187 -500
  53. package/lib/render/dash-activity.js +212 -0
  54. package/lib/render/dash-blocks.js +245 -0
  55. package/lib/render/dash-table.js +290 -0
  56. package/lib/render/dashboard.js +62 -0
  57. package/lib/render/diff.js +123 -228
  58. package/lib/render/files.js +45 -99
  59. package/lib/render/frame.js +129 -183
  60. package/lib/render/notes.js +144 -160
  61. package/lib/render/npm.js +234 -112
  62. package/lib/render/present.js +4 -11
  63. package/lib/render/primitives.js +131 -170
  64. package/lib/render/render.js +5 -14
  65. package/lib/render/report.js +43 -0
  66. package/lib/render/tiles.js +260 -0
  67. package/lib/render/unit.js +15 -28
  68. package/lib/report-model.js +110 -33
  69. package/lib/report-parse.js +56 -38
  70. package/lib/report-render.js +102 -59
  71. package/lib/report-run.js +87 -78
  72. package/lib/report-test.js +256 -141
  73. package/lib/report-tools.js +96 -161
  74. package/lib/review-merge.js +114 -152
  75. package/lib/review.js +115 -189
  76. package/lib/runs.js +225 -0
  77. package/lib/select.js +89 -75
  78. package/lib/session/accessors.js +14 -21
  79. package/lib/session/actions.js +82 -63
  80. package/lib/session/branches.js +193 -247
  81. package/lib/session/change-actions.js +171 -214
  82. package/lib/session/commit.js +280 -342
  83. package/lib/session/compose.js +559 -674
  84. package/lib/session/dashboard.js +385 -0
  85. package/lib/session/dispatch.js +164 -157
  86. package/lib/session/edit-click.js +57 -0
  87. package/lib/session/files-pane.js +85 -53
  88. package/lib/session/items.js +73 -104
  89. package/lib/session/lifecycle.js +403 -541
  90. package/lib/session/load.js +48 -68
  91. package/lib/session/navigation.js +96 -87
  92. package/lib/session/npm.js +409 -345
  93. package/lib/session/ops.js +196 -63
  94. package/lib/session/pointer.js +23 -15
  95. package/lib/session/progress.js +33 -21
  96. package/lib/session/review.js +33 -54
  97. package/lib/session/tasks.js +333 -0
  98. package/lib/session/templates.js +51 -59
  99. package/lib/session/terminal.js +85 -136
  100. package/lib/session/unit.js +3 -4
  101. package/lib/session/update.js +76 -97
  102. package/lib/session/view.js +52 -83
  103. package/lib/session/watch.js +208 -204
  104. package/lib/session.js +112 -237
  105. package/lib/update.js +45 -116
  106. package/lib/utilities.js +67 -89
  107. package/lib/wrap.js +33 -44
  108. package/package.json +1 -1
  109. package/lib/session/todos.js +0 -293
@@ -1,254 +1,200 @@
1
1
  'use strict';
2
2
 
3
- const accessors = require('./accessors.js');
4
- const { stateView } = accessors;
5
-
6
3
  const ops = require('./ops.js');
7
4
  const { pickRepoWrite } = ops;
8
5
 
9
- const selectedBranch = (api) => {
10
- const cursor = api.ui.nav.branchCursor;
11
- return api.state.branches[cursor];
12
- };
13
-
14
- const refreshBranchList = (api) => {
15
- const repo = api.ui.repo;
16
- if (!repo.listBranches) return;
17
- try {
18
- api.state.branches = repo.listBranches(api.ui.top);
19
- } catch (error) {
20
- api.ui.status = error.message;
21
- return;
22
- }
23
- const last = api.state.branches.length - 1;
24
- const nav = api.ui.nav;
25
- if (nav.branchCursor > last) nav.branchCursor = Math.max(0, last);
26
- };
27
-
28
- const refreshAfterWrite = (api, extra = {}) => {
29
- refreshBranchList(api);
30
- api.ui.commits.refresh();
31
- api.ui.refreshFromRepo({ keepEmpty: true, ...extra });
32
- };
33
-
34
- const onBranch = (api) => {
35
- if (api.ui.mode === 'compose') return;
36
- if (!api.ui.commits.canCommit()) return;
37
- const repo = api.ui.repo;
38
- const caps = api.ui.capabilities;
39
- if (!caps.branches || !repo.listBranches) {
40
- api.ui.status = 'read only';
41
- return;
42
- }
43
- try {
44
- api.state.branches = repo.listBranches(api.ui.top);
45
- } catch (error) {
46
- api.ui.status = error.message;
47
- return;
48
- }
49
- const current = api.state.branches.findIndex((entry) => entry.current);
50
- api.ui.nav.branchCursor = current < 0 ? 0 : current;
51
- api.ui.nav.pane = 'branches';
52
- api.ui.status = '';
53
- api.ui.nav.clearSelection();
54
- };
55
-
56
- const onBranchMove = (api, delta) => {
57
- const branches = api.state.branches;
58
- if (!branches.length) {
59
- api.ui.status = 'nothing to review';
60
- return;
61
- }
62
- const next = Math.min(
63
- branches.length - 1,
64
- Math.max(0, api.ui.nav.branchCursor + delta),
65
- );
66
- if (next === api.ui.nav.branchCursor) return;
67
- api.ui.nav.branchCursor = next;
68
- api.ui.status = '';
69
- };
70
-
71
- const checkoutAsync = (api, name, done, write) => {
72
- api.ui.showFiles();
73
- const run = (top) => write(top, name);
74
- const after = () =>
75
- api.ui.refreshFromRepo({ keepEmpty: true, doneStatus: done });
76
- return void api.ui.ops.runBusy('checking out', done, run, after);
77
- };
78
-
79
- const onCheckoutBranch = (api) => {
80
- if (!api.ui.commits.canCommit()) return;
81
- const entry = selectedBranch(api);
82
- if (!entry) return;
83
- if (entry.current) return void api.ui.showFiles();
84
- const name = entry.name;
85
- const done = `checked out ${name}`;
86
- const uiOpen = api.ui.uiOpen;
87
- const picked = pickRepoWrite(api.ui.repo, 'checkout', uiOpen);
88
- if (picked.async) {
89
- return void checkoutAsync(api, name, done, picked.write);
90
- }
91
- const ok = api.ui.ops.runRepo(done, (top) => {
92
- api.ui.repo.checkout(top, name);
93
- });
94
- if (!ok) return;
95
- api.ui.showFiles();
96
- api.ui.refreshFromRepo({ keepEmpty: true });
97
- if (!api.ui.status) api.ui.status = done;
98
- };
99
-
100
- const onRebaseBranch = (api) => {
101
- if (api.ui.nav.pane !== 'branches') return;
102
- if (!api.ui.commits.canCommit()) return;
103
- const entry = selectedBranch(api);
104
- if (!entry || entry.current) return;
105
- const onto = entry.name;
106
- const done = `rebased onto ${onto}`;
107
- api.ui.ops.runWrite('rebase', [onto], 'rebasing', done, (extra) =>
108
- refreshAfterWrite(api, extra),
109
- );
110
- };
111
-
112
- const onDropBranch = (api) => {
113
- if (api.ui.nav.pane !== 'branches') return;
114
- if (!api.ui.commits.canCommit()) return;
115
- const entry = selectedBranch(api);
116
- if (!entry || entry.current) return;
117
- api.state.dropName = entry.name;
118
- api.ui.mode = 'confirmDrop';
119
- api.ui.status = '';
120
- };
121
-
122
- const cancelDropBranch = (api) => {
123
- api.ui.mode = 'review';
124
- api.state.dropName = '';
125
- api.ui.status = '';
126
- };
127
-
128
- const confirmDropBranch = (api) => {
129
- const name = api.state.dropName;
130
- api.ui.mode = 'review';
131
- api.state.dropName = '';
132
- if (!name) return;
133
- const done = `dropped ${name}`;
134
- api.ui.ops.runWrite('drop', [name], 'dropping', done, (extra) =>
135
- refreshAfterWrite(api, extra),
136
- );
137
- };
138
-
139
- const onNewBranch = (api) => {
140
- if (api.ui.nav.pane !== 'branches') return;
141
- if (!api.ui.commits.canCommit()) return;
142
- api.ui.composer.openCompose('branch', '');
143
- };
144
-
145
- const createAsync = (api, name, done, write) => {
146
- api.ui.composer.closeCompose();
147
- api.ui.showFiles();
148
- const run = (top) => write(top, name);
149
- const after = () => refreshAfterWrite(api, { doneStatus: done });
150
- return void api.ui.ops.runBusy('creating branch', done, run, after);
151
- };
152
-
153
- const finishCreateBranch = (api) => {
154
- const editor = api.ui.composer.state.editor;
155
- const name = editor ? editor.text.trim() : '';
156
- if (!name) {
157
- api.ui.status = 'empty branch name';
158
- return;
159
- }
160
- const done = `created ${name}`;
161
- const uiOpen = api.ui.uiOpen;
162
- const picked = pickRepoWrite(api.ui.repo, 'createBranch', uiOpen);
163
- if (picked.async) {
164
- return void createAsync(api, name, done, picked.write);
165
- }
166
- const ok = api.ui.ops.runRepo(done, (top) => {
167
- api.ui.repo.createBranch(top, name);
168
- });
169
- if (!ok) return;
170
- api.ui.composer.closeCompose();
171
- api.ui.showFiles();
172
- refreshAfterWrite(api);
173
- if (!api.ui.status) api.ui.status = done;
174
- };
175
-
176
- const onPull = (api) => {
177
- if (!api.ui.commits.canCommit()) return;
178
- api.ui.ops.runWrite('pull', [], 'pulling', 'pulled', (extra) =>
179
- refreshAfterWrite(api, extra),
180
- );
181
- };
182
-
183
- const startPush = (api, force) => {
184
- if (!api.ui.commits.canCommit()) return;
185
- const done = force ? 'force pushed' : 'pushed';
186
- const kind = force ? 'force pushing' : 'pushing';
187
- const repo = api.ui.repo;
188
- const picked = pickRepoWrite(repo, 'push', api.ui.uiOpen);
189
- if (picked.async) {
190
- const write = (top) => picked.write(top, force);
191
- const after = () => refreshAfterWrite(api);
192
- return void api.ui.ops.runBusy(kind, done, write, after);
193
- }
194
- try {
195
- repo.push(api.ui.top, force);
196
- } catch (error) {
197
- if (error.rejected && !force) {
198
- api.ui.mode = 'confirmPush';
199
- api.ui.status = '';
6
+ class BranchController {
7
+ constructor(ui) {
8
+ this.ui = ui;
9
+ this.reset();
10
+ }
11
+
12
+ reset() {
13
+ this.branches = [];
14
+ this.dropName = '';
15
+ }
16
+
17
+ selected() {
18
+ return this.branches[this.ui.nav.branchCursor];
19
+ }
20
+
21
+ canWrite() {
22
+ return this.ui.nav.pane === 'branches' && this.ui.commits.canCommit();
23
+ }
24
+
25
+ loadBranches() {
26
+ const ui = this.ui;
27
+ try {
28
+ this.branches = ui.repo.listBranches(ui.top);
29
+ return true;
30
+ } catch (error) {
31
+ ui.status = error.message;
32
+ return false;
33
+ }
34
+ }
35
+
36
+ refreshAfterWrite(extra = {}) {
37
+ if (this.ui.repo.listBranches && this.loadBranches()) {
38
+ const last = this.branches.length - 1;
39
+ const nav = this.ui.nav;
40
+ if (nav.branchCursor > last) nav.branchCursor = Math.max(0, last);
41
+ }
42
+ this.ui.commits.refresh();
43
+ this.ui.refreshFromRepo({ keepEmpty: true, ...extra });
44
+ }
45
+
46
+ runWrite(name, args, kind, done) {
47
+ const after = (extra) => this.refreshAfterWrite(extra);
48
+ this.ui.ops.runWrite(name, args, kind, done, after);
49
+ }
50
+
51
+ onBranch() {
52
+ const ui = this.ui;
53
+ if (ui.mode === 'compose') return;
54
+ if (!ui.commits.canCommit()) return;
55
+ if (!ui.capabilities.branches || !ui.repo.listBranches) {
56
+ ui.status = 'read only';
57
+ return;
58
+ }
59
+ if (!this.loadBranches()) return;
60
+ const current = this.branches.findIndex((entry) => entry.current);
61
+ const nav = ui.nav;
62
+ nav.branchCursor = current < 0 ? 0 : current;
63
+ nav.pane = 'branches';
64
+ nav.resetListScroll('branches');
65
+ ui.status = '';
66
+ nav.clearSelection();
67
+ }
68
+
69
+ onBranchMove(delta) {
70
+ const nav = this.ui.nav;
71
+ if (!this.branches.length) {
72
+ this.ui.status = 'nothing to review';
73
+ return;
74
+ }
75
+ const last = this.branches.length - 1;
76
+ const next = Math.min(last, Math.max(0, nav.branchCursor + delta));
77
+ if (next === nav.branchCursor) return;
78
+ nav.branchCursor = next;
79
+ this.ui.status = '';
80
+ }
81
+
82
+ onCheckoutBranch() {
83
+ const ui = this.ui;
84
+ if (!ui.commits.canCommit()) return;
85
+ const entry = this.selected();
86
+ if (!entry) return;
87
+ if (entry.current) return void ui.showFiles();
88
+ const name = entry.name;
89
+ const after = (extra) => ui.refreshFromRepo({ keepEmpty: true, ...extra });
90
+ const leave = () => ui.showFiles();
91
+ const done = `checked out ${name}`;
92
+ ui.ops.runWrite('checkout', [name], 'checking out', done, after, leave);
93
+ }
94
+
95
+ finishCreateBranch() {
96
+ const ui = this.ui;
97
+ const editor = ui.composer.editor;
98
+ const name = editor ? editor.text.trim() : '';
99
+ if (!name) {
100
+ ui.status = 'empty branch name';
200
101
  return;
201
102
  }
202
- api.ui.status = error.message;
203
- return;
204
- }
205
- refreshAfterWrite(api);
206
- api.ui.status = done;
207
- };
208
-
209
- const onPush = (api) => startPush(api, false);
210
-
211
- const onForcePush = (api) => {
212
- api.ui.mode = 'review';
213
- startPush(api, true);
214
- };
215
-
216
- const cancelPush = (api) => {
217
- api.ui.mode = 'review';
218
- api.ui.status = '';
219
- };
220
-
221
- const reset = (state) => {
222
- state.branches = [];
223
- state.dropName = '';
224
- };
225
-
226
- const createBranchController = (ui) => {
227
- const state = {
228
- branches: [],
229
- dropName: '',
230
- };
231
- const api = { ui, state };
232
- return stateView(
233
- state,
234
- {
235
- reset: () => reset(state),
236
- onBranch: () => onBranch(api),
237
- onBranchMove: (delta) => onBranchMove(api, delta),
238
- onCheckoutBranch: () => onCheckoutBranch(api),
239
- onRebaseBranch: () => onRebaseBranch(api),
240
- onDropBranch: () => onDropBranch(api),
241
- cancelDropBranch: () => cancelDropBranch(api),
242
- confirmDropBranch: () => confirmDropBranch(api),
243
- onNewBranch: () => onNewBranch(api),
244
- finishCreateBranch: () => finishCreateBranch(api),
245
- onPull: () => onPull(api),
246
- onPush: () => onPush(api),
247
- onForcePush: () => onForcePush(api),
248
- cancelPush: () => cancelPush(api),
249
- },
250
- ['branches', 'dropName'],
251
- );
252
- };
253
-
254
- module.exports = { createBranchController };
103
+ const after = (extra) => this.refreshAfterWrite(extra);
104
+ const leave = () => {
105
+ ui.composer.closeCompose();
106
+ ui.showFiles();
107
+ };
108
+ const done = `created ${name}`;
109
+ ui.ops.runWrite(
110
+ 'createBranch',
111
+ [name],
112
+ 'creating branch',
113
+ done,
114
+ after,
115
+ leave,
116
+ );
117
+ }
118
+
119
+ onRebaseBranch() {
120
+ if (!this.canWrite()) return;
121
+ const entry = this.selected();
122
+ if (!entry || entry.current) return;
123
+ const onto = entry.name;
124
+ this.runWrite('rebase', [onto], 'rebasing', `rebased onto ${onto}`);
125
+ }
126
+
127
+ onDropBranch() {
128
+ if (!this.canWrite()) return;
129
+ const entry = this.selected();
130
+ if (!entry || entry.current) return;
131
+ this.dropName = entry.name;
132
+ this.ui.mode = 'confirmDrop';
133
+ this.ui.status = '';
134
+ }
135
+
136
+ cancelDropBranch() {
137
+ this.ui.mode = 'review';
138
+ this.dropName = '';
139
+ this.ui.status = '';
140
+ }
141
+
142
+ confirmDropBranch() {
143
+ const name = this.dropName;
144
+ this.ui.mode = 'review';
145
+ this.dropName = '';
146
+ if (name) this.runWrite('drop', [name], 'dropping', `dropped ${name}`);
147
+ }
148
+
149
+ onNewBranch() {
150
+ if (this.canWrite()) this.ui.composer.openCompose('branch', '');
151
+ }
152
+
153
+ onPull() {
154
+ if (this.ui.commits.canCommit()) {
155
+ this.runWrite('pull', [], 'pulling', 'pulled');
156
+ }
157
+ }
158
+
159
+ startPush(force) {
160
+ const ui = this.ui;
161
+ if (!ui.commits.canCommit()) return;
162
+ const done = force ? 'force pushed' : 'pushed';
163
+ const kind = force ? 'force pushing' : 'pushing';
164
+ const picked = pickRepoWrite(ui.repo, 'push', ui.uiOpen);
165
+ if (picked.async) {
166
+ const write = (top) => picked.write(top, force);
167
+ const after = () => this.refreshAfterWrite();
168
+ return void ui.ops.runBusy(kind, done, write, after);
169
+ }
170
+ try {
171
+ ui.repo.push(ui.top, force);
172
+ } catch (error) {
173
+ if (error.rejected && !force) {
174
+ ui.mode = 'confirmPush';
175
+ ui.status = '';
176
+ return;
177
+ }
178
+ ui.status = error.message;
179
+ return;
180
+ }
181
+ this.refreshAfterWrite();
182
+ ui.status = done;
183
+ }
184
+
185
+ onPush() {
186
+ this.startPush(false);
187
+ }
188
+
189
+ onForcePush() {
190
+ this.ui.mode = 'review';
191
+ this.startPush(true);
192
+ }
193
+
194
+ cancelPush() {
195
+ this.ui.mode = 'review';
196
+ this.ui.status = '';
197
+ }
198
+ }
199
+
200
+ module.exports = { BranchController };