reslop 0.1.1 → 0.1.2
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.
- package/CHANGELOG.md +13 -6
- package/README.md +11 -9
- package/bin/reslop.js +2 -2
- package/lib/ansi.js +0 -1
- package/lib/cli.js +44 -43
- package/lib/clipboard.js +1 -1
- package/lib/deps.js +1440 -0
- package/lib/detect.js +4 -4
- package/lib/diff.js +31 -55
- package/lib/editor.js +1 -1
- package/lib/files.js +22 -3
- package/lib/git.js +360 -36
- package/lib/github.js +28 -34
- package/lib/highlight.js +126 -140
- package/lib/keys.js +29 -39
- package/lib/render.js +172 -129
- package/lib/review.js +22 -42
- package/lib/select.js +16 -18
- package/lib/session.js +97 -208
- package/lib/source.js +7 -3
- package/package.json +1 -1
package/lib/session.js
CHANGED
|
@@ -16,7 +16,7 @@ const { refreshIndexPatches } = require('./diff.js');
|
|
|
16
16
|
const { renderFrame, presentRows, presentCursor } = render;
|
|
17
17
|
const { noteInnerWidth, todoInnerWidth } = render;
|
|
18
18
|
const { QUIT_FINISH, QUIT_CONTINUE } = render;
|
|
19
|
-
const { actionFromKey, hitAction, decodeChunk
|
|
19
|
+
const { actionFromKey, hitAction, decodeChunk } = keys;
|
|
20
20
|
const { FILES_DISABLED } = keys;
|
|
21
21
|
const { cursorInWrap, wrapDoc, wrapMove } = wrap;
|
|
22
22
|
const { AUTOSAVE_MS, listReviewNames, loadTemplates } = review;
|
|
@@ -28,20 +28,13 @@ const { feedbackKey, checkLabel, rankedTemplates } = review;
|
|
|
28
28
|
const { prefixTemplates, TEMPLATE_SHOW, rememberTemplate } = review;
|
|
29
29
|
|
|
30
30
|
const LAYOUTS = ['unified', 'mixed', 'side'];
|
|
31
|
-
const FILES_MOVE = {
|
|
32
|
-
next: 1,
|
|
33
|
-
prev: -1,
|
|
34
|
-
};
|
|
35
|
-
const ADD_STATUS = {
|
|
36
|
-
staged: 'already staged',
|
|
37
|
-
};
|
|
38
31
|
const READ_ONLY_ORIGINS = ['commit', 'pr'];
|
|
39
32
|
const ENTER_TERM = '\x1b[?1049h\x1b[?25l\x1b[?7l\x1b[?1002h\x1b[?1006h';
|
|
40
33
|
const LEAVE_TERM =
|
|
41
34
|
'\x1b[?1006l\x1b[?1002l\x1b[?7h\x1b[0 q\x1b[?12l\x1b[?25h\x1b[?1049l';
|
|
42
35
|
const CURSOR_BLINK_MS = 500;
|
|
43
36
|
|
|
44
|
-
const
|
|
37
|
+
const systemNow = () => new Date();
|
|
45
38
|
|
|
46
39
|
const isReadOnlyOrigin = (origin) => READ_ONLY_ORIGINS.includes(origin);
|
|
47
40
|
|
|
@@ -53,11 +46,21 @@ const relabelStatus = (entries, from, to) => {
|
|
|
53
46
|
});
|
|
54
47
|
};
|
|
55
48
|
|
|
49
|
+
const depChangeKey = (item) => {
|
|
50
|
+
const change = item.dep && item.dep.change;
|
|
51
|
+
if (!change) return '';
|
|
52
|
+
return `${change.section}/${change.name}`;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const needsReload = (item) => item.reload === true;
|
|
56
|
+
|
|
56
57
|
const itemKey = (item) => {
|
|
57
58
|
if (!item || !item.file) return '';
|
|
58
59
|
const rel = itemPath(item);
|
|
59
60
|
if (item.origin === 'todo') return `todo:${rel}`;
|
|
60
61
|
const origin = item.origin ?? '';
|
|
62
|
+
const depId = depChangeKey(item);
|
|
63
|
+
if (depId) return `${origin}:${rel}:dep:${depId}`;
|
|
61
64
|
if (!item.hunk) {
|
|
62
65
|
const block = item.blockId ?? '-';
|
|
63
66
|
return `${origin}:${rel}:file:${block}`;
|
|
@@ -71,12 +74,12 @@ const itemKey = (item) => {
|
|
|
71
74
|
const itemFeedKey = (item) => {
|
|
72
75
|
if (!item || !item.file || item.origin === 'todo') return '';
|
|
73
76
|
const hunk = item.hunk;
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
});
|
|
77
|
+
const depId = depChangeKey(item);
|
|
78
|
+
const file = depId ? `${itemPath(item)}#${depId}` : itemPath(item);
|
|
79
|
+
const oldStart = hunk ? hunk.oldStart : 0;
|
|
80
|
+
const newStart = hunk ? hunk.newStart : 0;
|
|
81
|
+
const blockId = item.blockId ?? 0;
|
|
82
|
+
return feedbackKey({ file, oldStart, newStart, blockId });
|
|
80
83
|
};
|
|
81
84
|
|
|
82
85
|
const sameCursor = (a, b) => {
|
|
@@ -114,7 +117,6 @@ const HANDLERS = {
|
|
|
114
117
|
add: (session) => session.onAdd(),
|
|
115
118
|
unstage: (session) => session.onUnstage(),
|
|
116
119
|
revert: (session) => session.onRevert(),
|
|
117
|
-
skip: (session) => session.onSkip(),
|
|
118
120
|
next: (session) => session.onNext(),
|
|
119
121
|
prev: (session) => session.onPrev(),
|
|
120
122
|
layout: (session) => session.onLayout(),
|
|
@@ -126,7 +128,6 @@ const HANDLERS = {
|
|
|
126
128
|
quit: (session) => session.onQuit(),
|
|
127
129
|
scrollUp: (session) => session.onScroll(-1),
|
|
128
130
|
scrollDown: (session) => session.onScroll(1),
|
|
129
|
-
help: (session) => session.onHelp(),
|
|
130
131
|
};
|
|
131
132
|
|
|
132
133
|
const KEY_MODE = {
|
|
@@ -172,15 +173,15 @@ class Session {
|
|
|
172
173
|
this.stdout = options.stdout;
|
|
173
174
|
this.color = options.color ?? true;
|
|
174
175
|
this.copyText = options.copyText ?? copyText;
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
176
|
+
const termSize = () => {
|
|
177
|
+
const width = this.stdout.columns ?? 80;
|
|
178
|
+
const height = this.stdout.rows ?? 24;
|
|
179
|
+
return { width, height };
|
|
180
|
+
};
|
|
181
|
+
this.getSize = options.getSize ?? termSize;
|
|
181
182
|
this.pane = options.startPane ?? 'files';
|
|
182
183
|
this.rev = options.rev ?? null;
|
|
183
|
-
this.revShort =
|
|
184
|
+
this.revShort = '';
|
|
184
185
|
this.sourceLabel = options.sourceLabel ?? '';
|
|
185
186
|
this.repoName = options.repoName ?? '';
|
|
186
187
|
this.change = options.change ?? null;
|
|
@@ -188,22 +189,24 @@ class Session {
|
|
|
188
189
|
this.readFileSync = options.readFileSync ?? fs.readFileSync;
|
|
189
190
|
this.writeFileSync = options.writeFileSync ?? fs.writeFileSync;
|
|
190
191
|
this.mkdirSync = options.mkdirSync ?? fs.mkdirSync;
|
|
191
|
-
this.now = options.now ??
|
|
192
|
+
this.now = options.now ?? systemNow;
|
|
192
193
|
this.forceNewReview = options.newReview === true;
|
|
194
|
+
this.audit = options.audit === true;
|
|
195
|
+
this.outdatedMap = options.outdatedMap;
|
|
196
|
+
this.auditMap = options.auditMap;
|
|
193
197
|
this.setInterval = options.setInterval ?? setInterval;
|
|
194
198
|
this.clearInterval = options.clearInterval ?? clearInterval;
|
|
195
199
|
}
|
|
196
200
|
|
|
197
201
|
resetState() {
|
|
198
202
|
this.items = [];
|
|
203
|
+
this.dismissed = new Set();
|
|
199
204
|
this.top = this.cwd;
|
|
200
205
|
this.index = 0;
|
|
201
|
-
this.skipped = new Set();
|
|
202
206
|
this.fileCursor = 0;
|
|
203
207
|
this.reviewPath = null;
|
|
204
208
|
this.scroll = 0;
|
|
205
209
|
this.status = '';
|
|
206
|
-
this.help = false;
|
|
207
210
|
this.layout = 'unified';
|
|
208
211
|
this.done = false;
|
|
209
212
|
this.exitCode = 0;
|
|
@@ -213,7 +216,6 @@ class Session {
|
|
|
213
216
|
this.lastSize = null;
|
|
214
217
|
this.selection = null;
|
|
215
218
|
this.mouseAnchor = null;
|
|
216
|
-
this.dragging = false;
|
|
217
219
|
this.pendingClick = null;
|
|
218
220
|
this.abortController = null;
|
|
219
221
|
this.notes = null;
|
|
@@ -240,11 +242,15 @@ class Session {
|
|
|
240
242
|
|
|
241
243
|
load() {
|
|
242
244
|
const here = itemKey(this.items[this.index]);
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
|
|
245
|
+
const commit = this.rev;
|
|
246
|
+
const audit = this.audit;
|
|
247
|
+
const outdatedMap = this.outdatedMap;
|
|
248
|
+
const auditMap = this.auditMap;
|
|
249
|
+
const options = { commit, audit, outdatedMap, auditMap };
|
|
250
|
+
const loaded = this.repo.load(this.cwd, this.paths, options);
|
|
246
251
|
this.top = loaded.top ?? this.cwd;
|
|
247
|
-
|
|
252
|
+
const items = loaded.items;
|
|
253
|
+
this.items = items.filter((item) => !this.dismissed.has(itemKey(item)));
|
|
248
254
|
if (loaded.rev) {
|
|
249
255
|
this.rev = loaded.rev;
|
|
250
256
|
}
|
|
@@ -268,13 +274,7 @@ class Session {
|
|
|
268
274
|
const idx = this.items.findIndex((item) => itemKey(item) === here);
|
|
269
275
|
if (idx >= 0) this.index = idx;
|
|
270
276
|
}
|
|
271
|
-
this.
|
|
272
|
-
if (this.index >= this.items.length) {
|
|
273
|
-
this.index = Math.max(0, this.items.length - 1);
|
|
274
|
-
}
|
|
275
|
-
if (!this.isRemaining(this.items[this.index])) {
|
|
276
|
-
this.focusRemaining(this.index, 1);
|
|
277
|
-
}
|
|
277
|
+
this.clampIndex();
|
|
278
278
|
this.syncReviewPath();
|
|
279
279
|
this.syncFileCursor();
|
|
280
280
|
}
|
|
@@ -304,57 +304,19 @@ class Session {
|
|
|
304
304
|
this.items = mergeTodos(this.items, todos, extra);
|
|
305
305
|
}
|
|
306
306
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
for (const item of this.items) live.add(itemKey(item));
|
|
310
|
-
for (const key of [...this.skipped]) {
|
|
311
|
-
if (!live.has(key)) this.skipped.delete(key);
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
isRemaining(item) {
|
|
316
|
-
if (!item) return false;
|
|
317
|
-
return !this.skipped.has(itemKey(item));
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
remainingIndices() {
|
|
321
|
-
const indices = [];
|
|
322
|
-
for (let i = 0; i < this.items.length; i++) {
|
|
323
|
-
if (this.isRemaining(this.items[i])) indices.push(i);
|
|
324
|
-
}
|
|
325
|
-
return indices;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
focusRemaining(from, direction) {
|
|
329
|
-
const remaining = this.remainingIndices();
|
|
330
|
-
if (!remaining.length) {
|
|
307
|
+
clampIndex() {
|
|
308
|
+
if (!this.items.length) {
|
|
331
309
|
this.index = 0;
|
|
332
|
-
return
|
|
333
|
-
}
|
|
334
|
-
if (direction >= 0) {
|
|
335
|
-
for (const i of remaining) {
|
|
336
|
-
if (i >= from) {
|
|
337
|
-
this.index = i;
|
|
338
|
-
return true;
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
this.index = remaining[remaining.length - 1];
|
|
342
|
-
return true;
|
|
310
|
+
return;
|
|
343
311
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
this.index = i;
|
|
348
|
-
return true;
|
|
349
|
-
}
|
|
312
|
+
if (this.index < 0) this.index = 0;
|
|
313
|
+
if (this.index >= this.items.length) {
|
|
314
|
+
this.index = this.items.length - 1;
|
|
350
315
|
}
|
|
351
|
-
this.index = remaining[0];
|
|
352
|
-
return true;
|
|
353
316
|
}
|
|
354
317
|
|
|
355
318
|
fileList() {
|
|
356
|
-
const
|
|
357
|
-
const entries = fileEntries(this.items, remaining);
|
|
319
|
+
const entries = fileEntries(this.items);
|
|
358
320
|
if (this.sourceLabel) {
|
|
359
321
|
return relabelStatus(entries, 'pr', this.sourceLabel);
|
|
360
322
|
}
|
|
@@ -408,15 +370,10 @@ class Session {
|
|
|
408
370
|
untracked: 0,
|
|
409
371
|
commit: 0,
|
|
410
372
|
pr: 0,
|
|
411
|
-
skipped: 0,
|
|
412
373
|
todo: 0,
|
|
413
374
|
feedback: 0,
|
|
414
375
|
};
|
|
415
376
|
for (const item of this.items) {
|
|
416
|
-
if (!this.isRemaining(item)) {
|
|
417
|
-
counts.skipped += 1;
|
|
418
|
-
continue;
|
|
419
|
-
}
|
|
420
377
|
if (!Object.hasOwn(counts, item.origin)) continue;
|
|
421
378
|
counts[item.origin] += 1;
|
|
422
379
|
}
|
|
@@ -427,19 +384,16 @@ class Session {
|
|
|
427
384
|
}
|
|
428
385
|
|
|
429
386
|
view() {
|
|
430
|
-
const remaining = this.remainingIndices();
|
|
431
|
-
const pos = remaining.indexOf(this.index);
|
|
432
387
|
const templates = this.shownTemplates();
|
|
433
388
|
const change = this.change;
|
|
434
389
|
const isGithubPr = change && change.source === 'github-pr';
|
|
435
390
|
const repoName = this.repoName || path.basename(this.top || this.cwd || '');
|
|
436
391
|
return {
|
|
437
392
|
item: this.current(),
|
|
438
|
-
index:
|
|
439
|
-
total:
|
|
393
|
+
index: this.index,
|
|
394
|
+
total: this.items.length,
|
|
440
395
|
scroll: this.scroll,
|
|
441
396
|
status: this.status,
|
|
442
|
-
help: this.help,
|
|
443
397
|
layout: this.layout,
|
|
444
398
|
counts: this.counts(),
|
|
445
399
|
selection: this.selection,
|
|
@@ -454,7 +408,6 @@ class Session {
|
|
|
454
408
|
mode: this.mode,
|
|
455
409
|
compose: this.composeView(),
|
|
456
410
|
noteText: this.idleNoteText(),
|
|
457
|
-
noteKind: this.idleNoteKind(),
|
|
458
411
|
todos: this.todoTexts(),
|
|
459
412
|
todoFocus: this.clampedTodoFocus(),
|
|
460
413
|
todoEdit: this.todoEditView(),
|
|
@@ -498,11 +451,8 @@ class Session {
|
|
|
498
451
|
this.closeCompose();
|
|
499
452
|
}
|
|
500
453
|
if (this.pane === 'files') {
|
|
501
|
-
|
|
502
|
-
if (
|
|
503
|
-
this.onFileMove(delta);
|
|
504
|
-
return;
|
|
505
|
-
}
|
|
454
|
+
if (action === 'next') return void this.onFileMove(1);
|
|
455
|
+
if (action === 'prev') return void this.onFileMove(-1);
|
|
506
456
|
if (FILES_DISABLED.includes(action)) return;
|
|
507
457
|
}
|
|
508
458
|
const handler = HANDLERS[action];
|
|
@@ -511,9 +461,7 @@ class Session {
|
|
|
511
461
|
}
|
|
512
462
|
|
|
513
463
|
current() {
|
|
514
|
-
|
|
515
|
-
if (!this.isRemaining(item)) return null;
|
|
516
|
-
return item;
|
|
464
|
+
return this.items[this.index] ?? null;
|
|
517
465
|
}
|
|
518
466
|
|
|
519
467
|
reloadAfterChange() {
|
|
@@ -526,7 +474,8 @@ class Session {
|
|
|
526
474
|
this.status = 'nothing to review';
|
|
527
475
|
return;
|
|
528
476
|
}
|
|
529
|
-
this.
|
|
477
|
+
this.index = here;
|
|
478
|
+
this.clampIndex();
|
|
530
479
|
this.syncReviewPath();
|
|
531
480
|
this.syncFileCursor();
|
|
532
481
|
this.scroll = 0;
|
|
@@ -552,7 +501,7 @@ class Session {
|
|
|
552
501
|
|
|
553
502
|
keepOrigin(item, origin) {
|
|
554
503
|
item.origin = origin;
|
|
555
|
-
refreshIndexPatches(this.items, item);
|
|
504
|
+
if (!item.dep) refreshIndexPatches(this.items, item);
|
|
556
505
|
this.clearSelection();
|
|
557
506
|
this.syncReviewPath();
|
|
558
507
|
this.syncFileCursor();
|
|
@@ -578,8 +527,7 @@ class Session {
|
|
|
578
527
|
if (!entry) return [];
|
|
579
528
|
const rel = entry.path;
|
|
580
529
|
const items = [];
|
|
581
|
-
for (const
|
|
582
|
-
const item = this.items[index];
|
|
530
|
+
for (const item of this.items) {
|
|
583
531
|
if (item.origin === 'todo') continue;
|
|
584
532
|
if (itemPath(item) !== rel) continue;
|
|
585
533
|
items.push(item);
|
|
@@ -636,12 +584,14 @@ class Session {
|
|
|
636
584
|
return;
|
|
637
585
|
}
|
|
638
586
|
const rel = itemPath(targets[0]);
|
|
587
|
+
const proposed = targets.some((item) => needsReload(item));
|
|
639
588
|
const ok = this.applyFileGit(
|
|
640
589
|
targets,
|
|
641
590
|
'staged',
|
|
642
591
|
(top, current) => this.repo.add(top, current),
|
|
643
592
|
(item) => this.keepOrigin(item, 'staged'),
|
|
644
593
|
);
|
|
594
|
+
if (ok && proposed) this.reloadAfterChange();
|
|
645
595
|
if (ok) this.selectNextFileAfter(rel);
|
|
646
596
|
}
|
|
647
597
|
|
|
@@ -670,13 +620,12 @@ class Session {
|
|
|
670
620
|
const items = this.fileActionItems();
|
|
671
621
|
if (!this.guardFileGit(items)) return;
|
|
672
622
|
const rel = itemPath(items[0]);
|
|
623
|
+
for (const item of items) {
|
|
624
|
+
if (needsReload(item)) this.dismissed.add(itemKey(item));
|
|
625
|
+
}
|
|
673
626
|
let ok = false;
|
|
674
627
|
try {
|
|
675
|
-
|
|
676
|
-
this.repo.revertFile(this.top, rel, items);
|
|
677
|
-
} else {
|
|
678
|
-
for (const item of items) this.repo.revert(this.top, item);
|
|
679
|
-
}
|
|
628
|
+
this.repo.revertFile(this.top, rel, items);
|
|
680
629
|
this.status = 'reverted';
|
|
681
630
|
ok = true;
|
|
682
631
|
} catch (error) {
|
|
@@ -694,16 +643,21 @@ class Session {
|
|
|
694
643
|
this.status = 'read only';
|
|
695
644
|
return;
|
|
696
645
|
}
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
this.status = blocked;
|
|
646
|
+
if (item.origin === 'staged') {
|
|
647
|
+
this.status = 'already staged';
|
|
700
648
|
return;
|
|
701
649
|
}
|
|
702
650
|
this.applyGit(
|
|
703
651
|
item,
|
|
704
652
|
'staged',
|
|
705
653
|
(top, current) => this.repo.add(top, current),
|
|
706
|
-
() =>
|
|
654
|
+
() => {
|
|
655
|
+
if (needsReload(item)) {
|
|
656
|
+
this.reloadAfterChange();
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
659
|
+
this.keepOrigin(item, 'staged');
|
|
660
|
+
},
|
|
707
661
|
);
|
|
708
662
|
}
|
|
709
663
|
|
|
@@ -740,51 +694,28 @@ class Session {
|
|
|
740
694
|
item,
|
|
741
695
|
'reverted',
|
|
742
696
|
(top, current) => this.repo.revert(top, current),
|
|
743
|
-
() =>
|
|
697
|
+
() => {
|
|
698
|
+
if (needsReload(item)) this.dismissed.add(itemKey(item));
|
|
699
|
+
this.reloadAfterChange();
|
|
700
|
+
},
|
|
744
701
|
);
|
|
745
702
|
}
|
|
746
703
|
|
|
747
|
-
onSkip() {
|
|
748
|
-
const item = this.items[this.index];
|
|
749
|
-
if (!this.isRemaining(item)) return;
|
|
750
|
-
this.skipped.add(itemKey(item));
|
|
751
|
-
this.scroll = 0;
|
|
752
|
-
this.clearSelection();
|
|
753
|
-
const remaining = this.remainingIndices();
|
|
754
|
-
if (!remaining.length) {
|
|
755
|
-
this.status = 'all skipped';
|
|
756
|
-
return;
|
|
757
|
-
}
|
|
758
|
-
this.focusRemaining(this.index + 1, 1);
|
|
759
|
-
this.syncReviewPath();
|
|
760
|
-
this.status = 'skipped';
|
|
761
|
-
}
|
|
762
|
-
|
|
763
704
|
moveRemaining(step) {
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
this.status = 'all skipped';
|
|
767
|
-
return;
|
|
768
|
-
}
|
|
769
|
-
const pos = remaining.indexOf(this.index);
|
|
770
|
-
if (pos < 0) {
|
|
771
|
-
this.focusRemaining(this.index, step);
|
|
772
|
-
this.scroll = 0;
|
|
773
|
-
this.status = '';
|
|
774
|
-
this.clearSelection();
|
|
775
|
-
this.syncReviewPath();
|
|
705
|
+
if (!this.items.length) {
|
|
706
|
+
this.status = 'nothing to review';
|
|
776
707
|
return;
|
|
777
708
|
}
|
|
778
|
-
const next =
|
|
709
|
+
const next = this.index + step;
|
|
779
710
|
if (next < 0) {
|
|
780
711
|
this.status = 'first block';
|
|
781
712
|
return;
|
|
782
713
|
}
|
|
783
|
-
if (next >=
|
|
714
|
+
if (next >= this.items.length) {
|
|
784
715
|
this.status = 'last block';
|
|
785
716
|
return;
|
|
786
717
|
}
|
|
787
|
-
this.index =
|
|
718
|
+
this.index = next;
|
|
788
719
|
this.scroll = 0;
|
|
789
720
|
this.status = '';
|
|
790
721
|
this.clearSelection();
|
|
@@ -792,18 +723,10 @@ class Session {
|
|
|
792
723
|
}
|
|
793
724
|
|
|
794
725
|
onNext() {
|
|
795
|
-
if (this.mode === 'compose') {
|
|
796
|
-
this.commitCompose();
|
|
797
|
-
this.closeCompose();
|
|
798
|
-
}
|
|
799
726
|
this.moveRemaining(1);
|
|
800
727
|
}
|
|
801
728
|
|
|
802
729
|
onPrev() {
|
|
803
|
-
if (this.mode === 'compose') {
|
|
804
|
-
this.commitCompose();
|
|
805
|
-
this.closeCompose();
|
|
806
|
-
}
|
|
807
730
|
this.moveRemaining(-1);
|
|
808
731
|
}
|
|
809
732
|
|
|
@@ -852,7 +775,6 @@ class Session {
|
|
|
852
775
|
this.status = 'not a diff block';
|
|
853
776
|
return;
|
|
854
777
|
}
|
|
855
|
-
this.help = false;
|
|
856
778
|
const prev = this.notes.feedback.get(itemFeedKey(item));
|
|
857
779
|
const text = prev ? prev.text : '';
|
|
858
780
|
this.openCompose('feedback', text);
|
|
@@ -939,9 +861,7 @@ class Session {
|
|
|
939
861
|
this.injectTodos();
|
|
940
862
|
const left = this.fileTodos(file);
|
|
941
863
|
if (!left.length) {
|
|
942
|
-
|
|
943
|
-
this.focusRemaining(this.index, 1);
|
|
944
|
-
}
|
|
864
|
+
this.clampIndex();
|
|
945
865
|
} else if (this.todoFocus >= left.length) {
|
|
946
866
|
this.todoFocus = left.length - 1;
|
|
947
867
|
}
|
|
@@ -970,7 +890,6 @@ class Session {
|
|
|
970
890
|
createTodo(file) {
|
|
971
891
|
if (!file) return;
|
|
972
892
|
this.pane = 'diff';
|
|
973
|
-
this.help = false;
|
|
974
893
|
this.scroll = 0;
|
|
975
894
|
this.clearSelection();
|
|
976
895
|
this.startDraftCompose(file);
|
|
@@ -1012,8 +931,8 @@ class Session {
|
|
|
1012
931
|
|
|
1013
932
|
commitTodo(text) {
|
|
1014
933
|
const id = this.composeTodoId;
|
|
1015
|
-
const
|
|
1016
|
-
|
|
934
|
+
const todos = this.notes.todos;
|
|
935
|
+
const prev = id === null ? null : todos.find((entry) => entry.id === id);
|
|
1017
936
|
const current = this.current();
|
|
1018
937
|
const file = prev ? prev.file : itemPath(current) || this.todoDraftFile;
|
|
1019
938
|
if (prev) {
|
|
@@ -1044,9 +963,7 @@ class Session {
|
|
|
1044
963
|
this.templateFocus = false;
|
|
1045
964
|
this.todoDraftFile = null;
|
|
1046
965
|
this.injectTodos();
|
|
1047
|
-
|
|
1048
|
-
this.focusRemaining(this.index, 1);
|
|
1049
|
-
}
|
|
966
|
+
this.clampIndex();
|
|
1050
967
|
this.syncReviewPath();
|
|
1051
968
|
this.syncFileCursor();
|
|
1052
969
|
}
|
|
@@ -1101,11 +1018,10 @@ class Session {
|
|
|
1101
1018
|
composeView() {
|
|
1102
1019
|
if (this.mode !== 'compose' || !this.editor) return null;
|
|
1103
1020
|
if (this.composeKind !== 'feedback') return null;
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
};
|
|
1021
|
+
const kind = this.composeKind;
|
|
1022
|
+
const text = this.editor.text;
|
|
1023
|
+
const cursor = this.editor.cursor;
|
|
1024
|
+
return { kind, text, cursor };
|
|
1109
1025
|
}
|
|
1110
1026
|
|
|
1111
1027
|
todoEditView() {
|
|
@@ -1116,8 +1032,6 @@ class Session {
|
|
|
1116
1032
|
|
|
1117
1033
|
fileTodos(rel) {
|
|
1118
1034
|
if (!this.notes || !rel) return [];
|
|
1119
|
-
const page = { origin: 'todo', file: { newPath: rel, oldPath: rel } };
|
|
1120
|
-
if (!this.isRemaining(page)) return [];
|
|
1121
1035
|
const todos = [];
|
|
1122
1036
|
for (const todo of this.notes.todos) {
|
|
1123
1037
|
if (todo.file !== rel) continue;
|
|
@@ -1130,10 +1044,8 @@ class Session {
|
|
|
1130
1044
|
const item = this.current();
|
|
1131
1045
|
if (!item || item.origin !== 'todo') return [];
|
|
1132
1046
|
const texts = [];
|
|
1133
|
-
const
|
|
1134
|
-
|
|
1135
|
-
? this.composeTodoId
|
|
1136
|
-
: null;
|
|
1047
|
+
const editingTodo = this.mode === 'compose' && this.composeKind === 'todo';
|
|
1048
|
+
const editingId = editingTodo ? this.composeTodoId : null;
|
|
1137
1049
|
for (const todo of this.fileTodos(itemPath(item))) {
|
|
1138
1050
|
const live = editingId === todo.id && this.editor;
|
|
1139
1051
|
const text = live ? this.editor.text : todo.text;
|
|
@@ -1152,7 +1064,7 @@ class Session {
|
|
|
1152
1064
|
}
|
|
1153
1065
|
|
|
1154
1066
|
clampedTodoFocus() {
|
|
1155
|
-
const last = Math.max(0, this.
|
|
1067
|
+
const last = Math.max(0, this.todoRowCount() - 1);
|
|
1156
1068
|
if (this.todoFocus < 0) return 0;
|
|
1157
1069
|
if (this.todoFocus > last) return last;
|
|
1158
1070
|
return this.todoFocus;
|
|
@@ -1175,12 +1087,6 @@ class Session {
|
|
|
1175
1087
|
else this.todoFocus = next;
|
|
1176
1088
|
}
|
|
1177
1089
|
|
|
1178
|
-
idleNoteKind() {
|
|
1179
|
-
const item = this.current();
|
|
1180
|
-
if (!item || item.origin === 'todo') return '';
|
|
1181
|
-
return 'feedback';
|
|
1182
|
-
}
|
|
1183
|
-
|
|
1184
1090
|
idleNoteText() {
|
|
1185
1091
|
if (!this.notes) return '';
|
|
1186
1092
|
if (this.mode === 'compose') return '';
|
|
@@ -1194,11 +1100,10 @@ class Session {
|
|
|
1194
1100
|
flushReview(force) {
|
|
1195
1101
|
if (!this.notes) return false;
|
|
1196
1102
|
try {
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
});
|
|
1103
|
+
const writeFileSync = this.writeFileSync;
|
|
1104
|
+
const mkdirSync = this.mkdirSync;
|
|
1105
|
+
const io = { writeFileSync, mkdirSync, force: force === true };
|
|
1106
|
+
return flushReview(this.notes, io);
|
|
1202
1107
|
} catch (error) {
|
|
1203
1108
|
this.status = error.message;
|
|
1204
1109
|
return false;
|
|
@@ -1317,7 +1222,6 @@ class Session {
|
|
|
1317
1222
|
|
|
1318
1223
|
showFiles() {
|
|
1319
1224
|
this.pane = 'files';
|
|
1320
|
-
this.help = false;
|
|
1321
1225
|
this.clearSelection();
|
|
1322
1226
|
this.followReviewPath();
|
|
1323
1227
|
}
|
|
@@ -1334,7 +1238,6 @@ class Session {
|
|
|
1334
1238
|
if (this.pane === 'files') {
|
|
1335
1239
|
if (!this.reviewPath) return;
|
|
1336
1240
|
this.pane = 'diff';
|
|
1337
|
-
this.help = false;
|
|
1338
1241
|
this.clearSelection();
|
|
1339
1242
|
return;
|
|
1340
1243
|
}
|
|
@@ -1354,7 +1257,6 @@ class Session {
|
|
|
1354
1257
|
this.pane = 'diff';
|
|
1355
1258
|
this.scroll = 0;
|
|
1356
1259
|
this.status = '';
|
|
1357
|
-
this.help = false;
|
|
1358
1260
|
this.clearSelection();
|
|
1359
1261
|
this.syncReviewPath();
|
|
1360
1262
|
}
|
|
@@ -1362,7 +1264,7 @@ class Session {
|
|
|
1362
1264
|
onFileMove(delta) {
|
|
1363
1265
|
const files = this.fileList();
|
|
1364
1266
|
if (!files.length) {
|
|
1365
|
-
this.status = '
|
|
1267
|
+
this.status = 'nothing to review';
|
|
1366
1268
|
return;
|
|
1367
1269
|
}
|
|
1368
1270
|
const next = this.fileCursor + delta;
|
|
@@ -1395,16 +1297,11 @@ class Session {
|
|
|
1395
1297
|
this.clearSelection();
|
|
1396
1298
|
}
|
|
1397
1299
|
|
|
1398
|
-
onHelp() {
|
|
1399
|
-
this.help = !this.help;
|
|
1400
|
-
this.clearSelection();
|
|
1401
|
-
}
|
|
1402
|
-
|
|
1403
1300
|
onLayout() {
|
|
1404
1301
|
const i = LAYOUTS.indexOf(this.layout);
|
|
1405
1302
|
const next = (i < 0 ? 0 : i + 1) % LAYOUTS.length;
|
|
1406
1303
|
this.layout = LAYOUTS[next];
|
|
1407
|
-
this.status =
|
|
1304
|
+
this.status = this.layout === 'side' ? 'side-by-side' : this.layout;
|
|
1408
1305
|
this.scroll = 0;
|
|
1409
1306
|
this.clearSelection();
|
|
1410
1307
|
}
|
|
@@ -1419,7 +1316,6 @@ class Session {
|
|
|
1419
1316
|
onMousePress(event) {
|
|
1420
1317
|
const cell = this.mouseCell(event);
|
|
1421
1318
|
this.mouseAnchor = cell;
|
|
1422
|
-
this.dragging = false;
|
|
1423
1319
|
this.pendingClick = null;
|
|
1424
1320
|
this.selection = null;
|
|
1425
1321
|
if (this.lastFrame && cell.y === this.lastFrame.height) {
|
|
@@ -1429,7 +1325,6 @@ class Session {
|
|
|
1429
1325
|
|
|
1430
1326
|
onMouseDrag(event) {
|
|
1431
1327
|
if (!this.mouseAnchor) return;
|
|
1432
|
-
this.dragging = true;
|
|
1433
1328
|
this.pendingClick = null;
|
|
1434
1329
|
this.selection = {
|
|
1435
1330
|
start: this.mouseAnchor,
|
|
@@ -1472,7 +1367,6 @@ class Session {
|
|
|
1472
1367
|
const clickId = this.pendingClick;
|
|
1473
1368
|
this.pendingClick = null;
|
|
1474
1369
|
this.mouseAnchor = null;
|
|
1475
|
-
this.dragging = false;
|
|
1476
1370
|
if (this.clickButton(cell, clickId)) return;
|
|
1477
1371
|
const frame = this.lastFrame;
|
|
1478
1372
|
for (const target of RELEASE_HITS) {
|
|
@@ -1502,7 +1396,7 @@ class Session {
|
|
|
1502
1396
|
return;
|
|
1503
1397
|
}
|
|
1504
1398
|
if (event.type !== 'mouse') return;
|
|
1505
|
-
const kind =
|
|
1399
|
+
const kind = event.kind;
|
|
1506
1400
|
const wheel = kind === 'wheelUp' || kind === 'wheelDown';
|
|
1507
1401
|
if (!wheel && event.btn !== 0 && event.btn !== undefined) return;
|
|
1508
1402
|
const handler = MOUSE_KIND[kind];
|
|
@@ -1580,11 +1474,6 @@ class Session {
|
|
|
1580
1474
|
}
|
|
1581
1475
|
|
|
1582
1476
|
module.exports = {
|
|
1583
|
-
LAYOUTS,
|
|
1584
|
-
ENTER_TERM,
|
|
1585
1477
|
LEAVE_TERM,
|
|
1586
|
-
CURSOR_BLINK_MS,
|
|
1587
|
-
HANDLERS,
|
|
1588
|
-
itemKey,
|
|
1589
1478
|
Session,
|
|
1590
1479
|
};
|