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
package/lib/session.js CHANGED
@@ -1,57 +1,52 @@
1
1
  'use strict';
2
2
 
3
3
  const render = require('./render/render.js');
4
- const keys = require('./keys.js');
5
- const review = require('./review.js');
6
- const files = require('./files.js');
7
- const { makeTodoItem } = files;
8
4
  const { renderFrame } = render;
5
+ const keys = require('./keys.js');
9
6
  const { decodeChunk } = keys;
7
+ const review = require('./review.js');
10
8
  const { AUTOSAVE_MS, hasNotes } = review;
9
+ const files = require('./files.js');
10
+ const { makeTaskItem } = files;
11
11
  const capabilities = require('./capabilities.js');
12
+ const { sessionCapabilities } = capabilities;
12
13
  const actions = require('./session/actions.js');
13
14
  const { LIST_PANES } = actions;
14
- const { sessionCapabilities } = capabilities;
15
15
  const terminal = require('./session/terminal.js');
16
- const { createTerminal, LEAVE_TERM } = terminal;
16
+ const { Terminal, LEAVE_TERM } = terminal;
17
17
  const load = require('./session/load.js');
18
- const { createLoadCoordinator } = load;
18
+ const { LoadCoordinator } = load;
19
19
  const items = require('./session/items.js');
20
- const { createItemCollection } = items;
20
+ const { ItemCollection } = items;
21
21
  const navigation = require('./session/navigation.js');
22
- const { createNavigation } = navigation;
22
+ const { Navigation } = navigation;
23
23
  const sessionReview = require('./session/review.js');
24
- const { createReviewController } = sessionReview;
24
+ const { ReviewController } = sessionReview;
25
25
  const update = require('./session/update.js');
26
- const { createUpdateCoordinator } = update;
26
+ const { UpdateCoordinator } = update;
27
27
  const progress = require('./session/progress.js');
28
- const { createProgress } = progress;
28
+ const { Progress } = progress;
29
29
  const compose = require('./session/compose.js');
30
- const { createComposer } = compose;
30
+ const { Composer } = compose;
31
31
  const ops = require('./session/ops.js');
32
- const { createOpsRunner } = ops;
33
- const changeActions = require('./session/change-actions.js');
34
- const { createChangeActions } = changeActions;
32
+ const { OpsRunner } = ops;
35
33
  const commit = require('./session/commit.js');
36
- const { createCommitController } = commit;
34
+ const { CommitController } = commit;
37
35
  const branches = require('./session/branches.js');
38
- const { createBranchController } = branches;
36
+ const { BranchController } = branches;
39
37
  const npm = require('./session/npm.js');
40
- const { createNpmController } = npm;
38
+ const { NpmController } = npm;
41
39
  const accessors = require('./session/accessors.js');
42
- const { bindAccessors, bindGetters, bindAlias } = accessors;
40
+ const { bindAccessors, bindGetters } = accessors;
43
41
  const view = require('./session/view.js');
44
- const { createView } = view;
45
42
  const filesPane = require('./session/files-pane.js');
46
- const { createFilesPane } = filesPane;
47
43
  const lifecycle = require('./session/lifecycle.js');
48
- const { createLifecycle } = lifecycle;
49
- const pointer = require('./session/pointer.js');
50
- const { createPointer } = pointer;
44
+ const { Lifecycle } = lifecycle;
51
45
  const dispatch = require('./session/dispatch.js');
52
- const { createDispatcher, createInput } = dispatch;
46
+ const { dispatchAction, confirmChoice, handleEvent } = dispatch;
47
+ const dashboard = require('./session/dashboard.js');
48
+ const { Dashboard } = dashboard;
53
49
 
54
- const CURSOR_BLINK_MS = 500;
55
50
  const PROGRESS_MS = 160;
56
51
 
57
52
  const NAV_FIELDS = [
@@ -69,19 +64,17 @@ const NAV_FIELDS = [
69
64
  'selection',
70
65
  'mouseAnchor',
71
66
  'pendingClick',
72
- 'todoOpen',
73
- 'todoFocus',
67
+ 'tasksOpen',
68
+ 'tasksFocus',
74
69
  ];
75
70
 
76
71
  const COMPOSER_FIELDS = [
77
72
  'editor',
78
73
  'composeKind',
79
74
  'commitKind',
80
- 'composeTodoId',
81
- 'composeBaseline',
75
+ 'composeTaskId',
82
76
  'templateIndex',
83
77
  'templateFocus',
84
- 'blinkOn',
85
78
  ];
86
79
 
87
80
  const assignOptions = (session, options) => {
@@ -92,11 +85,6 @@ const assignOptions = (session, options) => {
92
85
  session.stdout = options.stdout;
93
86
  session.proc = options.proc ?? process;
94
87
  session.color = options.color ?? true;
95
- session.getSize = () => {
96
- const width = session.stdout.columns ?? 80;
97
- const height = session.stdout.rows ?? 24;
98
- return { width, height };
99
- };
100
88
  session.rev = options.rev ?? null;
101
89
  session.revShort = '';
102
90
  session.sourceLabel = options.sourceLabel ?? '';
@@ -109,163 +97,69 @@ const assignOptions = (session, options) => {
109
97
  session.outdatedMap = options.outdatedMap;
110
98
  session.auditMap = options.auditMap;
111
99
  session.updateOpts = options.update;
112
- session.term = createTerminal({
113
- stdin: session.stdin,
114
- stdout: session.stdout,
115
- proc: session.proc,
116
- });
117
- session.loader = createLoadCoordinator();
118
- session.collection = createItemCollection();
119
- session.nav = createNavigation({
120
- startPane: options.startPane ?? 'files',
121
- });
122
- session.review = createReviewController();
123
- session.progress = createProgress(
124
- session.term,
125
- () => session.tickProgress(),
126
- PROGRESS_MS,
127
- );
128
- };
129
-
130
- const assignComposer = (session) => {
131
- session.composer = createComposer({
132
- nav: session.nav,
133
- review: session.review,
134
- ui: session,
135
- restartBlink: () => {
136
- if (!session.term.hasTimer('blink')) return;
137
- session.term.restartTimer(
138
- 'blink',
139
- () => session.tickBlink(),
140
- CURSOR_BLINK_MS,
141
- );
142
- },
143
- });
100
+ session.dashboardHome = options.startPane === 'dashboard';
144
101
  };
145
102
 
146
- const assignControllers = (session) => {
147
- session.ops = createOpsRunner(session);
148
- session.changeActions = createChangeActions(session);
149
- session.commits = createCommitController(session);
150
- session.gitBranches = createBranchController(session);
151
- session.npm = createNpmController(session);
103
+ const assignParts = (session, options) => {
104
+ const { stdin, stdout, proc } = session;
105
+ session.term = new Terminal({ stdin, stdout, proc });
106
+ session.loader = new LoadCoordinator();
107
+ session.collection = new ItemCollection();
108
+ session.nav = new Navigation({ startPane: options.startPane ?? 'files' });
109
+ session.review = new ReviewController();
110
+ const tick = () => session.tickProgress();
111
+ session.progress = new Progress(session.term, tick, PROGRESS_MS);
112
+ session.updater = new UpdateCoordinator(session);
113
+ session.composer = new Composer(session);
114
+ session.ops = new OpsRunner(session);
115
+ session.commits = new CommitController(session);
116
+ session.gitBranches = new BranchController(session);
117
+ session.npm = new NpmController(session);
118
+ session.dashboard = new Dashboard(session);
119
+ session.lifecycle = new Lifecycle(session);
152
120
  };
153
121
 
154
- const bindSessionAccessors = (session) => {
122
+ const bindFields = (session) => {
155
123
  bindAccessors(session, session.nav, NAV_FIELDS);
156
- bindAccessors(session, session.composer.state, COMPOSER_FIELDS);
124
+ bindAccessors(session, session.composer, COMPOSER_FIELDS);
157
125
  bindAccessors(session, session.loader, ['pendingExtras']);
158
- bindAlias(
159
- session,
160
- 'loadPromise',
161
- () => session.loader.promise,
162
- (value) => {
163
- session.loader.promise = value;
164
- },
165
- );
126
+ bindGetters(session, session.loader, ['didLoad']);
166
127
  bindAccessors(session, session.collection, ['items']);
167
128
  bindGetters(session, session.collection, ['dismissed']);
168
- bindAccessors(session, session.updater, ['installPromise']);
129
+ bindGetters(session, session.updater, ['installPromise']);
169
130
  bindAccessors(session, session.ops, ['gitBusy', 'busy']);
170
131
  bindAccessors(session, session.gitBranches, ['branches', 'dropName']);
171
132
  bindGetters(session, session.term, ['lastFrame', 'lastSize']);
172
- bindAlias(session, 'loadGen', () => session.loader.gen);
173
- bindAlias(
174
- session,
175
- 'didLoad',
176
- () => session.loader.didLoad,
177
- (value) => {
178
- session.loader.didLoad = value;
179
- if (value) session.updater.maybePrompt();
180
- },
181
- );
182
- bindAlias(session, 'notes', () => session.review.store);
183
- bindAlias(session, 'didResumeReview', () => session.review.didResume);
184
- bindAlias(
185
- session,
186
- 'importedRemoteNotes',
187
- () => session.review.importedRemote,
188
- );
189
- bindAlias(
190
- session,
191
- 'updateOffer',
192
- () => session.updater.offer,
193
- (value) => {
194
- session.updater.offer = value;
195
- },
196
- );
197
- bindAlias(session, 'updateFrom', () => session.updater.from);
198
- bindAlias(session, 'updateTo', () => session.updater.to);
199
- bindAlias(session, 'updatePromise', () => session.updater.checkPromise);
200
- };
201
-
202
- const bindViewer = (session) => {
203
- session.viewer = createView({
204
- nav: session.nav,
205
- composer: session.composer,
206
- collection: session.collection,
207
- review: session.review,
208
- gitBranches: session.gitBranches,
209
- commits: session.commits,
210
- npm: session.npm,
211
- updater: session.updater,
212
- ui: session,
213
- });
214
- };
215
-
216
- const bindLifecycle = (session) => {
217
- session.lifecycle = createLifecycle({
218
- loader: session.loader,
219
- collection: session.collection,
220
- review: session.review,
221
- nav: session.nav,
222
- ops: session.ops,
223
- updater: session.updater,
224
- loadConfig: {
225
- repo: session.repo,
226
- cwd: session.cwd,
227
- paths: session.paths,
228
- audit: session.audit,
229
- outdatedMap: session.outdatedMap,
230
- auditMap: session.auditMap,
231
- },
232
- ui: session,
233
- });
234
- };
235
-
236
- const bindDispatch = (session) => {
237
- session.dispatcher = createDispatcher(session);
238
- session.pointer = createPointer(session);
239
- session.input = createInput(session);
240
- };
241
-
242
- const composeSession = (session, options) => {
243
- assignOptions(session, options);
244
- session.updater = createUpdateCoordinator(session);
245
- assignComposer(session);
246
- assignControllers(session);
247
- bindSessionAccessors(session);
248
- bindViewer(session);
249
- session.filesPane = createFilesPane(session);
250
- bindLifecycle(session);
251
- bindDispatch(session);
252
133
  };
253
134
 
254
135
  class Session {
255
136
  constructor(options) {
256
- composeSession(this, options);
137
+ assignOptions(this, options);
138
+ assignParts(this, options);
139
+ bindFields(this);
257
140
  this.resetState();
258
141
  }
259
142
 
143
+ get notes() {
144
+ return this.review.store;
145
+ }
146
+
147
+ getSize() {
148
+ const width = this.stdout.columns ?? 80;
149
+ const height = this.stdout.rows ?? 24;
150
+ return { width, height };
151
+ }
152
+
260
153
  resetState() {
261
- if (this.collection) this.collection.reset();
262
- if (this.nav) this.nav.reset();
263
- if (this.review) this.review.reset();
264
- if (this.composer) this.composer.reset();
265
- if (this.ops) this.ops.reset();
266
- if (this.gitBranches) this.gitBranches.reset();
267
- if (this.commits) this.commits.reset();
268
- if (this.npm) this.npm.reset();
154
+ this.collection.reset();
155
+ this.nav.reset();
156
+ this.review.reset();
157
+ this.composer.reset();
158
+ this.ops.reset();
159
+ this.gitBranches.reset();
160
+ this.commits.reset();
161
+ this.npm.reset();
162
+ this.dashboard.reset();
269
163
  this.top = this.cwd;
270
164
  this.branch = '';
271
165
  this.status = '';
@@ -273,18 +167,18 @@ class Session {
273
167
  this.done = false;
274
168
  this.exitCode = 0;
275
169
  this.mode = 'review';
276
- this.todoItem = makeTodoItem();
170
+ this.tasksItem = makeTaskItem();
277
171
  this.progressFrame = 0;
278
172
  this.emptyReview = false;
279
173
  this.loadError = null;
280
174
  this.uiOpen = false;
281
175
  this.finishReadLoop = null;
282
- if (this.lifecycle) this.lifecycle.stopWatch();
283
- if (this.lifecycle) this.lifecycle.clearNpmExtras();
284
- if (this.term) this.term.resetCache();
285
- if (this.loader) this.loader.reset();
286
- if (this.updater) this.updater.reset();
287
- if (this.progress) this.progress.clear();
176
+ this.lifecycle.stopWatch();
177
+ this.lifecycle.clearNpmExtras();
178
+ this.term.resetCache();
179
+ this.loader.reset();
180
+ this.updater.reset();
181
+ this.progress.clear();
288
182
  }
289
183
 
290
184
  ensureRepo() {
@@ -316,13 +210,8 @@ class Session {
316
210
  this.lifecycle.ignoreWatch(ms);
317
211
  }
318
212
 
319
- applyLoaded(loaded) {
320
- return this.lifecycle.applyLoaded(loaded);
321
- }
322
-
323
213
  paint() {
324
- if (!this.uiOpen) return;
325
- this.draw();
214
+ if (this.uiOpen) this.draw();
326
215
  }
327
216
 
328
217
  draw() {
@@ -336,58 +225,66 @@ class Session {
336
225
  if (LIST_PANES.includes(this.pane)) {
337
226
  this.nav.listScroll = frame.listScroll;
338
227
  }
339
- if (this.nav.todoOpen) this.nav.scroll = frame.scroll;
228
+ if (this.nav.tasksOpen) this.nav.scroll = frame.scroll;
229
+ const editScroll = frame.cursor && frame.cursor.scroll;
230
+ if (this.editor && typeof editScroll === 'number') {
231
+ this.editor.scrollCol = editScroll;
232
+ }
340
233
  const composing = this.mode === 'compose';
341
- const cursor = composing && this.blinkOn ? frame.cursor : null;
342
- this.term.paint(frame, size, cursor);
234
+ this.term.paint(frame, size, composing ? frame.cursor : null);
235
+ this.scheduleAutosave();
236
+ this.dashboard.afterDraw();
343
237
  }
344
238
 
345
- view() {
346
- return this.viewer.view();
239
+ scheduleAutosave() {
240
+ if (!this.finishReadLoop) return;
241
+ const dirty = this.notes && this.notes.dirty;
242
+ if (!dirty && this.composeKind === null) return;
243
+ this.term.later('save', () => this.autosave(), AUTOSAVE_MS);
347
244
  }
348
245
 
349
- fileList() {
350
- return this.viewer.fileList();
351
- }
352
-
353
- counts() {
354
- return this.viewer.counts();
246
+ view() {
247
+ return view.view(this);
355
248
  }
356
249
 
357
- viewStatus() {
358
- return this.viewer.viewStatus();
250
+ fileList() {
251
+ return view.fileList(this);
359
252
  }
360
253
 
361
254
  current() {
362
- return this.nav.current(this.items, this.todoItem);
255
+ return this.nav.current(this.items, this.tasksItem);
363
256
  }
364
257
 
365
258
  fileCursorEntry() {
366
- return this.changeActions.fileCursorEntry();
259
+ return filesPane.fileCursorEntry(this);
367
260
  }
368
261
 
369
262
  clampIndex() {
370
- this.filesPane.clampIndex();
263
+ filesPane.clampIndex(this);
371
264
  }
372
265
 
373
266
  syncReviewPath() {
374
- this.filesPane.syncReviewPath();
267
+ filesPane.syncReviewPath(this);
375
268
  }
376
269
 
377
270
  syncFileCursor() {
378
- this.filesPane.syncFileCursor();
271
+ filesPane.syncFileCursor(this);
379
272
  }
380
273
 
381
274
  showFiles() {
382
- this.filesPane.showFiles();
275
+ filesPane.showFiles(this);
383
276
  }
384
277
 
385
278
  dispatch(action) {
386
- this.dispatcher.dispatch(action);
279
+ dispatchAction(this, action);
280
+ }
281
+
282
+ confirmChoice(key) {
283
+ confirmChoice(this, key);
387
284
  }
388
285
 
389
286
  handleEvent(event) {
390
- this.input.handleEvent(event);
287
+ handleEvent(this, event);
391
288
  }
392
289
 
393
290
  pushInput(text) {
@@ -415,7 +312,7 @@ class Session {
415
312
  this.status = result.error.message;
416
313
  return false;
417
314
  }
418
- if (this.lifecycle) this.lifecycle.noteReviewStamp();
315
+ this.lifecycle.noteReviewStamp();
419
316
  return result.wrote;
420
317
  }
421
318
 
@@ -427,23 +324,7 @@ class Session {
427
324
  }
428
325
 
429
326
  selectTemplate(index) {
430
- this.runComposeCommand(this.composer.selectTemplate(index));
431
- }
432
-
433
- idleNoteText() {
434
- return this.composer.idleNoteText();
435
- }
436
-
437
- shownTemplates() {
438
- return this.composer.shownTemplates();
439
- }
440
-
441
- startDraftCompose() {
442
- this.composer.startDraftCompose();
443
- }
444
-
445
- tickBlink() {
446
- this.composer.tickBlink();
327
+ this.runComposeCommand(this.composer.templates.selectTemplate(index));
447
328
  }
448
329
 
449
330
  autosave() {
@@ -530,6 +411,7 @@ class Session {
530
411
  if (settled) return;
531
412
  settled = true;
532
413
  this.lifecycle.stopWatch();
414
+ this.dashboard.stop();
533
415
  this.term.stopListening();
534
416
  this.progress.clear();
535
417
  this.term.clearTimers();
@@ -546,18 +428,11 @@ class Session {
546
428
  if (this.done) return void finish();
547
429
  this.draw();
548
430
  };
549
- this.term.startListening({
550
- onData,
551
- onResize: () => this.draw(),
552
- });
553
- this.term.startTimer('save', () => this.autosave(), AUTOSAVE_MS);
554
- this.term.startTimer('blink', () => this.tickBlink(), CURSOR_BLINK_MS);
431
+ this.term.startListening({ onData, onResize: () => this.draw() });
555
432
  this.lifecycle.startWatch();
433
+ if (this.dashboardHome) this.dashboard.start();
556
434
  });
557
435
  }
558
436
  }
559
437
 
560
- module.exports = {
561
- LEAVE_TERM,
562
- Session,
563
- };
438
+ module.exports = { LEAVE_TERM, Session };