reslop 0.2.5 → 0.2.7

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 (114) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/LICENSE +1 -1
  3. package/README.md +11 -11
  4. package/bin/reslop.js +3 -8
  5. package/lib/ansi.js +72 -19
  6. package/lib/api.js +1 -1
  7. package/lib/capabilities.js +8 -8
  8. package/lib/cli.js +61 -75
  9. package/lib/clipboard.js +39 -47
  10. package/lib/dashboard/git.js +128 -0
  11. package/lib/dashboard/model.js +357 -0
  12. package/lib/dashboard/npm.js +290 -0
  13. package/lib/dashboard/tree.js +278 -0
  14. package/lib/deps-diff.js +197 -402
  15. package/lib/deps.js +113 -240
  16. package/lib/detect.js +8 -18
  17. package/lib/diff/align.js +41 -113
  18. package/lib/diff/diff.js +12 -43
  19. package/lib/diff/display.js +25 -36
  20. package/lib/diff/edit.js +6 -20
  21. package/lib/diff/inline.js +76 -144
  22. package/lib/diff/items.js +33 -47
  23. package/lib/diff/parse.js +28 -56
  24. package/lib/diff/patch.js +12 -33
  25. package/lib/diff/unit.js +79 -178
  26. package/lib/editor.js +52 -69
  27. package/lib/files.js +79 -91
  28. package/lib/find.js +61 -0
  29. package/lib/git-branches.js +254 -416
  30. package/lib/git-deps.js +148 -272
  31. package/lib/git-reword-todo.js +5 -13
  32. package/lib/git-worktree.js +161 -214
  33. package/lib/git.js +21 -49
  34. package/lib/github.js +67 -181
  35. package/lib/gitlab.js +40 -90
  36. package/lib/highlight/bash.js +55 -177
  37. package/lib/highlight/core.js +155 -141
  38. package/lib/highlight/css.js +25 -58
  39. package/lib/highlight/csv.js +19 -37
  40. package/lib/highlight/dart.js +72 -213
  41. package/lib/highlight/dot.js +14 -14
  42. package/lib/highlight/html.js +42 -63
  43. package/lib/highlight/js.js +177 -506
  44. package/lib/highlight/json.js +17 -37
  45. package/lib/highlight/log.js +19 -25
  46. package/lib/highlight/txt.js +7 -10
  47. package/lib/highlight.js +17 -46
  48. package/lib/keys.js +75 -83
  49. package/lib/manifest.js +67 -126
  50. package/lib/npm-commands.js +120 -169
  51. package/lib/remote.js +140 -190
  52. package/lib/render/branches.js +63 -61
  53. package/lib/render/chrome.js +412 -347
  54. package/lib/render/commits.js +160 -361
  55. package/lib/render/dash-activity.js +212 -0
  56. package/lib/render/dash-blocks.js +496 -0
  57. package/lib/render/dash-table.js +295 -0
  58. package/lib/render/dashboard.js +62 -0
  59. package/lib/render/diff.js +123 -258
  60. package/lib/render/files.js +60 -86
  61. package/lib/render/frame.js +82 -117
  62. package/lib/render/notes.js +150 -210
  63. package/lib/render/npm.js +213 -177
  64. package/lib/render/packages.js +93 -0
  65. package/lib/render/present.js +4 -11
  66. package/lib/render/primitives.js +77 -172
  67. package/lib/render/render.js +5 -14
  68. package/lib/render/report.js +43 -0
  69. package/lib/render/repos.js +226 -0
  70. package/lib/render/search.js +25 -0
  71. package/lib/render/tiles.js +355 -0
  72. package/lib/render/unit.js +15 -31
  73. package/lib/report-model.js +110 -33
  74. package/lib/report-parse.js +56 -37
  75. package/lib/report-render.js +102 -59
  76. package/lib/report-run.js +87 -77
  77. package/lib/report-test.js +221 -99
  78. package/lib/report-tools.js +96 -154
  79. package/lib/review-merge.js +33 -41
  80. package/lib/review.js +69 -129
  81. package/lib/runs.js +225 -0
  82. package/lib/select.js +53 -91
  83. package/lib/session/accessors.js +14 -21
  84. package/lib/session/actions.js +189 -65
  85. package/lib/session/branches.js +164 -222
  86. package/lib/session/change-actions.js +49 -119
  87. package/lib/session/commit.js +298 -352
  88. package/lib/session/compose.js +572 -715
  89. package/lib/session/dashboard.js +530 -0
  90. package/lib/session/dispatch.js +197 -171
  91. package/lib/session/files-pane.js +92 -45
  92. package/lib/session/find.js +94 -0
  93. package/lib/session/items.js +6 -17
  94. package/lib/session/lifecycle.js +420 -466
  95. package/lib/session/load.js +1 -14
  96. package/lib/session/navigation.js +4 -2
  97. package/lib/session/npm.js +403 -420
  98. package/lib/session/ops.js +5 -13
  99. package/lib/session/packages.js +143 -0
  100. package/lib/session/pointer.js +30 -14
  101. package/lib/session/progress.js +39 -30
  102. package/lib/session/review.js +1 -3
  103. package/lib/session/tasks.js +277 -236
  104. package/lib/session/templates.js +51 -59
  105. package/lib/session/terminal.js +85 -132
  106. package/lib/session/view.js +59 -80
  107. package/lib/session/watch.js +201 -212
  108. package/lib/session/workspace.js +455 -0
  109. package/lib/session.js +95 -161
  110. package/lib/update.js +44 -111
  111. package/lib/utilities.js +46 -88
  112. package/lib/workspace.js +166 -0
  113. package/lib/wrap.js +29 -55
  114. package/package.json +1 -1
@@ -10,10 +10,8 @@ const { needsReload, npmBusyKind, sameBlock } = items;
10
10
  const diff = require('../diff/diff.js');
11
11
  const { hunkKey } = diff;
12
12
 
13
- const nextUnstageOrigin = (item) => {
14
- if (item.file.isNew === true) return 'untracked';
15
- return 'unstaged';
16
- };
13
+ const nextUnstageOrigin = (item) =>
14
+ item.file.isNew === true ? 'untracked' : 'unstaged';
17
15
 
18
16
  const COMMANDS = {
19
17
  add: {
@@ -34,26 +32,15 @@ const COMMANDS = {
34
32
 
35
33
  const IGNORE_FILES = ['.gitignore', '.npmignore'];
36
34
 
37
- const ignorePatternListed = (text, pattern) => {
38
- for (const line of `${text ?? ''}`.split('\n')) {
39
- if (line.trim() === pattern) return true;
40
- }
41
- return false;
42
- };
43
-
44
- const appendIgnorePattern = (text, pattern) => {
45
- if (ignorePatternListed(text, pattern)) return text;
46
- const base = text.length && !text.endsWith('\n') ? `${text}\n` : text;
47
- return `${base}${pattern}\n`;
48
- };
49
-
50
35
  const appendIgnoreFile = (top, name, pattern) => {
51
36
  const abs = path.join(top, name);
52
- if (name === '.npmignore' && !fs.existsSync(abs)) return false;
53
- const text = fs.existsSync(abs) ? fs.readFileSync(abs, 'utf8') : '';
54
- const next = appendIgnorePattern(text, pattern);
55
- if (next === text) return false;
56
- fs.writeFileSync(abs, next);
37
+ const exists = fs.existsSync(abs);
38
+ if (name === '.npmignore' && !exists) return false;
39
+ const text = exists ? fs.readFileSync(abs, 'utf8') : '';
40
+ const lines = text.split('\n');
41
+ if (lines.some((line) => line.trim() === pattern)) return false;
42
+ const base = text && !text.endsWith('\n') ? `${text}\n` : text;
43
+ fs.writeFileSync(abs, `${base}${pattern}\n`);
57
44
  return true;
58
45
  };
59
46
 
@@ -63,11 +50,8 @@ const ignoreRelPath = (ui, rel) => {
63
50
  ui.status = 'not a diff block';
64
51
  return;
65
52
  }
66
- let changed = false;
67
- for (const name of IGNORE_FILES) {
68
- if (appendIgnoreFile(ui.top, name, pattern)) changed = true;
69
- }
70
- if (!changed) {
53
+ const append = (name) => appendIgnoreFile(ui.top, name, pattern);
54
+ if (!IGNORE_FILES.map(append).includes(true)) {
71
55
  ui.status = 'already ignored';
72
56
  return;
73
57
  }
@@ -77,8 +61,6 @@ const ignoreRelPath = (ui, rel) => {
77
61
  ui.status = 'ignored';
78
62
  };
79
63
 
80
- const sameEntry = (entry) => entry;
81
-
82
64
  const keepOrigin = (ui, item, origin) => {
83
65
  ui.collection.keepOrigin(item, origin);
84
66
  const idx = ui.collection.findRestoredIndex({ ...item, origin });
@@ -89,22 +71,12 @@ const keepOrigin = (ui, item, origin) => {
89
71
  ui.syncFileCursor();
90
72
  };
91
73
 
92
- const fileCursorEntry = (ui) => {
93
- const list = ui.fileList();
94
- return list[ui.nav.fileCursor] ?? null;
95
- };
96
-
97
74
  const fileActionItems = (ui) => {
98
- const entry = fileCursorEntry(ui);
75
+ const entry = ui.fileCursorEntry();
99
76
  if (!entry || isTasksEntry(entry)) return [];
100
- const rel = entry.path;
101
- const selected = [];
102
- for (const item of ui.items) {
103
- if (isTaskItem(item)) continue;
104
- if (listPath(item) !== rel) continue;
105
- selected.push(item);
106
- }
107
- return selected;
77
+ return ui.items.filter(
78
+ (item) => !isTaskItem(item) && listPath(item) === entry.path,
79
+ );
108
80
  };
109
81
 
110
82
  const activeDiffItem = (ui) => {
@@ -144,16 +116,12 @@ const selectNextFileAfter = (ui, rel) => {
144
116
  nav.index = entry.firstIndex;
145
117
  };
146
118
 
147
- const liveItem = (ui, item) => {
148
- for (const entry of ui.items) {
149
- if (sameBlock(entry, item)) return entry;
150
- }
151
- return item;
152
- };
119
+ const liveItem = (ui, item) =>
120
+ ui.items.find((entry) => sameBlock(entry, item)) ?? item;
153
121
 
154
- const applyGit = (ui, item, label, write, after) => {
122
+ const applyGit = (ui, label, write, after) => {
155
123
  try {
156
- write(ui.top, item);
124
+ write(ui.top);
157
125
  ui.status = label;
158
126
  after();
159
127
  } catch (error) {
@@ -161,45 +129,35 @@ const applyGit = (ui, item, label, write, after) => {
161
129
  }
162
130
  };
163
131
 
164
- const applyFileGit = (ui, targets, label, write, afterItem) => {
165
- const { length } = targets;
166
- const completed = new Array(length);
167
- let n = 0;
132
+ const applyFileGit = (ui, targets, label, write, afterItem = () => {}) => {
133
+ let written = 0;
168
134
  try {
169
- for (let i = 0; i < length; i++) {
170
- const current = liveItem(ui, targets[i]);
135
+ for (const target of targets) {
136
+ const current = liveItem(ui, target);
171
137
  write(ui.top, current);
172
138
  afterItem(current);
173
- completed[n++] = current;
139
+ written++;
174
140
  }
175
- completed.length = n;
176
141
  ui.status = label;
177
- return { ok: true, completed };
142
+ return { ok: true, written };
178
143
  } catch (error) {
179
- completed.length = n;
180
144
  ui.status = error.message;
181
- return { ok: false, completed };
145
+ return { ok: false, written };
182
146
  }
183
147
  };
184
148
 
185
149
  const reconcilePartial = (ui, result) => {
186
150
  if (result.ok) return false;
187
- if (result.completed.length) ui.reloadAfterChange();
151
+ if (result.written) ui.reloadAfterChange();
188
152
  return true;
189
153
  };
190
154
 
191
- const applyBlockAdd = (ui, item) => {
192
- if (needsReload(item)) return void ui.reloadAfterChange();
193
- keepOrigin(ui, item, 'staged');
194
- };
195
-
196
155
  const enqueueOrigins = (ui, targets, spec) => {
197
- const writes = new Array(targets.length);
198
- for (let i = 0; i < targets.length; i++) {
199
- const current = liveItem(ui, targets[i]);
200
- writes[i] = current;
201
- keepOrigin(ui, current, spec.originOf(current));
202
- }
156
+ const writes = targets.map((target) => {
157
+ const item = liveItem(ui, target);
158
+ keepOrigin(ui, item, spec.originOf(item));
159
+ return item;
160
+ });
203
161
  if (spec.afterUi) spec.afterUi();
204
162
  if (!spec.busy) ui.status = spec.done;
205
163
  ui.ops.enqueueLazy({
@@ -239,22 +197,24 @@ const unstageLazy = (ui, targets, extra = {}) => {
239
197
  });
240
198
  };
241
199
 
200
+ const dismissReloadable = (ui, targets) => {
201
+ for (const item of targets) {
202
+ if (needsReload(item)) ui.collection.dismiss(item);
203
+ }
204
+ };
205
+
242
206
  const onBlockAdd = (ui, item) => {
243
- const busy = npmBusyKind(item);
244
- const repo = ui.repo;
207
+ const reload = needsReload(item);
245
208
  if (ui.uiOpen) {
246
- return void stageLazy(ui, [item], {
247
- busy,
248
- reload: needsReload(item),
249
- });
209
+ return void stageLazy(ui, [item], { busy: npmBusyKind(item), reload });
250
210
  }
251
211
  applyGit(
252
212
  ui,
253
- item,
254
213
  'staged',
255
- (top, current) => repo.add(top, current),
214
+ (top) => ui.repo.add(top, item),
256
215
  () => {
257
- applyBlockAdd(ui, item);
216
+ if (reload) ui.reloadAfterChange();
217
+ else keepOrigin(ui, item, 'staged');
258
218
  },
259
219
  );
260
220
  };
@@ -262,29 +222,19 @@ const onBlockAdd = (ui, item) => {
262
222
  const onBlockUnstage = (ui, item) => {
263
223
  if (ui.uiOpen) return void unstageLazy(ui, [item]);
264
224
  const origin = nextUnstageOrigin(item);
265
- const repo = ui.repo;
266
225
  applyGit(
267
226
  ui,
268
- item,
269
227
  'unstaged',
270
- (top, current) => repo.unstage(top, current),
228
+ (top) => ui.repo.unstage(top, item),
271
229
  () => keepOrigin(ui, item, origin),
272
230
  );
273
231
  };
274
232
 
275
- const dismissReloadable = (ui, targets) => {
276
- for (const item of targets) {
277
- if (needsReload(item)) ui.collection.dismiss(item);
278
- }
279
- };
280
-
281
233
  const onBlockRevert = (ui, item) => {
282
- const repo = ui.repo;
283
234
  applyGit(
284
235
  ui,
285
- item,
286
236
  'dropped',
287
- (top, current) => repo.revert(top, current),
237
+ (top) => ui.repo.revert(top, item),
288
238
  () => {
289
239
  dismissReloadable(ui, [item]);
290
240
  ui.reloadAfterChange();
@@ -340,14 +290,8 @@ const unstageTargets = (ui, targets, after = null) => {
340
290
 
341
291
  const revertTargets = (ui, targets) => {
342
292
  dismissReloadable(ui, targets);
343
- const result = applyFileGit(
344
- ui,
345
- targets,
346
- 'dropped',
347
- ui.repo.revert,
348
- sameEntry,
349
- );
350
- if (!result.ok && !result.completed.length) return;
293
+ const result = applyFileGit(ui, targets, 'dropped', ui.repo.revert);
294
+ if (!result.ok && !result.written) return;
351
295
  ui.reloadAfterChange();
352
296
  };
353
297
 
@@ -391,13 +335,7 @@ const onFileCommand = (ui, name) => {
391
335
 
392
336
  const hunkActionItems = (ui, item) => {
393
337
  const key = hunkKey(item);
394
- const selected = [];
395
- if (!key) return selected;
396
- for (const entry of ui.items) {
397
- if (hunkKey(entry) !== key) continue;
398
- selected.push(entry);
399
- }
400
- return selected;
338
+ return key ? ui.items.filter((entry) => hunkKey(entry) === key) : [];
401
339
  };
402
340
 
403
341
  const onUnitCommand = (ui, name) => {
@@ -419,12 +357,4 @@ const onCommand = (ui, name) => {
419
357
  onBlockCommand(ui, name);
420
358
  };
421
359
 
422
- const createChangeActions = (ui) => ({
423
- fileCursorEntry: () => fileCursorEntry(ui),
424
- onAdd: () => onCommand(ui, 'add'),
425
- onUnstage: () => onCommand(ui, 'unstage'),
426
- onRevert: () => onCommand(ui, 'revert'),
427
- onIgnore: () => onCommand(ui, 'ignore'),
428
- });
429
-
430
- module.exports = { createChangeActions };
360
+ module.exports = { onCommand };