reslop 0.2.3 → 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.
- package/CHANGELOG.md +27 -1
- package/README.md +8 -4
- package/bin/reslop.js +4 -2
- package/lib/api.js +2 -1
- package/lib/capabilities.js +0 -4
- package/lib/cli.js +19 -10
- package/lib/clipboard.js +45 -4
- package/lib/deps-diff.js +61 -118
- package/lib/deps.js +166 -235
- package/lib/detect.js +4 -2
- package/lib/diff/align.js +2 -1
- package/lib/diff/diff.js +6 -3
- package/lib/diff/display.js +2 -1
- package/lib/diff/inline.js +68 -2
- package/lib/diff/patch.js +2 -1
- package/lib/diff/unit.js +15 -30
- package/lib/editor.js +91 -13
- package/lib/files.js +54 -27
- package/lib/git-branches.js +107 -154
- package/lib/git-deps.js +78 -155
- package/lib/git-worktree.js +508 -0
- package/lib/git.js +23 -580
- package/lib/github.js +9 -8
- package/lib/gitlab.js +5 -4
- package/lib/highlight/bash.js +2 -1
- package/lib/highlight/core.js +11 -0
- package/lib/highlight/css.js +2 -1
- package/lib/highlight/csv.js +2 -1
- package/lib/highlight/dot.js +3 -12
- package/lib/highlight/html.js +2 -1
- package/lib/highlight/json.js +2 -1
- package/lib/highlight/log.js +5 -11
- package/lib/highlight/txt.js +3 -12
- package/lib/highlight.js +2 -1
- package/lib/keys.js +22 -12
- package/lib/manifest.js +4 -6
- package/lib/npm-commands.js +82 -24
- package/lib/remote.js +21 -20
- package/lib/render/branches.js +9 -27
- package/lib/render/chrome.js +109 -35
- package/lib/render/commits.js +216 -216
- package/lib/render/diff.js +160 -47
- package/lib/render/files.js +9 -26
- package/lib/render/frame.js +97 -118
- package/lib/render/notes.js +74 -26
- package/lib/render/npm.js +104 -30
- package/lib/render/present.js +2 -1
- package/lib/render/primitives.js +128 -52
- package/lib/render/render.js +2 -1
- package/lib/render/unit.js +17 -11
- package/lib/report-model.js +6 -4
- package/lib/report-parse.js +8 -14
- package/lib/report-render.js +38 -21
- package/lib/report-run.js +12 -11
- package/lib/report-test.js +45 -51
- package/lib/report-tools.js +44 -25
- package/lib/review-merge.js +102 -131
- package/lib/review.js +69 -78
- package/lib/select.js +52 -0
- package/lib/session/actions.js +72 -87
- package/lib/session/branches.js +18 -52
- package/lib/session/change-actions.js +175 -147
- package/lib/session/commit.js +65 -61
- package/lib/session/compose.js +152 -83
- package/lib/session/dispatch.js +53 -46
- package/lib/session/edit-click.js +57 -0
- package/lib/session/files-pane.js +30 -51
- package/lib/session/items.js +73 -90
- package/lib/session/lifecycle.js +37 -98
- package/lib/session/load.js +52 -57
- package/lib/session/navigation.js +105 -95
- package/lib/session/npm.js +205 -71
- package/lib/session/ops.js +200 -45
- package/lib/session/pointer.js +33 -8
- package/lib/session/progress.js +9 -6
- package/lib/session/review.js +35 -53
- package/lib/session/tasks.js +292 -0
- package/lib/session/terminal.js +17 -19
- package/lib/session/unit.js +3 -4
- package/lib/session/update.js +76 -96
- package/lib/session/view.js +45 -16
- package/lib/session/watch.js +47 -27
- package/lib/session.js +66 -97
- package/lib/source.js +6 -3
- package/lib/update.js +5 -13
- package/lib/utilities.js +25 -3
- package/lib/wrap.js +18 -1
- package/package.json +1 -1
- package/lib/session/todos.js +0 -293
package/lib/render/commits.js
CHANGED
|
@@ -1,39 +1,101 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const ansi = require('../ansi.js');
|
|
4
|
+
const files = require('../files.js');
|
|
4
5
|
const primitives = require('./primitives.js');
|
|
5
|
-
const
|
|
6
|
+
const wrap = require('../wrap.js');
|
|
7
|
+
const { shortAge } = files;
|
|
8
|
+
const { wrapMultiline, wrapDoc, cursorInWrap } = wrap;
|
|
6
9
|
const { measureColumns, padColumns, joinColumns, paintColumns } = primitives;
|
|
10
|
+
const { padVisible } = primitives;
|
|
7
11
|
|
|
8
12
|
const { THEME, paint, visibleWidth, truncateVisible, seq, EL } = ansi;
|
|
9
|
-
const { FILE_MARK,
|
|
10
|
-
const { paintBodyFill,
|
|
13
|
+
const { FILE_MARK, paintCursorList, fieldWindow } = primitives;
|
|
14
|
+
const { paintBodyFill, listLine, paintListWindow } = primitives;
|
|
11
15
|
|
|
12
16
|
const COMMIT_COL_ALIGN = {
|
|
13
17
|
sha: 'end',
|
|
14
18
|
refs: 'end',
|
|
19
|
+
add: 'start',
|
|
20
|
+
del: 'start',
|
|
15
21
|
date: 'start',
|
|
16
22
|
};
|
|
17
23
|
|
|
18
24
|
const COMMIT_COL_FG = {
|
|
19
25
|
sha: THEME.shaFg,
|
|
20
26
|
refs: THEME.warnFg,
|
|
27
|
+
add: THEME.addLineFg,
|
|
28
|
+
del: THEME.delLineFg,
|
|
21
29
|
date: THEME.mutedFg,
|
|
22
30
|
};
|
|
23
31
|
|
|
24
32
|
const COMMIT_CURRENT_COL_FG = {
|
|
25
33
|
sha: THEME.shaDarkFg,
|
|
34
|
+
refs: THEME.shaDarkFg,
|
|
26
35
|
date: THEME.headerFg,
|
|
27
36
|
};
|
|
28
37
|
|
|
29
38
|
const REFS_MAX = 28;
|
|
30
|
-
const LIST_PAD = 1;
|
|
31
39
|
const COMMIT_TAIL = 1;
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
40
|
+
const lineCounts = (entry) => {
|
|
41
|
+
const added = entry.added ?? 0;
|
|
42
|
+
const removed = entry.removed ?? 0;
|
|
43
|
+
if (!added && !removed) return null;
|
|
44
|
+
return { added, removed };
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const countLabel = (entry) => {
|
|
48
|
+
if (entry && entry.pending) {
|
|
49
|
+
const stagedAdd = entry.stagedAdded ?? 0;
|
|
50
|
+
const unstagedAdd = entry.unstagedAdded ?? 0;
|
|
51
|
+
const stagedDel = entry.stagedRemoved ?? 0;
|
|
52
|
+
const unstagedDel = entry.unstagedRemoved ?? 0;
|
|
53
|
+
const any = stagedAdd || unstagedAdd || stagedDel || unstagedDel;
|
|
54
|
+
if (!any) return null;
|
|
55
|
+
return {
|
|
56
|
+
add: `+${stagedAdd}/${unstagedAdd}`,
|
|
57
|
+
del: `-${stagedDel}/${unstagedDel}`,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
const counts = lineCounts(entry);
|
|
61
|
+
if (!counts) return null;
|
|
62
|
+
return { add: `+${counts.added}`, del: `-${counts.removed}` };
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const DIFF_LABEL = 'Diffs:';
|
|
66
|
+
const DIFF_GAP = ' ';
|
|
67
|
+
|
|
68
|
+
const entryCountWidth = (entry) => {
|
|
69
|
+
const label = countLabel(entry);
|
|
70
|
+
if (!label) return { add: 0, del: 0 };
|
|
71
|
+
return {
|
|
72
|
+
add: visibleWidth(label.add),
|
|
73
|
+
del: visibleWidth(label.del),
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const listCountWidth = (commits) => {
|
|
78
|
+
let add = 0;
|
|
79
|
+
let del = 0;
|
|
80
|
+
for (const entry of commits) {
|
|
81
|
+
const width = entryCountWidth(entry);
|
|
82
|
+
add = Math.max(add, width.add);
|
|
83
|
+
del = Math.max(del, width.del);
|
|
84
|
+
}
|
|
85
|
+
return { add, del };
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const commitRowFields = (entry) => {
|
|
89
|
+
const refs = `${entry.refs ?? ''}`.trim();
|
|
90
|
+
const label = countLabel(entry);
|
|
91
|
+
return {
|
|
92
|
+
sha: entry.shortSha ?? '',
|
|
93
|
+
refs: refs ? truncateVisible(refs, REFS_MAX) : '',
|
|
94
|
+
add: label ? label.add : '',
|
|
95
|
+
del: label ? label.del : '',
|
|
96
|
+
date: shortAge(entry.date ?? ''),
|
|
97
|
+
};
|
|
98
|
+
};
|
|
37
99
|
|
|
38
100
|
const contentWidth = (width) => Math.max(1, width - COMMIT_TAIL);
|
|
39
101
|
|
|
@@ -116,46 +178,38 @@ const paintCommitRow = (entry, width, color, selected, cols, current) => {
|
|
|
116
178
|
return out;
|
|
117
179
|
};
|
|
118
180
|
|
|
119
|
-
const
|
|
181
|
+
const lineEdit = (text, textX, span, scroll) => ({
|
|
182
|
+
x0: 1,
|
|
183
|
+
textX,
|
|
184
|
+
x1: textX + span,
|
|
185
|
+
start: 0,
|
|
186
|
+
text,
|
|
187
|
+
limit: text.length,
|
|
188
|
+
scroll,
|
|
189
|
+
live: true,
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
const subjectWindow = (compose, rest) => {
|
|
193
|
+
const line = splitMessage(compose.text).line;
|
|
194
|
+
const at = Math.min(compose.cursor ?? 0, line.length);
|
|
195
|
+
return fieldWindow(line, at, compose.scrollCol, rest);
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
const paintCommitEdit = (compose, width, color, entry = null, cols = {}) => {
|
|
120
199
|
const text = splitMessage(compose.text).line;
|
|
121
|
-
if (entry && cols) {
|
|
122
|
-
const shown = { ...entry, body: text, subject: text };
|
|
123
|
-
const row = paintCommitRow(shown, width, color, true, cols);
|
|
124
|
-
const inner = contentWidth(width);
|
|
125
|
-
const prefix = ` ${FILE_MARK} `;
|
|
126
|
-
const parts = padColumns(commitRowFields(entry), cols, COMMIT_COL_ALIGN);
|
|
127
|
-
const suffix = joinColumns(parts, cols);
|
|
128
|
-
const rest = Math.max(1, inner - visibleWidth(prefix + suffix));
|
|
129
|
-
const clipped = truncateVisible(text, rest);
|
|
130
|
-
const prefixW = visibleWidth(prefix);
|
|
131
|
-
const col = Math.min(compose.cursor ?? 0, visibleWidth(clipped));
|
|
132
|
-
return {
|
|
133
|
-
row,
|
|
134
|
-
cursor: { x: prefixW + col + 1 },
|
|
135
|
-
at: 'replace',
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
const inner = contentWidth(width);
|
|
139
200
|
const prefix = ` ${FILE_MARK} `;
|
|
140
201
|
const prefixW = visibleWidth(prefix);
|
|
141
|
-
const
|
|
142
|
-
const
|
|
143
|
-
const
|
|
144
|
-
const
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
row += paint(prefix, fgRgb, bgRgb, color);
|
|
153
|
-
row += paint(clipped, nameFg, bgRgb, color);
|
|
154
|
-
row += paint(gap, fgRgb, bgRgb, color);
|
|
155
|
-
row += paint(tail, fgRgb, bgRgb, color);
|
|
156
|
-
}
|
|
157
|
-
const col = Math.min(compose.cursor ?? 0, visibleWidth(clipped));
|
|
158
|
-
return { row, cursor: { x: prefixW + col + 1 }, at: 'start' };
|
|
202
|
+
const fields = commitRowFields(entry ?? {});
|
|
203
|
+
const suffix = joinColumns(padColumns(fields, cols, COMMIT_COL_ALIGN), cols);
|
|
204
|
+
const rest = Math.max(1, contentWidth(width) - visibleWidth(prefix + suffix));
|
|
205
|
+
const win = subjectWindow(compose, rest);
|
|
206
|
+
const shown = { ...entry, body: win.text, subject: win.text };
|
|
207
|
+
return {
|
|
208
|
+
row: paintCommitRow(shown, width, color, true, cols),
|
|
209
|
+
cursor: { x: prefixW + win.col + 1, scroll: win.scroll },
|
|
210
|
+
at: entry ? 'replace' : 'start',
|
|
211
|
+
edit: lineEdit(text, prefixW + 1, rest, win.scroll),
|
|
212
|
+
};
|
|
159
213
|
};
|
|
160
214
|
|
|
161
215
|
const pendingAt = (commits) => {
|
|
@@ -268,19 +322,45 @@ const partsWidth = (parts) => {
|
|
|
268
322
|
|
|
269
323
|
const timeNeed = (entry) => {
|
|
270
324
|
const when = `${entry.when ?? ''}`.trim();
|
|
271
|
-
const ago =
|
|
325
|
+
const ago = shortAge(entry.date ?? '');
|
|
272
326
|
if (when && ago) return visibleWidth(when) + COL_GAP + visibleWidth(ago);
|
|
273
327
|
return visibleWidth(when || ago);
|
|
274
328
|
};
|
|
275
329
|
|
|
276
330
|
const refsText = (entry) => `${entry.refs ?? ''}`.trim();
|
|
277
331
|
|
|
278
|
-
const
|
|
279
|
-
|
|
332
|
+
const diffLine = (entry, widths) => {
|
|
333
|
+
const label = countLabel(entry);
|
|
334
|
+
if (!label) return null;
|
|
335
|
+
const add = padVisible(label.add, widths.add, 'start');
|
|
336
|
+
const del = padVisible(label.del, widths.del, 'start');
|
|
337
|
+
const text = `${DIFF_LABEL}${DIFF_GAP}${add}${DIFF_GAP}${del}`;
|
|
338
|
+
return { add, del, text };
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
const diffCountParts = (entry, widths, rightW) => {
|
|
342
|
+
const line = diffLine(entry, widths);
|
|
343
|
+
if (!line || !rightW) return [];
|
|
344
|
+
const pad = Math.max(0, rightW - visibleWidth(line.text));
|
|
345
|
+
return [
|
|
346
|
+
{ text: ' '.repeat(pad), kind: 'meta' },
|
|
347
|
+
{ text: DIFF_LABEL, kind: 'meta' },
|
|
348
|
+
{ text: DIFF_GAP, kind: 'meta' },
|
|
349
|
+
{ text: line.add, kind: 'add' },
|
|
350
|
+
{ text: DIFF_GAP, kind: 'meta' },
|
|
351
|
+
{ text: line.del, kind: 'del' },
|
|
352
|
+
];
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
const rightNeed = (entry, widths = entryCountWidth(entry)) => {
|
|
356
|
+
const line = diffLine(entry, widths);
|
|
357
|
+
return Math.max(
|
|
280
358
|
partsWidth(authorParts(entry)),
|
|
281
359
|
timeNeed(entry),
|
|
282
360
|
visibleWidth(refsText(entry)),
|
|
361
|
+
line ? visibleWidth(line.text) : 0,
|
|
283
362
|
);
|
|
363
|
+
};
|
|
284
364
|
|
|
285
365
|
const spreadTime = (when, ago, width) => {
|
|
286
366
|
const agoW = visibleWidth(ago);
|
|
@@ -309,7 +389,7 @@ const alignEnd = (text, width, kind) => {
|
|
|
309
389
|
|
|
310
390
|
const timeParts = (entry, width) => {
|
|
311
391
|
const when = `${entry.when ?? ''}`.trim();
|
|
312
|
-
const ago =
|
|
392
|
+
const ago = shortAge(entry.date ?? '');
|
|
313
393
|
if (!width) return [];
|
|
314
394
|
if (when && ago) return spreadTime(when, ago, width);
|
|
315
395
|
if (ago) return alignEnd(ago, width, 'meta');
|
|
@@ -317,10 +397,16 @@ const timeParts = (entry, width) => {
|
|
|
317
397
|
return [];
|
|
318
398
|
};
|
|
319
399
|
|
|
320
|
-
const rightRows = (entry, rightW) => {
|
|
321
|
-
const rows = [
|
|
400
|
+
const rightRows = (entry, rightW, widths) => {
|
|
401
|
+
const rows = [];
|
|
402
|
+
const author = authorParts(entry);
|
|
403
|
+
if (author.length) rows.push(author);
|
|
404
|
+
const time = timeParts(entry, rightW);
|
|
405
|
+
if (time.length) rows.push(time);
|
|
322
406
|
const refs = refsText(entry);
|
|
323
407
|
if (refs) rows.push([{ text: refs, kind: 'refs' }]);
|
|
408
|
+
const diff = diffCountParts(entry, widths, rightW);
|
|
409
|
+
if (diff.length) rows.push(diff);
|
|
324
410
|
return rows;
|
|
325
411
|
};
|
|
326
412
|
|
|
@@ -342,7 +428,8 @@ const panelLeft = (entry, leftW, edit) => {
|
|
|
342
428
|
const parts = edit
|
|
343
429
|
? messagePartsFrom(edit.text ?? '', leftW)
|
|
344
430
|
: messageParts(entry, leftW);
|
|
345
|
-
|
|
431
|
+
if (!entry.sha) return parts;
|
|
432
|
+
return [{ text: entry.sha, kind: 'hash' }, ...parts];
|
|
346
433
|
};
|
|
347
434
|
|
|
348
435
|
const commitMessageWidth = (entry, screenWidth) => {
|
|
@@ -368,9 +455,11 @@ const messageCaret = (text, cursor, width, row, first, selected) => {
|
|
|
368
455
|
};
|
|
369
456
|
|
|
370
457
|
const pieceFg = (kind, tone) => {
|
|
458
|
+
if (kind === 'add') return THEME.addLineFg;
|
|
459
|
+
if (kind === 'del') return THEME.delLineFg;
|
|
371
460
|
if (tone.current) {
|
|
372
461
|
if (kind === 'hash') return THEME.shaDarkFg;
|
|
373
|
-
if (kind === 'refs') return THEME.
|
|
462
|
+
if (kind === 'refs') return THEME.shaDarkFg;
|
|
374
463
|
if (kind === 'text' || kind === 'body') return THEME.mutedFg;
|
|
375
464
|
return tone.fgRgb;
|
|
376
465
|
}
|
|
@@ -424,20 +513,32 @@ const paintPanelLine = (spec) => {
|
|
|
424
513
|
);
|
|
425
514
|
};
|
|
426
515
|
|
|
427
|
-
const
|
|
428
|
-
|
|
429
|
-
row
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
516
|
+
const editFromDoc = (doc, row, textX, span) => {
|
|
517
|
+
if (row < 0 || row >= doc.length) return null;
|
|
518
|
+
const piece = doc[row];
|
|
519
|
+
return {
|
|
520
|
+
x0: 1,
|
|
521
|
+
textX,
|
|
522
|
+
x1: textX + span,
|
|
523
|
+
start: piece.start,
|
|
524
|
+
text: piece.text,
|
|
525
|
+
limit: piece.start + piece.text.length,
|
|
526
|
+
live: true,
|
|
527
|
+
};
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
const editLines = (editHit) => (editHit ? [editHit] : undefined);
|
|
433
531
|
|
|
434
|
-
const commitLines = (entry, index,
|
|
532
|
+
const commitLines = (entry, index, spec) => {
|
|
533
|
+
const { width, color, selected, edit, current, diffWidths } = spec;
|
|
435
534
|
const inner = contentWidth(width);
|
|
436
535
|
const hashW = visibleWidth(entry.sha ?? '');
|
|
437
|
-
const
|
|
438
|
-
const
|
|
536
|
+
const widths = diffWidths ?? entryCountWidth(entry);
|
|
537
|
+
const cols = panelWidths(rightNeed(entry, widths), hashW, inner);
|
|
538
|
+
const rights = rightRows(entry, cols.rightW, widths);
|
|
439
539
|
const left = panelLeft(entry, cols.leftW, edit);
|
|
440
540
|
const count = Math.max(left.length, rights.length);
|
|
541
|
+
const doc = edit ? wrapDoc(`${edit.text ?? ''}`, cols.leftW) : null;
|
|
441
542
|
const lines = [];
|
|
442
543
|
for (let row = 0; row < count; row++) {
|
|
443
544
|
const line = left[row] ?? { text: '', kind: 'text' };
|
|
@@ -455,17 +556,23 @@ const commitLines = (entry, index, width, color, selected, edit, current) => {
|
|
|
455
556
|
leftKind: line.kind,
|
|
456
557
|
rightKind: 'meta',
|
|
457
558
|
});
|
|
559
|
+
const messageRow = entry.sha ? row - 1 : row;
|
|
560
|
+
const first = !entry.sha && row === 0;
|
|
458
561
|
const caret = edit
|
|
459
562
|
? messageCaret(
|
|
460
563
|
edit.text,
|
|
461
564
|
edit.cursor,
|
|
462
565
|
cols.leftW,
|
|
463
|
-
|
|
464
|
-
|
|
566
|
+
messageRow,
|
|
567
|
+
first,
|
|
465
568
|
selected,
|
|
466
569
|
)
|
|
467
570
|
: null;
|
|
468
|
-
|
|
571
|
+
const textX = prefixWidth(first, selected) + 1;
|
|
572
|
+
const editHit = doc
|
|
573
|
+
? editFromDoc(doc, messageRow, textX, cols.leftW)
|
|
574
|
+
: null;
|
|
575
|
+
lines.push(listLine(painted, index, caret, editLines(editHit)));
|
|
469
576
|
}
|
|
470
577
|
return lines;
|
|
471
578
|
};
|
|
@@ -474,6 +581,7 @@ const draftLines = (text, cursor, width, color) => {
|
|
|
474
581
|
const inner = contentWidth(width);
|
|
475
582
|
const leftW = Math.max(1, inner - visibleWidth(FULL_INDENT));
|
|
476
583
|
const parts = messagePartsFrom(text, leftW);
|
|
584
|
+
const doc = wrapDoc(`${text ?? ''}`, leftW);
|
|
477
585
|
const lines = [];
|
|
478
586
|
for (let row = 0; row < parts.length; row++) {
|
|
479
587
|
const line = parts[row];
|
|
@@ -491,7 +599,9 @@ const draftLines = (text, cursor, width, color) => {
|
|
|
491
599
|
rightKind: 'meta',
|
|
492
600
|
});
|
|
493
601
|
const caret = messageCaret(text, cursor, leftW, row, row === 0, true);
|
|
494
|
-
|
|
602
|
+
const textX = prefixWidth(row === 0, true) + 1;
|
|
603
|
+
const editHit = editFromDoc(doc, row, textX, leftW);
|
|
604
|
+
lines.push(listLine(painted, -1, caret, editLines(editHit)));
|
|
495
605
|
}
|
|
496
606
|
return lines;
|
|
497
607
|
};
|
|
@@ -511,181 +621,71 @@ const composeShowsDraft = (compose, commits) => {
|
|
|
511
621
|
return true;
|
|
512
622
|
};
|
|
513
623
|
|
|
514
|
-
const
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
const flattenCommits = (commits, cursor, width, color, compose, rev, short) => {
|
|
518
|
-
const lines = [];
|
|
624
|
+
const flattenCommits = (view, commits, width, color) => {
|
|
625
|
+
const cursor = view.commitCursor ?? 0;
|
|
626
|
+
const compose = view.compose ?? null;
|
|
519
627
|
const editing = compose && compose.kind === 'commit';
|
|
520
|
-
const
|
|
521
|
-
|
|
522
|
-
|
|
628
|
+
const diffWidths = listCountWidth(commits);
|
|
629
|
+
const gap = listLine(paintBodyFill(width, color, 'files'), -1);
|
|
630
|
+
const lines = [];
|
|
523
631
|
if (composeShowsDraft(compose, commits)) {
|
|
524
|
-
const
|
|
525
|
-
|
|
526
|
-
compose.cursor ?? 0,
|
|
527
|
-
width,
|
|
528
|
-
color,
|
|
529
|
-
);
|
|
530
|
-
for (const line of draft) lines.push(line);
|
|
632
|
+
const text = compose.text ?? '';
|
|
633
|
+
lines.push(...draftLines(text, compose.cursor ?? 0, width, color));
|
|
531
634
|
}
|
|
532
635
|
for (let index = 0; index < commits.length; index++) {
|
|
533
|
-
|
|
636
|
+
if (lines.length) lines.push(gap);
|
|
637
|
+
const entry = commits[index];
|
|
534
638
|
const inplace = composeEditsIndex(compose, commits, index, cursor);
|
|
535
639
|
const selected = inplace || (!editing && index === cursor);
|
|
536
|
-
const
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
const
|
|
540
|
-
|
|
541
|
-
index,
|
|
640
|
+
const text = compose?.text ?? '';
|
|
641
|
+
const caret = compose?.cursor ?? 0;
|
|
642
|
+
const edit = inplace ? { text, cursor: caret } : null;
|
|
643
|
+
const current = viewedCommit(entry, view.rev, view.revShort);
|
|
644
|
+
const block = commitLines(entry, index, {
|
|
542
645
|
width,
|
|
543
646
|
color,
|
|
544
647
|
selected,
|
|
545
648
|
edit,
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
649
|
+
current,
|
|
650
|
+
diffWidths,
|
|
651
|
+
});
|
|
652
|
+
lines.push(...block);
|
|
549
653
|
}
|
|
550
654
|
return lines;
|
|
551
655
|
};
|
|
552
656
|
|
|
553
657
|
const focusLine = (lines, cursor, compose) => {
|
|
554
658
|
if (compose && compose.kind === 'commit') {
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
}
|
|
659
|
+
const at = lines.findIndex((line) => line.cursor);
|
|
660
|
+
if (at >= 0) return at;
|
|
558
661
|
}
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
if (line.hit && line.commit === cursor) return i;
|
|
562
|
-
}
|
|
563
|
-
return 0;
|
|
564
|
-
};
|
|
565
|
-
|
|
566
|
-
const paintLineWindow = (
|
|
567
|
-
lines,
|
|
568
|
-
focus,
|
|
569
|
-
width,
|
|
570
|
-
color,
|
|
571
|
-
bodyH,
|
|
572
|
-
headerLines,
|
|
573
|
-
offset,
|
|
574
|
-
) => {
|
|
575
|
-
const pad = bodyH >= LIST_PAD * 2 + 1 ? LIST_PAD : 0;
|
|
576
|
-
const listH = bodyH - pad * 2;
|
|
577
|
-
const start = listWindowStart(focus, offset, listH, lines.length);
|
|
578
|
-
const blank = paintBodyFill(width, color, 'files');
|
|
579
|
-
const body = [];
|
|
580
|
-
const fileHits = [];
|
|
581
|
-
let textCursor = null;
|
|
582
|
-
if (pad) body.push(blank);
|
|
583
|
-
for (let i = 0; i < listH; i++) {
|
|
584
|
-
const line = lines[start + i];
|
|
585
|
-
if (!line) break;
|
|
586
|
-
body.push(line.row);
|
|
587
|
-
if (line.cursor) {
|
|
588
|
-
textCursor = { x: line.cursor.x, row: body.length - 1 };
|
|
589
|
-
}
|
|
590
|
-
if (!line.hit) continue;
|
|
591
|
-
const y = headerLines + pad + i + 1;
|
|
592
|
-
fileHits.push({ y, cursor: line.commit });
|
|
593
|
-
}
|
|
594
|
-
if (pad) body.push(blank);
|
|
595
|
-
return { body, fileHits, cursor: textCursor, offset: start };
|
|
662
|
+
const at = lines.findIndex((line) => line.hit && line.index === cursor);
|
|
663
|
+
return Math.max(0, at);
|
|
596
664
|
};
|
|
597
665
|
|
|
598
|
-
const
|
|
666
|
+
const paintBodyCommits = (view, width, color, bodyH, headerLines) => {
|
|
667
|
+
const pane = { width, color, bodyH, headerLines, offset: view.listScroll };
|
|
599
668
|
const commits = view.commits ?? [];
|
|
600
669
|
const cursor = view.commitCursor ?? 0;
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
view.
|
|
609
|
-
view.revShort,
|
|
610
|
-
);
|
|
611
|
-
const focus = focusLine(lines, cursor, compose);
|
|
612
|
-
return paintLineWindow(
|
|
613
|
-
lines,
|
|
614
|
-
focus,
|
|
615
|
-
width,
|
|
616
|
-
color,
|
|
617
|
-
bodyH,
|
|
618
|
-
headerLines,
|
|
619
|
-
view.listScroll,
|
|
620
|
-
);
|
|
621
|
-
};
|
|
622
|
-
|
|
623
|
-
const paintBriefCommits = (
|
|
624
|
-
commits,
|
|
625
|
-
cursor,
|
|
626
|
-
width,
|
|
627
|
-
color,
|
|
628
|
-
bodyH,
|
|
629
|
-
headerLines,
|
|
630
|
-
extra,
|
|
631
|
-
offset,
|
|
632
|
-
cols,
|
|
633
|
-
rev,
|
|
634
|
-
revShort,
|
|
635
|
-
) => {
|
|
636
|
-
const paintRow = (entry, rowWidth, rowColor, selected) =>
|
|
637
|
-
paintCommitRow(
|
|
638
|
-
entry,
|
|
639
|
-
rowWidth,
|
|
640
|
-
rowColor,
|
|
641
|
-
selected,
|
|
642
|
-
cols,
|
|
643
|
-
viewedCommit(entry, rev, revShort),
|
|
644
|
-
);
|
|
645
|
-
return paintCursorList(
|
|
670
|
+
if (view.commitView === 'full') {
|
|
671
|
+
const lines = flattenCommits(view, commits, width, color);
|
|
672
|
+
const focus = focusLine(lines, cursor, view.compose);
|
|
673
|
+
return paintListWindow(lines.length, focus, pane, (i) => lines[i]);
|
|
674
|
+
}
|
|
675
|
+
const cols = measureColumns(commits, commitRowFields, COMMIT_COL_ALIGN);
|
|
676
|
+
const extra = commitEditRow(
|
|
677
|
+
view.compose,
|
|
646
678
|
commits,
|
|
647
679
|
cursor,
|
|
648
680
|
width,
|
|
649
681
|
color,
|
|
650
|
-
|
|
651
|
-
headerLines,
|
|
652
|
-
paintRow,
|
|
653
|
-
extra,
|
|
654
|
-
offset,
|
|
682
|
+
cols,
|
|
655
683
|
);
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
const cursor = view.commitCursor ?? 0;
|
|
662
|
-
const full = view.commitView === 'full';
|
|
663
|
-
const extra = full
|
|
664
|
-
? null
|
|
665
|
-
: commitEditRow(view.compose, commits, cursor, width, color, cols);
|
|
666
|
-
const painted = full
|
|
667
|
-
? paintFullCommits(view, width, color, bodyH, headerLines)
|
|
668
|
-
: paintBriefCommits(
|
|
669
|
-
commits,
|
|
670
|
-
cursor,
|
|
671
|
-
width,
|
|
672
|
-
color,
|
|
673
|
-
bodyH,
|
|
674
|
-
headerLines,
|
|
675
|
-
extra,
|
|
676
|
-
view.listScroll,
|
|
677
|
-
cols,
|
|
678
|
-
view.rev,
|
|
679
|
-
view.revShort,
|
|
680
|
-
);
|
|
681
|
-
return paneResult({
|
|
682
|
-
body: painted.body,
|
|
683
|
-
fileHits: painted.fileHits,
|
|
684
|
-
todoOwners: [],
|
|
685
|
-
cursor: painted.cursor,
|
|
686
|
-
splitBody: false,
|
|
687
|
-
listScroll: painted.offset,
|
|
688
|
-
});
|
|
684
|
+
const paintRow = (entry, selected) => {
|
|
685
|
+
const current = viewedCommit(entry, view.rev, view.revShort);
|
|
686
|
+
return paintCommitRow(entry, width, color, selected, cols, current);
|
|
687
|
+
};
|
|
688
|
+
return paintCursorList(commits, cursor, pane, paintRow, extra);
|
|
689
689
|
};
|
|
690
690
|
|
|
691
691
|
module.exports = {
|