reslop 0.2.5 → 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 (105) hide show
  1. package/CHANGELOG.md +12 -1
  2. package/LICENSE +1 -1
  3. package/README.md +11 -11
  4. package/bin/reslop.js +3 -8
  5. package/lib/ansi.js +32 -19
  6. package/lib/capabilities.js +8 -8
  7. package/lib/cli.js +40 -74
  8. package/lib/clipboard.js +39 -47
  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 +197 -402
  14. package/lib/deps.js +113 -240
  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 +76 -144
  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 +79 -178
  25. package/lib/editor.js +52 -69
  26. package/lib/files.js +71 -89
  27. package/lib/git-branches.js +254 -416
  28. package/lib/git-deps.js +147 -272
  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 +155 -141
  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 +14 -14
  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 +19 -25
  44. package/lib/highlight/txt.js +7 -10
  45. package/lib/highlight.js +17 -46
  46. package/lib/keys.js +49 -82
  47. package/lib/manifest.js +67 -126
  48. package/lib/npm-commands.js +120 -169
  49. package/lib/remote.js +140 -190
  50. package/lib/render/branches.js +63 -61
  51. package/lib/render/chrome.js +220 -333
  52. package/lib/render/commits.js +160 -361
  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 -258
  58. package/lib/render/files.js +40 -85
  59. package/lib/render/frame.js +78 -117
  60. package/lib/render/notes.js +139 -210
  61. package/lib/render/npm.js +213 -177
  62. package/lib/render/present.js +4 -11
  63. package/lib/render/primitives.js +72 -174
  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 -31
  68. package/lib/report-model.js +110 -33
  69. package/lib/report-parse.js +56 -37
  70. package/lib/report-render.js +102 -59
  71. package/lib/report-run.js +87 -77
  72. package/lib/report-test.js +221 -99
  73. package/lib/report-tools.js +96 -154
  74. package/lib/review-merge.js +33 -41
  75. package/lib/review.js +68 -129
  76. package/lib/runs.js +225 -0
  77. package/lib/select.js +53 -91
  78. package/lib/session/accessors.js +14 -21
  79. package/lib/session/actions.js +61 -43
  80. package/lib/session/branches.js +166 -222
  81. package/lib/session/change-actions.js +49 -119
  82. package/lib/session/commit.js +274 -355
  83. package/lib/session/compose.js +556 -714
  84. package/lib/session/dashboard.js +385 -0
  85. package/lib/session/dispatch.js +162 -170
  86. package/lib/session/files-pane.js +76 -44
  87. package/lib/session/items.js +6 -17
  88. package/lib/session/lifecycle.js +393 -466
  89. package/lib/session/load.js +1 -14
  90. package/lib/session/navigation.js +2 -2
  91. package/lib/session/npm.js +403 -420
  92. package/lib/session/ops.js +5 -13
  93. package/lib/session/pointer.js +16 -14
  94. package/lib/session/progress.js +39 -30
  95. package/lib/session/review.js +1 -3
  96. package/lib/session/tasks.js +276 -235
  97. package/lib/session/templates.js +51 -59
  98. package/lib/session/terminal.js +85 -132
  99. package/lib/session/view.js +47 -81
  100. package/lib/session/watch.js +196 -212
  101. package/lib/session.js +81 -161
  102. package/lib/update.js +44 -111
  103. package/lib/utilities.js +46 -88
  104. package/lib/wrap.js +29 -55
  105. 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 };