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
package/lib/keys.js CHANGED
@@ -4,8 +4,8 @@ const actions = require('./session/actions.js');
4
4
 
5
5
  const { ACTIONS, ACTION_IDS, BRANCH_ACTIONS, COMMIT_ACTIONS } = actions;
6
6
  const { DIFF_DISABLED, FILES_DISABLED, FILES_GIT_DISABLED } = actions;
7
- const { FILES_HIDDEN, FILES_TODO_DISABLED } = actions;
8
- const { TODO_DISABLED, BRANCHES_DISABLED } = actions;
7
+ const { FILES_HIDDEN, FILES_TASKS_DISABLED } = actions;
8
+ const { TASKS_DISABLED, BRANCHES_DISABLED } = actions;
9
9
  const { COMMITS_DISABLED, UNIT_DISABLED, NPM_DISABLED } = actions;
10
10
  const { disabledActions, diffGitDisabled, branchGitDisabled } = actions;
11
11
  const { commitGitDisabled } = actions;
@@ -65,21 +65,31 @@ const parseCsiSeq = (rest) => {
65
65
  return { params: body.slice(0, i), final: body[i], eat: 2 + i + 1 };
66
66
  };
67
67
 
68
- const ctrlHeld = (modText) => {
68
+ const modifierBits = (modText) => {
69
69
  const mod = parseInt(modText, 10);
70
- return Number.isFinite(mod) && ((mod - 1) & 4) !== 0;
70
+ if (!Number.isFinite(mod)) return 0;
71
+ return mod - 1;
72
+ };
73
+
74
+ const modifiedKey = (base, bits) => {
75
+ const arrow =
76
+ base === 'left' || base === 'right' || base === 'up' || base === 'down';
77
+ const end = base === 'home' || base === 'end';
78
+ if (!arrow && !end) return base;
79
+ const ctrl = (bits & 4) !== 0;
80
+ const shift = (bits & 1) !== 0;
81
+ if (ctrl && shift && arrow) return `ctrl-shift-${base}`;
82
+ if (ctrl && arrow) return `ctrl-${base}`;
83
+ if (shift) return `shift-${base}`;
84
+ return base;
71
85
  };
72
86
 
73
87
  const keyFromCsi = (paramsText, final) => {
74
88
  const params = paramsText ? paramsText.split(';') : [];
75
- if (final === '~') return CSI_TILDE[params[0]] ?? null;
76
- const base = CSI_KEYS[final];
89
+ const base = final === '~' ? CSI_TILDE[params[0]] : CSI_KEYS[final];
77
90
  if (!base) return null;
78
91
  if (params.length < 2) return base;
79
- const arrow =
80
- base === 'left' || base === 'right' || base === 'up' || base === 'down';
81
- if (ctrlHeld(params[1]) && arrow) return `ctrl-${base}`;
82
- return base;
92
+ return modifiedKey(base, modifierBits(params[1]));
83
93
  };
84
94
 
85
95
  const mouseKindFromButton = (button, press) => {
@@ -194,8 +204,8 @@ module.exports = {
194
204
  FILES_DISABLED,
195
205
  FILES_HIDDEN,
196
206
  FILES_GIT_DISABLED,
197
- FILES_TODO_DISABLED,
198
- TODO_DISABLED,
207
+ FILES_TASKS_DISABLED,
208
+ TASKS_DISABLED,
199
209
  BRANCHES_DISABLED,
200
210
  COMMITS_DISABLED,
201
211
  NPM_DISABLED,
package/lib/manifest.js CHANGED
@@ -310,9 +310,7 @@ const proposedWanted = (out, vul) => {
310
310
  module.exports = {
311
311
  MANIFEST,
312
312
  LOCKFILE,
313
- DEP_KIND,
314
313
  SECTION_KEYS,
315
- posixRel,
316
314
  depFileMeta,
317
315
  relOf,
318
316
  listFilePath,
@@ -321,8 +319,6 @@ module.exports = {
321
319
  lockRootSections,
322
320
  lockEntries,
323
321
  lockPackageCount,
324
- cloneJson,
325
- stringifyJson,
326
322
  mergeDepFile,
327
323
  applyWantedRange,
328
324
  findDeclared,
@@ -9,7 +9,7 @@ const { jsonParse } = metautil;
9
9
  const ansi = require('./ansi.js');
10
10
  const { stripAnsi, visibleWidth } = ansi;
11
11
  const utilities = require('./utilities.js');
12
- const { npmBin, npmOpts, spawnBase } = utilities;
12
+ const { npmBin, npmOpts, spawnBase, unquote, dateStamp } = utilities;
13
13
 
14
14
  const MANIFEST = 'package.json';
15
15
  const SECTIONS = ['dependencies', 'devDependencies', 'optionalDependencies'];
@@ -128,17 +128,6 @@ const withoutNodeFrame = (line) => {
128
128
  return null;
129
129
  };
130
130
 
131
- const unquote = (value) => {
132
- const text = `${value ?? ''}`;
133
- if (text.length < 2) return text;
134
- const open = text[0];
135
- const close = text[text.length - 1];
136
- const code = open.charCodeAt(0);
137
- const quoted = open === close && (code === 34 || code === 39);
138
- if (!quoted) return text;
139
- return text.slice(1, -1);
140
- };
141
-
142
131
  const objectEnd = (lines, start) => {
143
132
  if (stripAnsi(lines[start]).trim() !== '{') return -1;
144
133
  for (let i = start + 1; i < lines.length; i++) {
@@ -284,13 +273,6 @@ const logFileName = (command, date, index) => {
284
273
  return `${date}-${safe}-${n}.log`;
285
274
  };
286
275
 
287
- const dateStamp = (now) => {
288
- const y = now.getFullYear();
289
- const m = `${now.getMonth() + 1}`.padStart(2, '0');
290
- const d = `${now.getDate()}`.padStart(2, '0');
291
- return `${y}-${m}-${d}`;
292
- };
293
-
294
276
  const LOG_DIR = '.log';
295
277
  const LOG_STALE_DAYS = 5;
296
278
  const DAY_MS = 24 * 60 * 60 * 1000;
@@ -403,8 +385,6 @@ const parseScriptLine = (text) => {
403
385
  return { name, command };
404
386
  };
405
387
 
406
- const scriptLine = (entry) => `${entry.name}: ${entry.command}`;
407
-
408
388
  const orderedScripts = (pkg) => {
409
389
  const scripts = pkg.scripts;
410
390
  if (!scripts || typeof scripts !== 'object' || Array.isArray(scripts)) {
@@ -577,7 +557,6 @@ module.exports = {
577
557
  removeStaleLogs,
578
558
  formatSize,
579
559
  parseScriptLine,
580
- scriptLine,
581
560
  saveScript,
582
561
  removeScript,
583
562
  reorderScript,
package/lib/remote.js CHANGED
@@ -347,7 +347,7 @@ const loadChange = async (ref, options, source) => {
347
347
  const items = foldDepItems(itemsFromFiles(files, 'pr'));
348
348
  const change = source.toChange(ref, data, items);
349
349
  const sourceLabel = `${source.prefix}${change.number}`;
350
- let imported = { feedback: [], todos: [] };
350
+ let imported = { feedback: [], tasks: [] };
351
351
  try {
352
352
  const discussion = await source.loadDiscussion(ref, request);
353
353
  imported = source.discussionToNotes(discussion, items, paths);
@@ -359,22 +359,16 @@ const loadChange = async (ref, options, source) => {
359
359
  };
360
360
 
361
361
  module.exports = {
362
- RETRY_ATTEMPTS,
363
- RETRY_DELAY_MS,
364
- TRANSIENT_STATUS,
365
362
  isRecord,
366
363
  isAbortError,
367
364
  createTransport,
368
- headerValue,
369
365
  parseLinkNext,
370
366
  parseNextPage,
371
367
  createClient,
372
368
  listUrl,
373
- findItemForLine,
374
369
  importedText,
375
370
  importedTodo,
376
371
  noteFromLocation,
377
- changePath,
378
372
  filterChangeFiles,
379
373
  changeFiles,
380
374
  loadChange,
@@ -124,19 +124,10 @@ const paintBodyBranches = (view, width, color, bodyH, headerLines) => {
124
124
  const compose = view.compose;
125
125
  const editing = compose && compose.kind === 'branch';
126
126
  const tail = editing ? paintListEdit(compose, width, color) : null;
127
- const paintRow = (entry, rowWidth, rowColor, selected) =>
128
- paintBranchRow(entry, rowWidth, rowColor, selected, cols);
129
- return paintCursorList(
130
- branches,
131
- cursor,
132
- width,
133
- color,
134
- bodyH,
135
- headerLines,
136
- paintRow,
137
- tail,
138
- view.listScroll,
139
- );
127
+ const pane = { width, color, bodyH, headerLines, offset: view.listScroll };
128
+ const paintRow = (entry, selected) =>
129
+ paintBranchRow(entry, width, color, selected, cols);
130
+ return paintCursorList(branches, cursor, pane, paintRow, tail);
140
131
  };
141
132
 
142
133
  module.exports = { paintBodyBranches };
@@ -5,11 +5,11 @@ const keys = require('../keys.js');
5
5
  const files = require('../files.js');
6
6
  const primitives = require('./primitives.js');
7
7
 
8
- const { itemPath, REPO_TODOS_LABEL, isTodosEntry, fileTotals } = files;
8
+ const { itemPath, REPO_TASKS_LABEL, isTasksEntry, fileTotals } = files;
9
9
  const { ACTION_IDS, BRANCH_ACTIONS, COMMIT_ACTIONS, actionLetter } = keys;
10
10
  const { buttonWord } = keys;
11
11
  const { FILES_HIDDEN, FILES_GIT_DISABLED, BRANCHES_DISABLED } = keys;
12
- const { COMMITS_DISABLED, TODO_DISABLED, DIFF_DISABLED, UNIT_DISABLED } = keys;
12
+ const { COMMITS_DISABLED, TASKS_DISABLED, DIFF_DISABLED, UNIT_DISABLED } = keys;
13
13
  const { NPM_DISABLED } = keys;
14
14
  const { diffGitDisabled, branchGitDisabled, commitGitDisabled } = keys;
15
15
  const { CONFIRM, confirmPrefix, promptFromChoices } = keys;
@@ -122,6 +122,9 @@ const BUTTON_LEAD = ' ';
122
122
  const BUTTON_GAP = ' ';
123
123
  const BUTTON_EDGE = 1;
124
124
  const buttonGap = (index) => (index ? BUTTON_GAP : BUTTON_LEAD);
125
+ const BACK_ARROW = '🢐';
126
+ const STOP_MARK = '⊗';
127
+ const BACK_KEY = 'esc';
125
128
  const LOGO = '👁️';
126
129
 
127
130
  const pathSegments = (rel) => {
@@ -152,10 +155,10 @@ const headerScreen = (view) => {
152
155
  if (pane === 'files') {
153
156
  const files = view.files ?? [];
154
157
  const entry = files[view.fileCursor ?? 0];
155
- if (isTodosEntry(entry)) return REPO_TODOS_LABEL;
158
+ if (isTasksEntry(entry)) return REPO_TASKS_LABEL;
156
159
  return '';
157
160
  }
158
- if (view.item && view.item.origin === 'todo') return REPO_TODOS_LABEL;
161
+ if (view.item && view.item.origin === 'task') return REPO_TASKS_LABEL;
159
162
  return '';
160
163
  };
161
164
 
@@ -163,11 +166,11 @@ const headerTarget = (view) => {
163
166
  const pane = view.pane ?? 'diff';
164
167
  if (pane === 'files') {
165
168
  const entry = (view.files ?? [])[view.fileCursor ?? 0];
166
- if (!entry || isTodosEntry(entry)) return '';
169
+ if (!entry || isTasksEntry(entry)) return '';
167
170
  return entry.path;
168
171
  }
169
172
  if (pane === 'unit') return view.reviewPath ?? '';
170
- if (!view.item || view.item.origin === 'todo') return '';
173
+ if (!view.item || view.item.origin === 'task') return '';
171
174
  return itemPath(view.item);
172
175
  };
173
176
 
@@ -251,6 +254,38 @@ const QUIT_MARK = {
251
254
  missBold: false,
252
255
  };
253
256
 
257
+ const backFooterId = (view) => {
258
+ const pane = view.pane ?? 'diff';
259
+ if (pane === 'branches' || pane === 'commits') return 'back';
260
+ if (pane === 'npm') return view.npmView ? 'npmStop' : 'back';
261
+ if (view.item && view.item.origin === 'task') return 'back';
262
+ return '';
263
+ };
264
+
265
+ const backHintMark = (view) => {
266
+ if (view.pane === 'npm' && view.npmView && view.npmRunning) return STOP_MARK;
267
+ return BACK_ARROW;
268
+ };
269
+
270
+ const hintBody = (mark) => {
271
+ const gap = mark === STOP_MARK ? ' ' : '';
272
+ return `${mark}${gap}${BACK_KEY}`;
273
+ };
274
+
275
+ const buttonLabel = (id, short, backId, mark) => {
276
+ if (id === backId) return hintBody(mark);
277
+ if (short) return actionLetter(id);
278
+ return buttonWord(id);
279
+ };
280
+
281
+ const paintBackHint = (color, mark) => {
282
+ const bgRgb = THEME.buttonBg;
283
+ const body = hintBody(mark);
284
+ const arrow = paint(mark, THEME.buttonHotFg, bgRgb, color, true);
285
+ const rest = paint(body.slice(mark.length), THEME.buttonFg, bgRgb, color);
286
+ return arrow + rest;
287
+ };
288
+
254
289
  const paintMarkedWord = (label, letter, color, mark) => {
255
290
  const at = label.indexOf(letter);
256
291
  if (at < 0) {
@@ -266,37 +301,49 @@ const paintMarkedWord = (label, letter, color, mark) => {
266
301
  return out;
267
302
  };
268
303
 
269
- const layoutButtons = (width, compact, hidden, extra, disabled) => {
270
- const hiddenIds = hidden ?? [];
271
- const extraIds = extra ?? [];
272
- const disabledIds = disabled ?? [];
273
- const ids = [];
304
+ const footerIds = (hidden, extra, backId) => {
305
+ const ids = backId ? [backId] : [];
274
306
  for (const id of ACTION_IDS) {
275
- if (id === 'quit') {
276
- for (const add of extraIds) {
277
- if (!ids.includes(add)) ids.push(add);
278
- }
307
+ if (id !== 'quit') {
308
+ if (!hidden.includes(id)) ids.push(id);
279
309
  continue;
280
310
  }
281
- if (hiddenIds.includes(id)) continue;
282
- ids.push(id);
311
+ for (const add of extra) {
312
+ if (!ids.includes(add)) ids.push(add);
313
+ }
283
314
  }
315
+ return ids;
316
+ };
317
+
318
+ const layoutButtons = (width, options = {}) => {
319
+ const { compact = false, hidden = [], extra = [] } = options;
320
+ const { disabled: disabledIds = [], backId = '', mark = '' } = options;
321
+ const hint = mark || BACK_ARROW;
322
+ const ids = footerIds(hidden, extra, backId);
284
323
  const build = (short) => {
285
324
  const hits = [];
286
325
  const parts = [];
287
326
  let x = 0;
288
327
  const limit = Math.max(0, width - BUTTON_EDGE);
289
328
  for (const id of ids) {
290
- const letter = actionLetter(id);
291
- const word = buttonWord(id);
292
- const label = short ? letter : word;
329
+ const back = id === backId;
330
+ const letter = back ? BACK_KEY : actionLetter(id);
331
+ const label = buttonLabel(id, short, backId, hint);
293
332
  const gap = buttonGap(parts.length);
294
333
  const piece = `${gap}${label}`;
295
334
  const w = visibleWidth(piece);
296
335
  if (x + w > limit && parts.length) break;
297
336
  const off = disabledIds.includes(id);
298
337
  if (!off) hits.push({ id, x0: x, x1: x + w });
299
- parts.push({ action: { id }, piece, letter, label, disabled: off });
338
+ parts.push({
339
+ action: { id },
340
+ piece,
341
+ letter,
342
+ label,
343
+ disabled: off,
344
+ back,
345
+ mark: back ? hint : '',
346
+ });
300
347
  x += w;
301
348
  }
302
349
  return { hits, parts, width: x };
@@ -316,7 +363,8 @@ const paintButtons = (layout, width, color) => {
316
363
  const part = layout.parts[i];
317
364
  const gap = buttonGap(i);
318
365
  out += paint(gap, fgRgb, bgRgb, color);
319
- if (part.disabled) out += paint(part.label, fgRgb, bgRgb, color);
366
+ if (part.back) out += paintBackHint(color, part.mark);
367
+ else if (part.disabled) out += paint(part.label, fgRgb, bgRgb, color);
320
368
  else out += paintMarkedWord(part.label, part.letter, color, BUTTON_MARK);
321
369
  used += visibleWidth(part.piece);
322
370
  }
@@ -351,9 +399,9 @@ const countsKind = (sourceKind, revShort) => {
351
399
 
352
400
  const notesLine = (counts) => {
353
401
  const feedback = counts.feedback ?? 0;
354
- const todo = counts.todo ?? 0;
402
+ const tasks = counts.tasks ?? 0;
355
403
  const code = counts.code ?? 0;
356
- return `feedback ${feedback} todo ${todo} code ${code}`;
404
+ return `feedback ${feedback} tasks ${tasks} code ${code}`;
357
405
  };
358
406
 
359
407
  const statusLead = (view) => {
@@ -619,7 +667,7 @@ const hiddenActions = (view) => {
619
667
  if (pane === 'branches') return BRANCHES_DISABLED;
620
668
  if (pane === 'commits') return COMMITS_DISABLED;
621
669
  if (pane === 'npm') return NPM_DISABLED;
622
- if (view.item && view.item.origin === 'todo') return TODO_DISABLED;
670
+ if (view.item && view.item.origin === 'task') return TASKS_DISABLED;
623
671
  return DIFF_DISABLED;
624
672
  };
625
673
 
@@ -628,7 +676,7 @@ const dimFooterActions = (view) => {
628
676
  if (pane === 'files') {
629
677
  const files = view.files ?? [];
630
678
  const entry = files[view.fileCursor ?? 0];
631
- if (!entry || entry.kind !== 'todos') return [];
679
+ if (!entry || entry.kind !== 'tasks') return [];
632
680
  return FILES_GIT_DISABLED;
633
681
  }
634
682
  if (pane === 'diff' || pane === 'unit') return diffGitDisabled(view.item);
@@ -660,12 +708,21 @@ const extraFooterActions = (view) => {
660
708
  if (pane === 'branches') return Object.keys(BRANCH_ACTIONS);
661
709
  if (pane === 'commits') return Object.keys(COMMIT_ACTIONS);
662
710
  if (pane === 'npm') {
663
- if (view.npmView) return ['npmStop', 'npmRerun'];
711
+ if (view.npmView) return ['npmVerbose', 'npmRerun'];
664
712
  return ['npmEdit', 'npmNew', 'npmDrop', 'npmLogs'];
665
713
  }
666
714
  return [];
667
715
  };
668
716
 
717
+ const footerLayout = (view, width) =>
718
+ layoutButtons(width, {
719
+ hidden: hiddenActions(view),
720
+ extra: extraFooterActions(view),
721
+ disabled: dimFooterActions(view),
722
+ backId: backFooterId(view),
723
+ mark: backHintMark(view),
724
+ });
725
+
669
726
  module.exports = {
670
727
  QUIT_PROMPT,
671
728
  PUSH_PROMPT,
@@ -675,13 +732,10 @@ module.exports = {
675
732
  headerText,
676
733
  paintHeader,
677
734
  layoutButtons,
678
- paintButtons,
735
+ footerLayout,
679
736
  paintFooter,
680
737
  footerHits,
681
738
  paintStatusLine,
682
739
  statusChoiceHits,
683
740
  statusBranchHit,
684
- hiddenActions,
685
- dimFooterActions,
686
- extraFooterActions,
687
741
  };