reslop 0.2.4 → 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.
- package/CHANGELOG.md +25 -1
- package/LICENSE +1 -1
- package/README.md +12 -13
- package/bin/reslop.js +3 -8
- package/lib/ansi.js +32 -19
- package/lib/capabilities.js +8 -12
- package/lib/cli.js +40 -74
- package/lib/clipboard.js +48 -18
- package/lib/dashboard/git.js +128 -0
- package/lib/dashboard/model.js +332 -0
- package/lib/dashboard/npm.js +193 -0
- package/lib/dashboard/tree.js +278 -0
- package/lib/deps-diff.js +196 -404
- package/lib/deps.js +240 -399
- package/lib/detect.js +8 -18
- package/lib/diff/align.js +41 -113
- package/lib/diff/diff.js +12 -43
- package/lib/diff/display.js +25 -36
- package/lib/diff/edit.js +6 -20
- package/lib/diff/inline.js +138 -141
- package/lib/diff/items.js +33 -47
- package/lib/diff/parse.js +28 -56
- package/lib/diff/patch.js +12 -33
- package/lib/diff/unit.js +90 -206
- package/lib/editor.js +98 -55
- package/lib/files.js +86 -103
- package/lib/git-branches.js +254 -416
- package/lib/git-deps.js +182 -344
- package/lib/git-reword-todo.js +5 -13
- package/lib/git-worktree.js +141 -212
- package/lib/git.js +21 -49
- package/lib/github.js +67 -181
- package/lib/gitlab.js +40 -90
- package/lib/highlight/bash.js +55 -177
- package/lib/highlight/core.js +157 -132
- package/lib/highlight/css.js +25 -58
- package/lib/highlight/csv.js +19 -37
- package/lib/highlight/dart.js +72 -213
- package/lib/highlight/dot.js +16 -26
- package/lib/highlight/html.js +42 -63
- package/lib/highlight/js.js +177 -506
- package/lib/highlight/json.js +17 -37
- package/lib/highlight/log.js +22 -35
- package/lib/highlight/txt.js +9 -22
- package/lib/highlight.js +17 -46
- package/lib/keys.js +62 -85
- package/lib/manifest.js +67 -130
- package/lib/npm-commands.js +119 -189
- package/lib/remote.js +141 -197
- package/lib/render/branches.js +66 -73
- package/lib/render/chrome.js +264 -323
- package/lib/render/commits.js +187 -500
- package/lib/render/dash-activity.js +212 -0
- package/lib/render/dash-blocks.js +245 -0
- package/lib/render/dash-table.js +290 -0
- package/lib/render/dashboard.js +62 -0
- package/lib/render/diff.js +123 -228
- package/lib/render/files.js +45 -99
- package/lib/render/frame.js +129 -183
- package/lib/render/notes.js +144 -160
- package/lib/render/npm.js +234 -112
- package/lib/render/present.js +4 -11
- package/lib/render/primitives.js +131 -170
- package/lib/render/render.js +5 -14
- package/lib/render/report.js +43 -0
- package/lib/render/tiles.js +260 -0
- package/lib/render/unit.js +15 -28
- package/lib/report-model.js +110 -33
- package/lib/report-parse.js +56 -38
- package/lib/report-render.js +102 -59
- package/lib/report-run.js +87 -78
- package/lib/report-test.js +256 -141
- package/lib/report-tools.js +96 -161
- package/lib/review-merge.js +114 -152
- package/lib/review.js +115 -189
- package/lib/runs.js +225 -0
- package/lib/select.js +89 -75
- package/lib/session/accessors.js +14 -21
- package/lib/session/actions.js +82 -63
- package/lib/session/branches.js +193 -247
- package/lib/session/change-actions.js +171 -214
- package/lib/session/commit.js +280 -342
- package/lib/session/compose.js +559 -674
- package/lib/session/dashboard.js +385 -0
- package/lib/session/dispatch.js +164 -157
- package/lib/session/edit-click.js +57 -0
- package/lib/session/files-pane.js +85 -53
- package/lib/session/items.js +73 -104
- package/lib/session/lifecycle.js +403 -541
- package/lib/session/load.js +48 -68
- package/lib/session/navigation.js +96 -87
- package/lib/session/npm.js +409 -345
- package/lib/session/ops.js +196 -63
- package/lib/session/pointer.js +23 -15
- package/lib/session/progress.js +33 -21
- package/lib/session/review.js +33 -54
- package/lib/session/tasks.js +333 -0
- package/lib/session/templates.js +51 -59
- package/lib/session/terminal.js +85 -136
- package/lib/session/unit.js +3 -4
- package/lib/session/update.js +76 -97
- package/lib/session/view.js +52 -83
- package/lib/session/watch.js +208 -204
- package/lib/session.js +112 -237
- package/lib/update.js +45 -116
- package/lib/utilities.js +67 -89
- package/lib/wrap.js +33 -44
- package/package.json +1 -1
- package/lib/session/todos.js +0 -293
package/lib/render/commits.js
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
const ansi = require('../ansi.js');
|
|
4
4
|
const files = require('../files.js');
|
|
5
|
-
const primitives = require('./primitives.js');
|
|
6
5
|
const wrap = require('../wrap.js');
|
|
6
|
+
const primitives = require('./primitives.js');
|
|
7
|
+
|
|
7
8
|
const { shortAge } = files;
|
|
8
|
-
const { wrapMultiline, cursorInWrap } = wrap;
|
|
9
|
+
const { wrapMultiline, wrapDoc, cursorInWrap } = wrap;
|
|
10
|
+
const { THEME, paint, visibleWidth, trimVisible, seq, EL } = ansi;
|
|
11
|
+
const { MARK_W, markPrefix, padVisible } = primitives;
|
|
12
|
+
const { editSpan, fieldWindow, paintBodyFill, listLine } = primitives;
|
|
13
|
+
const { paintListWindow, paintCursorList } = primitives;
|
|
9
14
|
const { measureColumns, padColumns, joinColumns, paintColumns } = primitives;
|
|
10
|
-
const { padVisible } = primitives;
|
|
11
|
-
|
|
12
|
-
const { THEME, paint, visibleWidth, truncateVisible, seq, EL } = ansi;
|
|
13
|
-
const { FILE_MARK, paneResult, paintCursorList } = primitives;
|
|
14
|
-
const { paintBodyFill, listWindowStart } = primitives;
|
|
15
15
|
|
|
16
16
|
const COMMIT_COL_ALIGN = {
|
|
17
17
|
sha: 'end',
|
|
@@ -21,6 +21,8 @@ const COMMIT_COL_ALIGN = {
|
|
|
21
21
|
date: 'start',
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
+
const COUNT_ALIGN = { add: 'start', del: 'start' };
|
|
25
|
+
|
|
24
26
|
const COMMIT_COL_FG = {
|
|
25
27
|
sha: THEME.shaFg,
|
|
26
28
|
refs: THEME.warnFg,
|
|
@@ -30,70 +32,53 @@ const COMMIT_COL_FG = {
|
|
|
30
32
|
};
|
|
31
33
|
|
|
32
34
|
const COMMIT_CURRENT_COL_FG = {
|
|
35
|
+
...COMMIT_COL_FG,
|
|
33
36
|
sha: THEME.shaDarkFg,
|
|
37
|
+
refs: THEME.shaDarkFg,
|
|
34
38
|
date: THEME.headerFg,
|
|
35
39
|
};
|
|
36
40
|
|
|
37
41
|
const REFS_MAX = 28;
|
|
38
|
-
const LIST_PAD = 1;
|
|
39
42
|
const COMMIT_TAIL = 1;
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
};
|
|
43
|
+
const DIFF_LABEL = 'Diffs:';
|
|
44
|
+
const DIFF_GAP = ' ';
|
|
45
|
+
const COL_GAP = 2;
|
|
46
|
+
const MIN_LEFT = 8;
|
|
47
|
+
const FULL_INDENT = ' '.repeat(MARK_W);
|
|
48
|
+
const NO_COUNT = { add: '', del: '' };
|
|
46
49
|
|
|
47
50
|
const countLabel = (entry) => {
|
|
48
|
-
if (entry
|
|
51
|
+
if (entry.pending) {
|
|
49
52
|
const stagedAdd = entry.stagedAdded ?? 0;
|
|
50
53
|
const unstagedAdd = entry.unstagedAdded ?? 0;
|
|
51
54
|
const stagedDel = entry.stagedRemoved ?? 0;
|
|
52
55
|
const unstagedDel = entry.unstagedRemoved ?? 0;
|
|
53
56
|
const any = stagedAdd || unstagedAdd || stagedDel || unstagedDel;
|
|
54
|
-
if (!any) return
|
|
57
|
+
if (!any) return NO_COUNT;
|
|
55
58
|
return {
|
|
56
59
|
add: `+${stagedAdd}/${unstagedAdd}`,
|
|
57
60
|
del: `-${stagedDel}/${unstagedDel}`,
|
|
58
61
|
};
|
|
59
62
|
}
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
+
const added = entry.added ?? 0;
|
|
64
|
+
const removed = entry.removed ?? 0;
|
|
65
|
+
if (!added && !removed) return NO_COUNT;
|
|
66
|
+
return { add: `+${added}`, del: `-${removed}` };
|
|
63
67
|
};
|
|
64
68
|
|
|
65
|
-
const
|
|
66
|
-
|
|
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
|
-
};
|
|
69
|
+
const countWidths = (entries) =>
|
|
70
|
+
measureColumns(entries, countLabel, COUNT_ALIGN);
|
|
76
71
|
|
|
77
|
-
const
|
|
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
|
-
};
|
|
72
|
+
const refsText = (entry) => `${entry.refs ?? ''}`.trim();
|
|
87
73
|
|
|
88
74
|
const commitRowFields = (entry) => {
|
|
89
|
-
const
|
|
90
|
-
const label = countLabel(entry);
|
|
75
|
+
const { add, del } = countLabel(entry);
|
|
91
76
|
return {
|
|
92
77
|
sha: entry.shortSha ?? '',
|
|
93
|
-
refs:
|
|
94
|
-
add
|
|
95
|
-
del
|
|
96
|
-
date: shortAge(entry.date
|
|
78
|
+
refs: trimVisible(refsText(entry), REFS_MAX),
|
|
79
|
+
add,
|
|
80
|
+
del,
|
|
81
|
+
date: shortAge(entry.date),
|
|
97
82
|
};
|
|
98
83
|
};
|
|
99
84
|
|
|
@@ -115,18 +100,11 @@ const commitText = (entry) => {
|
|
|
115
100
|
const commitLine = (entry) => splitMessage(commitText(entry)).line;
|
|
116
101
|
|
|
117
102
|
const viewedCommit = (entry, rev, revShort) => {
|
|
118
|
-
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
const sha = entry && entry.sha ? `${entry.sha}` : '';
|
|
122
|
-
const brief = entry && entry.shortSha ? `${entry.shortSha}` : '';
|
|
123
|
-
if (want && (sha === want || brief === want)) return true;
|
|
124
|
-
if (short && (sha === short || brief === short)) return true;
|
|
125
|
-
return false;
|
|
103
|
+
if (entry.pending) return !rev && !revShort;
|
|
104
|
+
const ids = [rev, revShort].filter(Boolean);
|
|
105
|
+
return ids.some((id) => entry.sha === id || entry.shortSha === id);
|
|
126
106
|
};
|
|
127
107
|
|
|
128
|
-
const FULL_INDENT = ' '.repeat(visibleWidth(` ${FILE_MARK} `));
|
|
129
|
-
|
|
130
108
|
const commitTone = (selected, current) => {
|
|
131
109
|
if (current) {
|
|
132
110
|
return {
|
|
@@ -153,119 +131,79 @@ const commitTone = (selected, current) => {
|
|
|
153
131
|
};
|
|
154
132
|
|
|
155
133
|
const paintCommitRow = (entry, width, color, selected, cols, current) => {
|
|
156
|
-
const
|
|
157
|
-
const mark = selected ? FILE_MARK : ' ';
|
|
158
|
-
const prefix = ` ${mark} `;
|
|
134
|
+
const prefix = markPrefix(selected);
|
|
159
135
|
const parts = padColumns(commitRowFields(entry), cols, COMMIT_COL_ALIGN);
|
|
160
136
|
const suffix = joinColumns(parts, cols);
|
|
161
|
-
const rest = Math.max(1,
|
|
162
|
-
const subject =
|
|
163
|
-
const
|
|
164
|
-
const after = `${' '.repeat(pad)}`;
|
|
165
|
-
const left = `${prefix}${subject}${after}`;
|
|
137
|
+
const rest = Math.max(1, contentWidth(width) - visibleWidth(prefix + suffix));
|
|
138
|
+
const subject = trimVisible(commitLine(entry), rest);
|
|
139
|
+
const after = ' '.repeat(Math.max(0, rest - visibleWidth(subject)));
|
|
166
140
|
const tail = ' '.repeat(COMMIT_TAIL);
|
|
141
|
+
if (!color) return `${prefix}${subject}${after}${suffix}${tail}`;
|
|
167
142
|
const tone = commitTone(selected, current);
|
|
168
|
-
const tones = current
|
|
169
|
-
? { ...COMMIT_COL_FG, ...COMMIT_CURRENT_COL_FG }
|
|
170
|
-
: COMMIT_COL_FG;
|
|
171
|
-
if (!color) return `${left}${suffix}${tail}`;
|
|
143
|
+
const tones = current ? COMMIT_CURRENT_COL_FG : COMMIT_COL_FG;
|
|
172
144
|
let out = `${seq(tone.fgRgb, tone.bgRgb)}${EL}`;
|
|
173
145
|
out += paint(prefix, tone.fgRgb, tone.bgRgb, color);
|
|
174
146
|
out += paint(subject, tone.nameFg, tone.bgRgb, color);
|
|
175
147
|
out += paint(after, tone.fgRgb, tone.bgRgb, color);
|
|
176
148
|
out += paintColumns(parts, cols, tone.fgRgb, tone.bgRgb, color, tones);
|
|
177
|
-
out
|
|
178
|
-
return out;
|
|
149
|
+
return out + paint(tail, tone.fgRgb, tone.bgRgb, color);
|
|
179
150
|
};
|
|
180
151
|
|
|
181
|
-
const paintCommitEdit = (compose, width, color, entry, cols) => {
|
|
152
|
+
const paintCommitEdit = (compose, width, color, entry, cols, index) => {
|
|
182
153
|
const text = splitMessage(compose.text).line;
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
const inner = contentWidth(width);
|
|
201
|
-
const prefix = ` ${FILE_MARK} `;
|
|
202
|
-
const prefixW = visibleWidth(prefix);
|
|
203
|
-
const rest = Math.max(1, inner - prefixW);
|
|
204
|
-
const clipped = truncateVisible(text, rest);
|
|
205
|
-
const pad = Math.max(0, rest - visibleWidth(clipped));
|
|
206
|
-
const gap = ' '.repeat(pad);
|
|
207
|
-
const tail = ' '.repeat(COMMIT_TAIL);
|
|
208
|
-
const fgRgb = THEME.chromeFg;
|
|
209
|
-
const bgRgb = THEME.buttonBg;
|
|
210
|
-
const nameFg = THEME.buttonHotFg;
|
|
211
|
-
let row = `${prefix}${clipped}${gap}${tail}`;
|
|
212
|
-
if (color) {
|
|
213
|
-
row = `${seq(fgRgb, bgRgb)}${EL}`;
|
|
214
|
-
row += paint(prefix, fgRgb, bgRgb, color);
|
|
215
|
-
row += paint(clipped, nameFg, bgRgb, color);
|
|
216
|
-
row += paint(gap, fgRgb, bgRgb, color);
|
|
217
|
-
row += paint(tail, fgRgb, bgRgb, color);
|
|
218
|
-
}
|
|
219
|
-
const col = Math.min(compose.cursor ?? 0, visibleWidth(clipped));
|
|
220
|
-
return { row, cursor: { x: prefixW + col + 1 }, at: 'start' };
|
|
154
|
+
const prefix = markPrefix(true);
|
|
155
|
+
const fields = commitRowFields(entry ?? {});
|
|
156
|
+
const suffix = joinColumns(padColumns(fields, cols, COMMIT_COL_ALIGN), cols);
|
|
157
|
+
const rest = Math.max(1, contentWidth(width) - visibleWidth(prefix + suffix));
|
|
158
|
+
const win = fieldWindow(text, compose.cursor, compose.scrollCol, rest);
|
|
159
|
+
const shown = { ...entry, body: win.text, subject: win.text };
|
|
160
|
+
const textX = MARK_W + 1;
|
|
161
|
+
const edit = editSpan(1, textX, textX + rest, 0, text);
|
|
162
|
+
return {
|
|
163
|
+
row: paintCommitRow(shown, width, color, true, cols),
|
|
164
|
+
cursor: { x: textX + win.col, scroll: win.scroll },
|
|
165
|
+
at: entry ? 'replace' : 'start',
|
|
166
|
+
index,
|
|
167
|
+
edits: [{ ...edit, scroll: win.scroll }],
|
|
168
|
+
};
|
|
221
169
|
};
|
|
222
170
|
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
171
|
+
const editTarget = (compose, commits, cursor) => {
|
|
172
|
+
if (compose?.kind !== 'commit') return null;
|
|
173
|
+
const kind = compose.commitKind;
|
|
174
|
+
if (kind === 'amend' || kind === 'reword') return cursor;
|
|
175
|
+
if (kind === 'commit' || kind === 'fixup') {
|
|
176
|
+
return commits.findIndex((entry) => entry.pending);
|
|
226
177
|
}
|
|
227
178
|
return -1;
|
|
228
179
|
};
|
|
229
180
|
|
|
230
|
-
const
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
const
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
const commitEditRow = (compose, commits, cursor, width, color, cols) => {
|
|
237
|
-
if (!compose || compose.kind !== 'commit') return null;
|
|
238
|
-
let at = -1;
|
|
239
|
-
if (editsCursor(compose)) at = cursor;
|
|
240
|
-
if (editsPending(compose)) at = pendingAt(commits);
|
|
241
|
-
if (at >= 0) {
|
|
242
|
-
const entry = commits[at];
|
|
243
|
-
if (!entry) return null;
|
|
244
|
-
const painted = paintCommitEdit(compose, width, color, entry, cols);
|
|
245
|
-
painted.index = at;
|
|
246
|
-
return painted;
|
|
247
|
-
}
|
|
248
|
-
return paintCommitEdit(compose, width, color);
|
|
181
|
+
const commitEditRow = (compose, commits, target, width, color, cols) => {
|
|
182
|
+
if (target === null) return null;
|
|
183
|
+
if (target < 0) return paintCommitEdit(compose, width, color, null, {}, -1);
|
|
184
|
+
const entry = commits[target];
|
|
185
|
+
if (!entry) return null;
|
|
186
|
+
return paintCommitEdit(compose, width, color, entry, cols, target);
|
|
249
187
|
};
|
|
250
188
|
|
|
251
|
-
const
|
|
252
|
-
const tone = commitTone(selected, current);
|
|
253
|
-
const inner = contentWidth(width);
|
|
189
|
+
const fitPieces = (pieces, width) => {
|
|
254
190
|
const shown = [];
|
|
255
191
|
let used = 0;
|
|
256
192
|
for (const piece of pieces) {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
const text = truncateVisible(piece.text, room);
|
|
193
|
+
if (used >= width) break;
|
|
194
|
+
const text = trimVisible(piece.text, width - used);
|
|
260
195
|
if (!text) continue;
|
|
261
196
|
shown.push({ text, fg: piece.fg });
|
|
262
197
|
used += visibleWidth(text);
|
|
263
198
|
}
|
|
264
|
-
|
|
199
|
+
return { shown, pad: ' '.repeat(Math.max(0, width - used)) };
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const paintPieces = (pieces, width, color, tone) => {
|
|
203
|
+
const { shown, pad } = fitPieces(pieces, contentWidth(width));
|
|
265
204
|
const tail = ' '.repeat(COMMIT_TAIL);
|
|
266
205
|
if (!color) {
|
|
267
|
-
|
|
268
|
-
for (const piece of shown) plain += piece.text;
|
|
206
|
+
const plain = shown.map((piece) => piece.text).join('');
|
|
269
207
|
return `${plain}${pad}${tail}`;
|
|
270
208
|
}
|
|
271
209
|
let out = `${seq(tone.fgRgb, tone.bgRgb)}${EL}`;
|
|
@@ -273,41 +211,25 @@ const paintPieces = (pieces, width, color, selected, current) => {
|
|
|
273
211
|
out += paint(piece.text, piece.fg, tone.bgRgb, color);
|
|
274
212
|
}
|
|
275
213
|
out += paint(pad, tone.fgRgb, tone.bgRgb, color);
|
|
276
|
-
out
|
|
277
|
-
return out;
|
|
214
|
+
return out + paint(tail, tone.fgRgb, tone.bgRgb, color);
|
|
278
215
|
};
|
|
279
216
|
|
|
280
|
-
const
|
|
281
|
-
|
|
217
|
+
const messageText = (entry) =>
|
|
218
|
+
`${entry.body ?? ''}`.trimEnd() || `${entry.subject ?? ''}`.trimEnd();
|
|
282
219
|
|
|
283
|
-
const
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
const
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
for (const row of rows) lines.push({ text: row, kind });
|
|
293
|
-
return lines;
|
|
294
|
-
};
|
|
295
|
-
|
|
296
|
-
const messagePartsFrom = (text, width) => {
|
|
297
|
-
const raw = `${text ?? ''}`;
|
|
298
|
-
if (!raw) return [{ text: '', kind: 'text' }];
|
|
299
|
-
const split = raw.split('\n');
|
|
300
|
-
const lines = wrapKind(split[0], width, 'text');
|
|
301
|
-
for (let i = 1; i < split.length; i++) {
|
|
302
|
-
const rest = wrapKind(split[i], width, 'body');
|
|
303
|
-
for (const line of rest) lines.push(line);
|
|
220
|
+
const messageParts = (text, width) => {
|
|
221
|
+
if (!text) return [{ text: '', kind: 'text' }];
|
|
222
|
+
const parts = [];
|
|
223
|
+
const lines = text.split('\n');
|
|
224
|
+
for (let i = 0; i < lines.length; i++) {
|
|
225
|
+
const kind = i ? 'body' : 'text';
|
|
226
|
+
for (const row of wrapMultiline(lines[i], Math.max(1, width))) {
|
|
227
|
+
parts.push({ text: row, kind });
|
|
228
|
+
}
|
|
304
229
|
}
|
|
305
|
-
return
|
|
230
|
+
return parts;
|
|
306
231
|
};
|
|
307
232
|
|
|
308
|
-
const messageParts = (entry, width) =>
|
|
309
|
-
messagePartsFrom(messageText(entry), width);
|
|
310
|
-
|
|
311
233
|
const authorParts = (entry) => {
|
|
312
234
|
const name = `${entry.author ?? ''}`.trim();
|
|
313
235
|
const email = `${entry.email ?? ''}`.trim();
|
|
@@ -322,24 +244,23 @@ const authorParts = (entry) => {
|
|
|
322
244
|
return [];
|
|
323
245
|
};
|
|
324
246
|
|
|
325
|
-
const partsWidth = (parts) =>
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
}
|
|
247
|
+
const partsWidth = (parts) =>
|
|
248
|
+
parts.reduce((width, part) => width + visibleWidth(part.text), 0);
|
|
249
|
+
|
|
250
|
+
const timeFields = (entry) => ({
|
|
251
|
+
when: `${entry.when ?? ''}`.trim(),
|
|
252
|
+
ago: shortAge(entry.date),
|
|
253
|
+
});
|
|
330
254
|
|
|
331
255
|
const timeNeed = (entry) => {
|
|
332
|
-
const when
|
|
333
|
-
const ago = shortAge(entry.date ?? '');
|
|
256
|
+
const { when, ago } = timeFields(entry);
|
|
334
257
|
if (when && ago) return visibleWidth(when) + COL_GAP + visibleWidth(ago);
|
|
335
258
|
return visibleWidth(when || ago);
|
|
336
259
|
};
|
|
337
260
|
|
|
338
|
-
const refsText = (entry) => `${entry.refs ?? ''}`.trim();
|
|
339
|
-
|
|
340
261
|
const diffLine = (entry, widths) => {
|
|
341
262
|
const label = countLabel(entry);
|
|
342
|
-
if (!label) return null;
|
|
263
|
+
if (!label.add) return null;
|
|
343
264
|
const add = padVisible(label.add, widths.add, 'start');
|
|
344
265
|
const del = padVisible(label.del, widths.del, 'start');
|
|
345
266
|
const text = `${DIFF_LABEL}${DIFF_GAP}${add}${DIFF_GAP}${del}`;
|
|
@@ -360,7 +281,7 @@ const diffCountParts = (entry, widths, rightW) => {
|
|
|
360
281
|
];
|
|
361
282
|
};
|
|
362
283
|
|
|
363
|
-
const rightNeed = (entry, widths
|
|
284
|
+
const rightNeed = (entry, widths) => {
|
|
364
285
|
const line = diffLine(entry, widths);
|
|
365
286
|
return Math.max(
|
|
366
287
|
partsWidth(authorParts(entry)),
|
|
@@ -373,11 +294,11 @@ const rightNeed = (entry, widths = entryCountWidth(entry)) => {
|
|
|
373
294
|
const spreadTime = (when, ago, width) => {
|
|
374
295
|
const agoW = visibleWidth(ago);
|
|
375
296
|
if (agoW >= width) {
|
|
376
|
-
return [{ text:
|
|
297
|
+
return [{ text: trimVisible(ago, width), kind: 'meta' }];
|
|
377
298
|
}
|
|
378
299
|
const room = width - agoW;
|
|
379
300
|
const minGap = Math.min(COL_GAP, room);
|
|
380
|
-
const left =
|
|
301
|
+
const left = trimVisible(when, room - minGap);
|
|
381
302
|
const gap = width - visibleWidth(left) - agoW;
|
|
382
303
|
return [
|
|
383
304
|
{ text: left, kind: 'meta' },
|
|
@@ -387,7 +308,7 @@ const spreadTime = (when, ago, width) => {
|
|
|
387
308
|
};
|
|
388
309
|
|
|
389
310
|
const alignEnd = (text, width, kind) => {
|
|
390
|
-
const shown =
|
|
311
|
+
const shown = trimVisible(text, width);
|
|
391
312
|
const pad = Math.max(0, width - visibleWidth(shown));
|
|
392
313
|
return [
|
|
393
314
|
{ text: ' '.repeat(pad), kind },
|
|
@@ -396,12 +317,11 @@ const alignEnd = (text, width, kind) => {
|
|
|
396
317
|
};
|
|
397
318
|
|
|
398
319
|
const timeParts = (entry, width) => {
|
|
399
|
-
const when = `${entry.when ?? ''}`.trim();
|
|
400
|
-
const ago = shortAge(entry.date ?? '');
|
|
401
320
|
if (!width) return [];
|
|
321
|
+
const { when, ago } = timeFields(entry);
|
|
402
322
|
if (when && ago) return spreadTime(when, ago, width);
|
|
403
323
|
if (ago) return alignEnd(ago, width, 'meta');
|
|
404
|
-
if (when) return [{ text:
|
|
324
|
+
if (when) return [{ text: trimVisible(when, width), kind: 'meta' }];
|
|
405
325
|
return [];
|
|
406
326
|
};
|
|
407
327
|
|
|
@@ -419,23 +339,17 @@ const rightRows = (entry, rightW, widths) => {
|
|
|
419
339
|
};
|
|
420
340
|
|
|
421
341
|
const panelWidths = (need, leftNeed, inner) => {
|
|
422
|
-
const
|
|
423
|
-
|
|
424
|
-
const room = Math.max(1, inner - indent);
|
|
425
|
-
if (!rightW || room <= MIN_LEFT) {
|
|
426
|
-
return { rightW: 0, leftW: room, gapW: 0 };
|
|
427
|
-
}
|
|
342
|
+
const room = Math.max(1, inner - MARK_W);
|
|
343
|
+
if (!need || room <= MIN_LEFT) return { rightW: 0, leftW: room, gapW: 0 };
|
|
428
344
|
const reserve = Math.max(MIN_LEFT, leftNeed);
|
|
429
345
|
const minLeft = Math.min(reserve, room - COL_GAP - 1);
|
|
430
346
|
const maxRight = room - COL_GAP - minLeft;
|
|
431
|
-
|
|
347
|
+
const rightW = need > maxRight ? Math.max(1, maxRight) : need;
|
|
432
348
|
return { rightW, leftW: room - COL_GAP - rightW, gapW: COL_GAP };
|
|
433
349
|
};
|
|
434
350
|
|
|
435
351
|
const panelLeft = (entry, leftW, edit) => {
|
|
436
|
-
const parts = edit
|
|
437
|
-
? messagePartsFrom(edit.text ?? '', leftW)
|
|
438
|
-
: messageParts(entry, leftW);
|
|
352
|
+
const parts = messageParts(edit ? edit.text : messageText(entry), leftW);
|
|
439
353
|
if (!entry.sha) return parts;
|
|
440
354
|
return [{ text: entry.sha, kind: 'hash' }, ...parts];
|
|
441
355
|
};
|
|
@@ -443,31 +357,18 @@ const panelLeft = (entry, leftW, edit) => {
|
|
|
443
357
|
const commitMessageWidth = (entry, screenWidth) => {
|
|
444
358
|
const width = Math.max(20, screenWidth || 80);
|
|
445
359
|
const inner = contentWidth(width);
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
const
|
|
449
|
-
const cols = panelWidths(rightNeed(entry), hashW, inner);
|
|
360
|
+
if (!entry) return Math.max(1, inner - MARK_W);
|
|
361
|
+
const need = rightNeed(entry, countWidths([entry]));
|
|
362
|
+
const cols = panelWidths(need, visibleWidth(entry.sha ?? ''), inner);
|
|
450
363
|
return Math.max(1, cols.leftW);
|
|
451
364
|
};
|
|
452
365
|
|
|
453
|
-
const prefixWidth = (first, selected) => {
|
|
454
|
-
const mark = first && selected ? FILE_MARK : ' ';
|
|
455
|
-
const prefix = first ? ` ${mark} ` : FULL_INDENT;
|
|
456
|
-
return visibleWidth(prefix);
|
|
457
|
-
};
|
|
458
|
-
|
|
459
|
-
const messageCaret = (text, cursor, width, row, first, selected) => {
|
|
460
|
-
const pos = cursorInWrap(`${text ?? ''}`, cursor ?? 0, width);
|
|
461
|
-
if (pos.row !== row) return null;
|
|
462
|
-
return { x: prefixWidth(first, selected) + pos.col + 1 };
|
|
463
|
-
};
|
|
464
|
-
|
|
465
366
|
const pieceFg = (kind, tone) => {
|
|
466
367
|
if (kind === 'add') return THEME.addLineFg;
|
|
467
368
|
if (kind === 'del') return THEME.delLineFg;
|
|
468
369
|
if (tone.current) {
|
|
469
370
|
if (kind === 'hash') return THEME.shaDarkFg;
|
|
470
|
-
if (kind === 'refs') return THEME.
|
|
371
|
+
if (kind === 'refs') return THEME.shaDarkFg;
|
|
471
372
|
if (kind === 'text' || kind === 'body') return THEME.mutedFg;
|
|
472
373
|
return tone.fgRgb;
|
|
473
374
|
}
|
|
@@ -480,324 +381,110 @@ const pieceFg = (kind, tone) => {
|
|
|
480
381
|
return tone.fgRgb;
|
|
481
382
|
};
|
|
482
383
|
|
|
483
|
-
const clipParts = (parts, width,
|
|
484
|
-
const
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
if (!text) continue;
|
|
491
|
-
const kind = part.kind ?? fallbackKind;
|
|
492
|
-
shown.push({ text, fg: pieceFg(kind, tone) });
|
|
493
|
-
used += visibleWidth(text);
|
|
494
|
-
}
|
|
495
|
-
const pad = Math.max(0, width - used);
|
|
496
|
-
if (pad) shown.push({ text: ' '.repeat(pad), fg: tone.fgRgb });
|
|
384
|
+
const clipParts = (parts, width, tone) => {
|
|
385
|
+
const pieces = parts.map((part) => ({
|
|
386
|
+
text: part.text,
|
|
387
|
+
fg: pieceFg(part.kind, tone),
|
|
388
|
+
}));
|
|
389
|
+
const { shown, pad } = fitPieces(pieces, width);
|
|
390
|
+
if (pad) shown.push({ text: pad, fg: tone.fgRgb });
|
|
497
391
|
return shown;
|
|
498
392
|
};
|
|
499
393
|
|
|
500
|
-
const paintPanelLine = (spec) => {
|
|
394
|
+
const paintPanelLine = (left, right, cols, first, spec) => {
|
|
501
395
|
const tone = commitTone(spec.selected, spec.current);
|
|
502
|
-
const
|
|
503
|
-
const
|
|
504
|
-
const
|
|
505
|
-
const
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
{ text: prefix, fg: tone.fgRgb },
|
|
513
|
-
{ text: left, fg: pieceFg(spec.leftKind, tone) },
|
|
514
|
-
{ text: `${' '.repeat(leftPad)}${gap}`, fg: tone.fgRgb },
|
|
515
|
-
...clipParts(right, spec.rightW, spec.rightKind, tone),
|
|
516
|
-
],
|
|
517
|
-
spec.width,
|
|
518
|
-
spec.color,
|
|
519
|
-
spec.selected,
|
|
520
|
-
spec.current,
|
|
521
|
-
);
|
|
396
|
+
const prefix = first ? markPrefix(spec.selected) : FULL_INDENT;
|
|
397
|
+
const text = trimVisible(left.text, cols.leftW);
|
|
398
|
+
const gapW = Math.max(0, cols.leftW - visibleWidth(text)) + cols.gapW;
|
|
399
|
+
const pieces = [
|
|
400
|
+
{ text: prefix, fg: tone.fgRgb },
|
|
401
|
+
{ text, fg: pieceFg(left.kind, tone) },
|
|
402
|
+
{ text: ' '.repeat(gapW), fg: tone.fgRgb },
|
|
403
|
+
...clipParts(right, cols.rightW, tone),
|
|
404
|
+
];
|
|
405
|
+
return paintPieces(pieces, spec.width, spec.color, tone);
|
|
522
406
|
};
|
|
523
407
|
|
|
524
|
-
const
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
hit,
|
|
528
|
-
cursor,
|
|
529
|
-
});
|
|
530
|
-
|
|
531
|
-
const commitLines = (
|
|
532
|
-
entry,
|
|
533
|
-
index,
|
|
534
|
-
width,
|
|
535
|
-
color,
|
|
536
|
-
selected,
|
|
537
|
-
edit,
|
|
538
|
-
current,
|
|
539
|
-
diffWidths,
|
|
540
|
-
) => {
|
|
541
|
-
const inner = contentWidth(width);
|
|
408
|
+
const commitLines = (entry, index, spec) => {
|
|
409
|
+
const { width, edit, diffWidths } = spec;
|
|
410
|
+
const need = rightNeed(entry, diffWidths);
|
|
542
411
|
const hashW = visibleWidth(entry.sha ?? '');
|
|
543
|
-
const
|
|
544
|
-
const
|
|
545
|
-
const rights = rightRows(entry, cols.rightW, widths);
|
|
412
|
+
const cols = panelWidths(need, hashW, contentWidth(width));
|
|
413
|
+
const rights = rightRows(entry, cols.rightW, diffWidths);
|
|
546
414
|
const left = panelLeft(entry, cols.leftW, edit);
|
|
415
|
+
const doc = edit ? wrapDoc(edit.text, cols.leftW) : [];
|
|
416
|
+
const caret = edit ? cursorInWrap(edit.text, edit.cursor, cols.leftW) : null;
|
|
417
|
+
const skip = entry.sha ? 1 : 0;
|
|
418
|
+
const textX = MARK_W + 1;
|
|
419
|
+
const x1 = textX + cols.leftW;
|
|
547
420
|
const count = Math.max(left.length, rights.length);
|
|
548
421
|
const lines = [];
|
|
549
422
|
for (let row = 0; row < count; row++) {
|
|
550
423
|
const line = left[row] ?? { text: '', kind: 'text' };
|
|
551
|
-
const
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
first: row === 0,
|
|
562
|
-
leftKind: line.kind,
|
|
563
|
-
rightKind: 'meta',
|
|
564
|
-
});
|
|
565
|
-
const messageRow = entry.sha ? row - 1 : row;
|
|
566
|
-
const caret = edit
|
|
567
|
-
? messageCaret(
|
|
568
|
-
edit.text,
|
|
569
|
-
edit.cursor,
|
|
570
|
-
cols.leftW,
|
|
571
|
-
messageRow,
|
|
572
|
-
!entry.sha && row === 0,
|
|
573
|
-
selected,
|
|
574
|
-
)
|
|
575
|
-
: null;
|
|
576
|
-
lines.push(lineRecord(index, painted, true, caret));
|
|
577
|
-
}
|
|
578
|
-
return lines;
|
|
579
|
-
};
|
|
580
|
-
|
|
581
|
-
const draftLines = (text, cursor, width, color) => {
|
|
582
|
-
const inner = contentWidth(width);
|
|
583
|
-
const leftW = Math.max(1, inner - visibleWidth(FULL_INDENT));
|
|
584
|
-
const parts = messagePartsFrom(text, leftW);
|
|
585
|
-
const lines = [];
|
|
586
|
-
for (let row = 0; row < parts.length; row++) {
|
|
587
|
-
const line = parts[row];
|
|
588
|
-
const painted = paintPanelLine({
|
|
589
|
-
left: line.text,
|
|
590
|
-
right: '',
|
|
591
|
-
leftW,
|
|
592
|
-
rightW: 0,
|
|
593
|
-
gapW: 0,
|
|
594
|
-
width,
|
|
595
|
-
color,
|
|
596
|
-
selected: true,
|
|
597
|
-
first: row === 0,
|
|
598
|
-
leftKind: line.kind,
|
|
599
|
-
rightKind: 'meta',
|
|
600
|
-
});
|
|
601
|
-
const caret = messageCaret(text, cursor, leftW, row, row === 0, true);
|
|
602
|
-
lines.push(lineRecord(-1, painted, false, caret));
|
|
424
|
+
const right = rights[row] ?? [];
|
|
425
|
+
const painted = paintPanelLine(line, right, cols, row === 0, spec);
|
|
426
|
+
const messageRow = row - skip;
|
|
427
|
+
const atCaret = caret && caret.row === messageRow;
|
|
428
|
+
const cursor = atCaret ? { x: textX + caret.col } : null;
|
|
429
|
+
const piece = doc[messageRow];
|
|
430
|
+
const edits = piece
|
|
431
|
+
? [editSpan(1, textX, x1, piece.start, piece.text)]
|
|
432
|
+
: [];
|
|
433
|
+
lines.push(listLine(painted, index, cursor, edits));
|
|
603
434
|
}
|
|
604
435
|
return lines;
|
|
605
436
|
};
|
|
606
437
|
|
|
607
|
-
const
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
const
|
|
612
|
-
return at >= 0 && index === at;
|
|
613
|
-
};
|
|
614
|
-
|
|
615
|
-
const composeShowsDraft = (compose, commits) => {
|
|
616
|
-
if (!compose || compose.kind !== 'commit') return false;
|
|
617
|
-
if (editsCursor(compose)) return false;
|
|
618
|
-
if (editsPending(compose)) return pendingAt(commits) < 0;
|
|
619
|
-
return true;
|
|
620
|
-
};
|
|
621
|
-
|
|
622
|
-
const gapLine = (width, color) =>
|
|
623
|
-
lineRecord(-1, paintBodyFill(width, color, 'files'), false);
|
|
624
|
-
|
|
625
|
-
const flattenCommits = (commits, cursor, width, color, compose, rev, short) => {
|
|
438
|
+
const flattenCommits = (view, commits, target, width, color) => {
|
|
439
|
+
const cursor = view.commitCursor ?? 0;
|
|
440
|
+
const { compose } = view;
|
|
441
|
+
const edit = { text: compose?.text ?? '', cursor: compose?.cursor ?? 0 };
|
|
442
|
+
const spec = { width, color, diffWidths: countWidths(commits) };
|
|
626
443
|
const lines = [];
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
const pushGap = () => {
|
|
630
|
-
if (lines.length) lines.push(gapLine(width, color));
|
|
631
|
-
};
|
|
632
|
-
if (composeShowsDraft(compose, commits)) {
|
|
633
|
-
const draft = draftLines(
|
|
634
|
-
compose.text ?? '',
|
|
635
|
-
compose.cursor ?? 0,
|
|
636
|
-
width,
|
|
637
|
-
color,
|
|
638
|
-
);
|
|
639
|
-
for (const line of draft) lines.push(line);
|
|
444
|
+
if (target === -1) {
|
|
445
|
+
lines.push(...commitLines({}, -1, { ...spec, selected: true, edit }));
|
|
640
446
|
}
|
|
447
|
+
const gap = listLine(paintBodyFill(width, color, 'files'), -1);
|
|
641
448
|
for (let index = 0; index < commits.length; index++) {
|
|
642
|
-
|
|
643
|
-
const
|
|
644
|
-
const
|
|
645
|
-
const
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
const
|
|
649
|
-
|
|
650
|
-
index,
|
|
651
|
-
width,
|
|
652
|
-
color,
|
|
653
|
-
selected,
|
|
654
|
-
edit,
|
|
655
|
-
viewedCommit(commits[index], rev, short),
|
|
656
|
-
diffWidths,
|
|
657
|
-
);
|
|
658
|
-
for (const line of block) lines.push(line);
|
|
449
|
+
if (lines.length) lines.push(gap);
|
|
450
|
+
const entry = commits[index];
|
|
451
|
+
const inplace = index === target;
|
|
452
|
+
const selected = inplace || (target === null && index === cursor);
|
|
453
|
+
const current = viewedCommit(entry, view.rev, view.revShort);
|
|
454
|
+
const entryEdit = inplace ? edit : null;
|
|
455
|
+
const entrySpec = { ...spec, selected, current, edit: entryEdit };
|
|
456
|
+
lines.push(...commitLines(entry, index, entrySpec));
|
|
659
457
|
}
|
|
660
458
|
return lines;
|
|
661
459
|
};
|
|
662
460
|
|
|
663
|
-
const focusLine = (lines, cursor,
|
|
664
|
-
if (
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
for (let i = 0; i < lines.length; i++) {
|
|
670
|
-
const line = lines[i];
|
|
671
|
-
if (line.hit && line.commit === cursor) return i;
|
|
461
|
+
const focusLine = (lines, cursor, editing) => {
|
|
462
|
+
if (editing) {
|
|
463
|
+
const at = lines.findIndex((line) => line.cursor);
|
|
464
|
+
if (at >= 0) return at;
|
|
672
465
|
}
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
const paintLineWindow = (
|
|
677
|
-
lines,
|
|
678
|
-
focus,
|
|
679
|
-
width,
|
|
680
|
-
color,
|
|
681
|
-
bodyH,
|
|
682
|
-
headerLines,
|
|
683
|
-
offset,
|
|
684
|
-
) => {
|
|
685
|
-
const pad = bodyH >= LIST_PAD * 2 + 1 ? LIST_PAD : 0;
|
|
686
|
-
const listH = bodyH - pad * 2;
|
|
687
|
-
const start = listWindowStart(focus, offset, listH, lines.length);
|
|
688
|
-
const blank = paintBodyFill(width, color, 'files');
|
|
689
|
-
const body = [];
|
|
690
|
-
const fileHits = [];
|
|
691
|
-
let textCursor = null;
|
|
692
|
-
if (pad) body.push(blank);
|
|
693
|
-
for (let i = 0; i < listH; i++) {
|
|
694
|
-
const line = lines[start + i];
|
|
695
|
-
if (!line) break;
|
|
696
|
-
body.push(line.row);
|
|
697
|
-
if (line.cursor) {
|
|
698
|
-
textCursor = { x: line.cursor.x, row: body.length - 1 };
|
|
699
|
-
}
|
|
700
|
-
if (!line.hit) continue;
|
|
701
|
-
const y = headerLines + pad + i + 1;
|
|
702
|
-
fileHits.push({ y, cursor: line.commit });
|
|
703
|
-
}
|
|
704
|
-
if (pad) body.push(blank);
|
|
705
|
-
return paneResult({
|
|
706
|
-
body,
|
|
707
|
-
fileHits,
|
|
708
|
-
cursor: textCursor,
|
|
709
|
-
listScroll: start,
|
|
710
|
-
});
|
|
466
|
+
const at = lines.findIndex((line) => line.hit && line.index === cursor);
|
|
467
|
+
return Math.max(0, at);
|
|
711
468
|
};
|
|
712
469
|
|
|
713
|
-
const
|
|
470
|
+
const paintBodyCommits = (view, width, color, bodyH, headerLines) => {
|
|
471
|
+
const pane = { width, color, bodyH, headerLines, offset: view.listScroll };
|
|
714
472
|
const commits = view.commits ?? [];
|
|
715
473
|
const cursor = view.commitCursor ?? 0;
|
|
716
|
-
const compose = view
|
|
717
|
-
const
|
|
718
|
-
commits,
|
|
719
|
-
cursor,
|
|
720
|
-
width,
|
|
721
|
-
color,
|
|
722
|
-
compose,
|
|
723
|
-
view.rev,
|
|
724
|
-
view.revShort,
|
|
725
|
-
);
|
|
726
|
-
const focus = focusLine(lines, cursor, compose);
|
|
727
|
-
return paintLineWindow(
|
|
728
|
-
lines,
|
|
729
|
-
focus,
|
|
730
|
-
width,
|
|
731
|
-
color,
|
|
732
|
-
bodyH,
|
|
733
|
-
headerLines,
|
|
734
|
-
view.listScroll,
|
|
735
|
-
);
|
|
736
|
-
};
|
|
737
|
-
|
|
738
|
-
const paintBriefCommits = (
|
|
739
|
-
commits,
|
|
740
|
-
cursor,
|
|
741
|
-
width,
|
|
742
|
-
color,
|
|
743
|
-
bodyH,
|
|
744
|
-
headerLines,
|
|
745
|
-
extra,
|
|
746
|
-
offset,
|
|
747
|
-
cols,
|
|
748
|
-
rev,
|
|
749
|
-
revShort,
|
|
750
|
-
) => {
|
|
751
|
-
const paintRow = (entry, rowWidth, rowColor, selected) =>
|
|
752
|
-
paintCommitRow(
|
|
753
|
-
entry,
|
|
754
|
-
rowWidth,
|
|
755
|
-
rowColor,
|
|
756
|
-
selected,
|
|
757
|
-
cols,
|
|
758
|
-
viewedCommit(entry, rev, revShort),
|
|
759
|
-
);
|
|
760
|
-
return paintCursorList(
|
|
761
|
-
commits,
|
|
762
|
-
cursor,
|
|
763
|
-
width,
|
|
764
|
-
color,
|
|
765
|
-
bodyH,
|
|
766
|
-
headerLines,
|
|
767
|
-
paintRow,
|
|
768
|
-
extra,
|
|
769
|
-
offset,
|
|
770
|
-
);
|
|
771
|
-
};
|
|
772
|
-
|
|
773
|
-
const paintBodyCommits = (view, width, color, bodyH, headerLines) => {
|
|
474
|
+
const { compose } = view;
|
|
475
|
+
const target = editTarget(compose, commits, cursor);
|
|
774
476
|
if (view.commitView === 'full') {
|
|
775
|
-
|
|
477
|
+
const lines = flattenCommits(view, commits, target, width, color);
|
|
478
|
+
const focus = focusLine(lines, cursor, target !== null);
|
|
479
|
+
return paintListWindow(lines.length, focus, pane, (i) => lines[i]);
|
|
776
480
|
}
|
|
777
|
-
const commits = view.commits ?? [];
|
|
778
481
|
const cols = measureColumns(commits, commitRowFields, COMMIT_COL_ALIGN);
|
|
779
|
-
const
|
|
780
|
-
const
|
|
781
|
-
view.
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
color,
|
|
786
|
-
cols,
|
|
787
|
-
);
|
|
788
|
-
return paintBriefCommits(
|
|
789
|
-
commits,
|
|
790
|
-
cursor,
|
|
791
|
-
width,
|
|
792
|
-
color,
|
|
793
|
-
bodyH,
|
|
794
|
-
headerLines,
|
|
795
|
-
extra,
|
|
796
|
-
view.listScroll,
|
|
797
|
-
cols,
|
|
798
|
-
view.rev,
|
|
799
|
-
view.revShort,
|
|
800
|
-
);
|
|
482
|
+
const edit = commitEditRow(compose, commits, target, width, color, cols);
|
|
483
|
+
const paintRow = (entry, selected) => {
|
|
484
|
+
const current = viewedCommit(entry, view.rev, view.revShort);
|
|
485
|
+
return paintCommitRow(entry, width, color, selected, cols, current);
|
|
486
|
+
};
|
|
487
|
+
return paintCursorList(commits, cursor, pane, paintRow, edit);
|
|
801
488
|
};
|
|
802
489
|
|
|
803
490
|
module.exports = {
|