reslop 0.2.4 → 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 (67) hide show
  1. package/CHANGELOG.md +14 -1
  2. package/README.md +1 -2
  3. package/lib/capabilities.js +0 -4
  4. package/lib/clipboard.js +39 -1
  5. package/lib/deps-diff.js +0 -3
  6. package/lib/deps.js +144 -176
  7. package/lib/diff/inline.js +66 -1
  8. package/lib/diff/unit.js +11 -28
  9. package/lib/editor.js +69 -9
  10. package/lib/files.js +17 -16
  11. package/lib/git-deps.js +58 -95
  12. package/lib/github.js +7 -7
  13. package/lib/gitlab.js +3 -3
  14. package/lib/highlight/core.js +11 -0
  15. package/lib/highlight/dot.js +2 -12
  16. package/lib/highlight/log.js +4 -11
  17. package/lib/highlight/txt.js +2 -12
  18. package/lib/keys.js +22 -12
  19. package/lib/manifest.js +0 -4
  20. package/lib/npm-commands.js +1 -22
  21. package/lib/remote.js +1 -7
  22. package/lib/render/branches.js +4 -13
  23. package/lib/render/chrome.js +85 -31
  24. package/lib/render/commits.js +95 -207
  25. package/lib/render/diff.js +31 -1
  26. package/lib/render/files.js +7 -16
  27. package/lib/render/frame.js +95 -110
  28. package/lib/render/notes.js +71 -16
  29. package/lib/render/npm.js +104 -18
  30. package/lib/render/primitives.js +108 -45
  31. package/lib/render/unit.js +4 -1
  32. package/lib/report-parse.js +0 -1
  33. package/lib/report-run.js +0 -1
  34. package/lib/report-test.js +40 -47
  35. package/lib/report-tools.js +0 -7
  36. package/lib/review-merge.js +101 -131
  37. package/lib/review.js +64 -77
  38. package/lib/select.js +52 -0
  39. package/lib/session/actions.js +23 -22
  40. package/lib/session/branches.js +5 -3
  41. package/lib/session/change-actions.js +173 -146
  42. package/lib/session/commit.js +32 -13
  43. package/lib/session/compose.js +120 -77
  44. package/lib/session/dispatch.js +36 -21
  45. package/lib/session/edit-click.js +57 -0
  46. package/lib/session/files-pane.js +24 -24
  47. package/lib/session/items.js +69 -89
  48. package/lib/session/lifecycle.js +31 -96
  49. package/lib/session/load.js +51 -58
  50. package/lib/session/navigation.js +105 -96
  51. package/lib/session/npm.js +158 -77
  52. package/lib/session/ops.js +192 -51
  53. package/lib/session/pointer.js +11 -5
  54. package/lib/session/progress.js +9 -6
  55. package/lib/session/review.js +35 -54
  56. package/lib/session/tasks.js +292 -0
  57. package/lib/session/terminal.js +13 -17
  58. package/lib/session/unit.js +3 -4
  59. package/lib/session/update.js +76 -97
  60. package/lib/session/view.js +17 -14
  61. package/lib/session/watch.js +47 -27
  62. package/lib/session.js +34 -79
  63. package/lib/update.js +1 -5
  64. package/lib/utilities.js +21 -1
  65. package/lib/wrap.js +15 -0
  66. package/package.json +1 -1
  67. package/lib/session/todos.js +0 -293
@@ -1,73 +1,66 @@
1
1
  'use strict';
2
2
 
3
- const accessors = require('./accessors.js');
4
- const { stateView } = accessors;
5
-
6
3
  const utilities = require('../utilities.js');
7
4
  const { isAbort: isAbortError } = utilities;
8
5
 
9
- const createLoadCoordinator = () => {
10
- const state = {
11
- gen: 0,
12
- abort: null,
13
- promise: null,
14
- pendingExtras: false,
15
- didLoad: false,
16
- };
6
+ class LoadCoordinator {
7
+ constructor() {
8
+ this.gen = 0;
9
+ this.abortController = null;
10
+ this.promise = null;
11
+ this.pendingExtras = false;
12
+ this.didLoad = false;
13
+ }
14
+
15
+ get signal() {
16
+ return this.abortController?.signal;
17
+ }
17
18
 
18
- const bump = () => {
19
- state.gen += 1;
20
- state.abort?.abort();
21
- state.abort = new AbortController();
22
- return state.gen;
23
- };
19
+ bump() {
20
+ this.gen += 1;
21
+ this.abortController?.abort();
22
+ this.abortController = new AbortController();
23
+ return this.gen;
24
+ }
24
25
 
25
- const isCurrent = (gen, done = false) => gen === state.gen && !done;
26
- const accept = isCurrent;
26
+ isCurrent(gen, done = false) {
27
+ return gen === this.gen && !done;
28
+ }
27
29
 
28
- const abort = () => {
29
- state.abort?.abort();
30
- };
30
+ accept(gen, done = false) {
31
+ return this.isCurrent(gen, done);
32
+ }
31
33
 
32
- const reset = () => {
33
- abort();
34
- state.gen += 1;
35
- state.abort = null;
36
- state.promise = null;
37
- state.pendingExtras = false;
38
- state.didLoad = false;
39
- };
34
+ abort() {
35
+ this.abortController?.abort();
36
+ }
40
37
 
41
- const tag = (loaded, gen) => ({ ...loaded, generation: gen });
38
+ reset() {
39
+ this.abort();
40
+ this.gen += 1;
41
+ this.abortController = null;
42
+ this.promise = null;
43
+ this.pendingExtras = false;
44
+ this.didLoad = false;
45
+ }
46
+ }
42
47
 
43
- const fetchSnapshot = async (repo, cwd, paths, options) => {
44
- if (repo.loadAsync) return repo.loadAsync(cwd, paths, options);
45
- return repo.load(cwd, paths, options);
46
- };
48
+ const tagLoaded = (loaded, gen) => ({ ...loaded, generation: gen });
47
49
 
48
- const fetchExtras = async (repo, loaded, extra) => {
49
- if (!repo.loadExtras) return null;
50
- return repo.loadExtras(loaded, extra);
51
- };
50
+ const fetchSnapshot = async (repo, cwd, paths, options) => {
51
+ if (repo.loadAsync) return repo.loadAsync(cwd, paths, options);
52
+ return repo.load(cwd, paths, options);
53
+ };
52
54
 
53
- return stateView(
54
- state,
55
- {
56
- get signal() {
57
- return state.abort?.signal;
58
- },
59
- bump,
60
- isCurrent,
61
- accept,
62
- abort,
63
- reset,
64
- tag,
65
- fetchSnapshot,
66
- fetchExtras,
67
- },
68
- ['promise', 'pendingExtras', 'didLoad'],
69
- ['gen'],
70
- );
55
+ const fetchExtras = async (repo, loaded, extra) => {
56
+ if (!repo.loadExtras) return null;
57
+ return repo.loadExtras(loaded, extra);
71
58
  };
72
59
 
73
- module.exports = { isAbortError, createLoadCoordinator };
60
+ module.exports = {
61
+ isAbortError,
62
+ LoadCoordinator,
63
+ tagLoaded,
64
+ fetchSnapshot,
65
+ fetchExtras,
66
+ };
@@ -1,107 +1,116 @@
1
1
  'use strict';
2
2
 
3
3
  const files = require('../files.js');
4
- const { listPath, isTodoItem, isTodosEntry, TODO_FILE } = files;
5
-
6
- const initialState = (options = {}) => ({
7
- pane: options.startPane ?? 'files',
8
- index: 0,
9
- fileCursor: 0,
10
- branchCursor: 0,
11
- commitCursor: 0,
12
- npmCursor: 0,
13
- scroll: 0,
14
- listScroll: 0,
15
- reviewPath: null,
16
- fileScope: 'diff',
17
- unitLine: 0,
18
- selection: null,
19
- mouseAnchor: null,
20
- pendingClick: null,
21
- lastClick: null,
22
- todoOpen: false,
23
- todoFocus: 0,
24
- });
25
-
26
- const clampIndex = (nav, length) => {
27
- if (!length) {
28
- nav.index = 0;
29
- return;
4
+ const { listPath, isTaskItem, isTasksEntry, TASKS_FILE } = files;
5
+
6
+ const LIST_PANES = ['files', 'branches', 'commits', 'npm'];
7
+
8
+ const freshListScroll = () =>
9
+ Object.fromEntries(LIST_PANES.map((pane) => [pane, 0]));
10
+
11
+ class Navigation {
12
+ constructor(options = {}) {
13
+ this.reset(options.startPane ?? 'files');
30
14
  }
31
- if (nav.index < 0) nav.index = 0;
32
- if (nav.index >= length) nav.index = length - 1;
33
- };
34
-
35
- const current = (nav, items, todoItem) => {
36
- if (nav.todoOpen) return todoItem;
37
- if (nav.pane === 'unit' && nav.reviewPath) {
38
- const item = items[nav.index];
39
- if (item && listPath(item) === nav.reviewPath) return item;
40
- for (const entry of items) {
41
- if (listPath(entry) === nav.reviewPath) return entry;
15
+
16
+ reset(startPane = this.pane) {
17
+ this.pane = startPane;
18
+ this.index = 0;
19
+ this.fileCursor = 0;
20
+ this.branchCursor = 0;
21
+ this.commitCursor = 0;
22
+ this.npmCursor = 0;
23
+ this.scroll = 0;
24
+ this.listScrollByPane = freshListScroll();
25
+ this.reviewPath = null;
26
+ this.fileScope = 'diff';
27
+ this.unitLine = 0;
28
+ this.selection = null;
29
+ this.mouseAnchor = null;
30
+ this.pendingClick = null;
31
+ this.lastClick = null;
32
+ this.tasksOpen = false;
33
+ this.tasksFocus = 0;
34
+ }
35
+
36
+ clampIndex(length) {
37
+ if (!length) {
38
+ this.index = 0;
39
+ return;
42
40
  }
43
- return null;
41
+ if (this.index < 0) this.index = 0;
42
+ if (this.index >= length) this.index = length - 1;
44
43
  }
45
- return items[nav.index] ?? null;
46
- };
47
-
48
- const syncReviewPath = (nav, item) => {
49
- if (nav.pane !== 'diff' && nav.pane !== 'unit') return;
50
- if (nav.pane === 'unit' && nav.reviewPath) return;
51
- nav.reviewPath = item ? listPath(item) : null;
52
- };
53
-
54
- const clampFileCursor = (nav, length) => {
55
- if (!length) {
56
- nav.fileCursor = 0;
57
- return;
44
+
45
+ current(items, tasksItem) {
46
+ if (this.tasksOpen) return tasksItem;
47
+ if (this.pane === 'unit' && this.reviewPath) {
48
+ const item = items[this.index];
49
+ if (item && listPath(item) === this.reviewPath) return item;
50
+ for (const entry of items) {
51
+ if (listPath(entry) === this.reviewPath) return entry;
52
+ }
53
+ return null;
54
+ }
55
+ return items[this.index] ?? null;
58
56
  }
59
- if (nav.fileCursor >= length) nav.fileCursor = length - 1;
60
- };
61
57
 
62
- const followReviewPath = (nav, fileList, item) => {
63
- if (!fileList.length) {
64
- nav.fileCursor = 0;
65
- return;
58
+ syncReviewPath(item) {
59
+ if (this.pane !== 'diff' && this.pane !== 'unit') return;
60
+ if (this.pane === 'unit' && this.reviewPath) return;
61
+ this.reviewPath = item ? listPath(item) : null;
66
62
  }
67
- let idx = fileList.findIndex(
68
- (entry) => !isTodosEntry(entry) && entry.path === nav.reviewPath,
69
- );
70
- if (nav.reviewPath === TODO_FILE || isTodoItem(item)) {
71
- idx = fileList.findIndex((entry) => isTodosEntry(entry));
63
+
64
+ clampFileCursor(length) {
65
+ if (!length) {
66
+ this.fileCursor = 0;
67
+ return;
68
+ }
69
+ if (this.fileCursor >= length) this.fileCursor = length - 1;
72
70
  }
73
- if (idx >= 0) {
74
- nav.fileCursor = idx;
75
- return;
71
+
72
+ followReviewPath(fileList, item) {
73
+ if (!fileList.length) {
74
+ this.fileCursor = 0;
75
+ return;
76
+ }
77
+ let idx = fileList.findIndex(
78
+ (entry) => !isTasksEntry(entry) && entry.path === this.reviewPath,
79
+ );
80
+ if (this.reviewPath === TASKS_FILE || isTaskItem(item)) {
81
+ idx = fileList.findIndex((entry) => isTasksEntry(entry));
82
+ }
83
+ if (idx >= 0) {
84
+ this.fileCursor = idx;
85
+ return;
86
+ }
87
+ this.clampFileCursor(fileList.length);
88
+ }
89
+
90
+ restoreFileCursor(fileList) {
91
+ if (this.pane !== 'files') return;
92
+ this.followReviewPath(fileList, null);
93
+ }
94
+
95
+ clearSelection() {
96
+ this.selection = null;
97
+ this.mouseAnchor = null;
98
+ this.pendingClick = null;
99
+ }
100
+
101
+ get listScroll() {
102
+ return this.listScrollByPane[this.pane] ?? 0;
103
+ }
104
+
105
+ set listScroll(value) {
106
+ if (!LIST_PANES.includes(this.pane)) return;
107
+ this.listScrollByPane[this.pane] = value ?? 0;
76
108
  }
77
- clampFileCursor(nav, fileList.length);
78
- };
79
-
80
- const restoreFileCursor = (nav, fileList) => {
81
- if (nav.pane !== 'files') return;
82
- followReviewPath(nav, fileList, null);
83
- };
84
-
85
- const clearSelection = (nav) => {
86
- nav.selection = null;
87
- nav.mouseAnchor = null;
88
- nav.pendingClick = null;
89
- };
90
-
91
- const createNavigation = (options = {}) => {
92
- const nav = initialState(options);
93
- nav.reset = (startPane) => {
94
- const pane = startPane ?? nav.pane;
95
- Object.assign(nav, initialState({ startPane: pane }));
96
- };
97
- nav.clampIndex = (length) => clampIndex(nav, length);
98
- nav.current = (items, todoItem) => current(nav, items, todoItem);
99
- nav.syncReviewPath = (item) => syncReviewPath(nav, item);
100
- nav.clampFileCursor = (length) => clampFileCursor(nav, length);
101
- nav.followReviewPath = (list, item) => followReviewPath(nav, list, item);
102
- nav.restoreFileCursor = (list) => restoreFileCursor(nav, list);
103
- nav.clearSelection = () => clearSelection(nav);
104
- return nav;
105
- };
106
-
107
- module.exports = { createNavigation };
109
+
110
+ resetListScroll(pane = this.pane) {
111
+ if (!LIST_PANES.includes(pane)) return;
112
+ this.listScrollByPane[pane] = 0;
113
+ }
114
+ }
115
+
116
+ module.exports = { Navigation };