@xuhaojun/githunk 0.1.0 → 0.1.1
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/dist/githunk.js +1287 -311
- package/package.json +3 -3
package/dist/githunk.js
CHANGED
|
@@ -4408,6 +4408,13 @@ function syncVerticalScrollbar(bar, text, viewportHeight) {
|
|
|
4408
4408
|
bar.viewportSize = scrollbarViewportOverrides.get(bar) ?? Math.max(0, Math.floor(text.height));
|
|
4409
4409
|
bar.scrollPosition = text.scrollY;
|
|
4410
4410
|
}
|
|
4411
|
+
function clearScrollbarViewportOverride(text) {
|
|
4412
|
+
const bar = scrollbars.get(text);
|
|
4413
|
+
if (bar === undefined)
|
|
4414
|
+
return;
|
|
4415
|
+
scrollbarViewportOverrides.delete(bar);
|
|
4416
|
+
syncVerticalScrollbar(bar, text);
|
|
4417
|
+
}
|
|
4411
4418
|
function createPane(renderer, id, title, content, selectable = false, options = {}) {
|
|
4412
4419
|
const tabsConfig = options.tabs;
|
|
4413
4420
|
const BoxClass = tabsConfig === undefined ? BoxRenderable2 : PaneTabsBoxRenderable;
|
|
@@ -4892,36 +4899,62 @@ function computeColumnLayout(rows, width) {
|
|
|
4892
4899
|
const widths = indexes.map((j) => j === flexIndex ? flexWidth : rawWidths[j]);
|
|
4893
4900
|
return { indexes, widths };
|
|
4894
4901
|
}
|
|
4895
|
-
function
|
|
4896
|
-
const
|
|
4902
|
+
function layoutListRowSegments(row, layout) {
|
|
4903
|
+
const segments = [];
|
|
4897
4904
|
for (let i = 0;i < layout.indexes.length; i++) {
|
|
4898
4905
|
const column = row.columns[layout.indexes[i]];
|
|
4899
4906
|
const cellWidth = layout.widths[i];
|
|
4900
4907
|
const isLast = i === layout.indexes.length - 1;
|
|
4901
4908
|
if (i > 0)
|
|
4902
|
-
|
|
4909
|
+
segments.push({ text: " " });
|
|
4903
4910
|
const text = column?.text ?? "";
|
|
4904
4911
|
const truncated = truncateToWidth(text, cellWidth);
|
|
4905
4912
|
if (truncated.length > 0) {
|
|
4906
|
-
if (column?.segments !== undefined
|
|
4913
|
+
if (column?.segments !== undefined) {
|
|
4914
|
+
let remaining = [...truncated].length;
|
|
4907
4915
|
for (const segment of column.segments) {
|
|
4916
|
+
if (remaining <= 0)
|
|
4917
|
+
break;
|
|
4908
4918
|
if (segment.text.length === 0)
|
|
4909
4919
|
continue;
|
|
4910
|
-
|
|
4920
|
+
const chars = [...segment.text];
|
|
4921
|
+
if (chars.length <= remaining) {
|
|
4922
|
+
segments.push({
|
|
4923
|
+
text: segment.text,
|
|
4924
|
+
...column.style === undefined ? {} : { style: column.style },
|
|
4925
|
+
...segment.color === undefined ? {} : { color: segment.color }
|
|
4926
|
+
});
|
|
4927
|
+
remaining -= chars.length;
|
|
4928
|
+
} else {
|
|
4929
|
+
segments.push({
|
|
4930
|
+
text: chars.slice(0, remaining).join(""),
|
|
4931
|
+
...column.style === undefined ? {} : { style: column.style },
|
|
4932
|
+
...segment.color === undefined ? {} : { color: segment.color }
|
|
4933
|
+
});
|
|
4934
|
+
remaining = 0;
|
|
4935
|
+
break;
|
|
4936
|
+
}
|
|
4911
4937
|
}
|
|
4912
4938
|
} else {
|
|
4913
|
-
|
|
4939
|
+
segments.push({
|
|
4940
|
+
text: truncated,
|
|
4941
|
+
...column?.style === undefined ? {} : { style: column.style },
|
|
4942
|
+
...column?.color === undefined ? {} : { color: column.color }
|
|
4943
|
+
});
|
|
4914
4944
|
}
|
|
4915
4945
|
}
|
|
4916
4946
|
if (!isLast) {
|
|
4917
4947
|
const pad = cellWidth - visualLength(truncated);
|
|
4918
4948
|
if (pad > 0)
|
|
4919
|
-
|
|
4949
|
+
segments.push({ text: " ".repeat(pad) });
|
|
4920
4950
|
}
|
|
4921
4951
|
}
|
|
4922
|
-
while (
|
|
4923
|
-
|
|
4924
|
-
return
|
|
4952
|
+
while (segments.length > 0 && segments[segments.length - 1].text.trim().length === 0)
|
|
4953
|
+
segments.pop();
|
|
4954
|
+
return segments;
|
|
4955
|
+
}
|
|
4956
|
+
function renderColumns(row, layout) {
|
|
4957
|
+
return layoutListRowSegments(row, layout).map((segment) => styleToChunk(segment.text, segment.style, segment.color));
|
|
4925
4958
|
}
|
|
4926
4959
|
function highlightChunk(chunk, selectedBg) {
|
|
4927
4960
|
const current = chunk.fg;
|
|
@@ -5017,6 +5050,393 @@ function renderListRows(state, focused, width, hoveredId) {
|
|
|
5017
5050
|
return new StyledText2(allChunks);
|
|
5018
5051
|
}
|
|
5019
5052
|
|
|
5053
|
+
// src/ui/panes/list-text.ts
|
|
5054
|
+
import { parseColor } from "@opentui/core";
|
|
5055
|
+
|
|
5056
|
+
// src/domain/diff/cell-width.ts
|
|
5057
|
+
var WIDE_RANGES = [
|
|
5058
|
+
[4352, 4447],
|
|
5059
|
+
[11904, 42191],
|
|
5060
|
+
[44032, 55203],
|
|
5061
|
+
[63744, 64255],
|
|
5062
|
+
[65072, 65135],
|
|
5063
|
+
[65280, 65376],
|
|
5064
|
+
[65504, 65510],
|
|
5065
|
+
[127744, 129535],
|
|
5066
|
+
[129648, 129791],
|
|
5067
|
+
[131072, 262141]
|
|
5068
|
+
];
|
|
5069
|
+
function isWide(grapheme) {
|
|
5070
|
+
const code = grapheme.codePointAt(0);
|
|
5071
|
+
if (code === undefined)
|
|
5072
|
+
return false;
|
|
5073
|
+
for (const [low, high] of WIDE_RANGES) {
|
|
5074
|
+
if (code >= low && code <= high)
|
|
5075
|
+
return true;
|
|
5076
|
+
}
|
|
5077
|
+
return false;
|
|
5078
|
+
}
|
|
5079
|
+
function cellWidth(value) {
|
|
5080
|
+
let ascii = true;
|
|
5081
|
+
for (let index = 0;index < value.length; index++) {
|
|
5082
|
+
if (value.charCodeAt(index) > 127) {
|
|
5083
|
+
ascii = false;
|
|
5084
|
+
break;
|
|
5085
|
+
}
|
|
5086
|
+
}
|
|
5087
|
+
if (ascii)
|
|
5088
|
+
return value.length;
|
|
5089
|
+
let width = 0;
|
|
5090
|
+
for (const codePoint of value)
|
|
5091
|
+
width += isWide(codePoint) ? 2 : 1;
|
|
5092
|
+
return width;
|
|
5093
|
+
}
|
|
5094
|
+
|
|
5095
|
+
// src/ui/panes/pane-text.ts
|
|
5096
|
+
function internalsOf(text) {
|
|
5097
|
+
const candidate = text;
|
|
5098
|
+
const buffer = candidate.textBuffer;
|
|
5099
|
+
const style = candidate._textBufferSyntaxStyle;
|
|
5100
|
+
if (buffer === undefined || style === undefined)
|
|
5101
|
+
return;
|
|
5102
|
+
if (typeof buffer.setText !== "function" || typeof buffer.addHighlight !== "function" || typeof buffer.clearAllHighlights !== "function")
|
|
5103
|
+
return;
|
|
5104
|
+
if (typeof buffer.clearLineHighlights !== "function")
|
|
5105
|
+
return;
|
|
5106
|
+
if (typeof style.registerStyle !== "function" || typeof candidate.updateTextInfo !== "function")
|
|
5107
|
+
return;
|
|
5108
|
+
return candidate;
|
|
5109
|
+
}
|
|
5110
|
+
function paneTextBuffer(text) {
|
|
5111
|
+
const internals = internalsOf(text);
|
|
5112
|
+
if (internals === undefined)
|
|
5113
|
+
return;
|
|
5114
|
+
internals._hasManualStyledText = true;
|
|
5115
|
+
return {
|
|
5116
|
+
setText(value) {
|
|
5117
|
+
internals.textBuffer.setText(value);
|
|
5118
|
+
internals.updateTextInfo();
|
|
5119
|
+
},
|
|
5120
|
+
addHighlight(row, highlight) {
|
|
5121
|
+
internals.textBuffer.addHighlight(row, highlight);
|
|
5122
|
+
},
|
|
5123
|
+
clearRow(row) {
|
|
5124
|
+
internals.textBuffer.clearLineHighlights(row);
|
|
5125
|
+
},
|
|
5126
|
+
clearAllHighlights() {
|
|
5127
|
+
internals.textBuffer.clearAllHighlights();
|
|
5128
|
+
},
|
|
5129
|
+
registerStyle(name, definition) {
|
|
5130
|
+
return internals._textBufferSyntaxStyle.registerStyle(name, definition);
|
|
5131
|
+
},
|
|
5132
|
+
refresh() {
|
|
5133
|
+
internals.updateTextInfo();
|
|
5134
|
+
}
|
|
5135
|
+
};
|
|
5136
|
+
}
|
|
5137
|
+
function onPaneLifecyclePass(text, callback) {
|
|
5138
|
+
const host = text;
|
|
5139
|
+
const previous = host.onLifecyclePass;
|
|
5140
|
+
host.onLifecyclePass = () => {
|
|
5141
|
+
previous?.call(text);
|
|
5142
|
+
callback();
|
|
5143
|
+
};
|
|
5144
|
+
}
|
|
5145
|
+
|
|
5146
|
+
// src/ui/panes/viewport-highlights.ts
|
|
5147
|
+
var MARGIN_LINES = 32;
|
|
5148
|
+
var LINE_END_COLS = 1e6;
|
|
5149
|
+
function createViewportHighlights(text, spec) {
|
|
5150
|
+
const { buffer, paintLine, scrollY: logicalScrollY } = spec;
|
|
5151
|
+
let content;
|
|
5152
|
+
let installed = "";
|
|
5153
|
+
let active = false;
|
|
5154
|
+
let rowSources;
|
|
5155
|
+
let rowSourcesWidth = -1;
|
|
5156
|
+
let appliedScrollY = -1;
|
|
5157
|
+
let appliedHeight = -1;
|
|
5158
|
+
let painted;
|
|
5159
|
+
const paint = (force) => {
|
|
5160
|
+
if (!active)
|
|
5161
|
+
return;
|
|
5162
|
+
const height = Math.max(1, Math.floor(text.height));
|
|
5163
|
+
const scrollY = Math.max(0, Math.floor(logicalScrollY?.(content) ?? text.scrollY));
|
|
5164
|
+
const width = Math.max(1, Math.floor(text.width));
|
|
5165
|
+
if (!force && painted !== undefined && appliedScrollY === scrollY && appliedHeight === height && rowSourcesWidth === width)
|
|
5166
|
+
return;
|
|
5167
|
+
if (rowSources === undefined || rowSourcesWidth !== width) {
|
|
5168
|
+
rowSources = text.lineInfo.lineSources;
|
|
5169
|
+
rowSourcesWidth = width;
|
|
5170
|
+
}
|
|
5171
|
+
const sources = rowSources;
|
|
5172
|
+
const lastRow = Math.max(0, Math.min(scrollY + height - 1, sources.length - 1));
|
|
5173
|
+
const firstLine = sources[Math.min(scrollY, lastRow)] ?? scrollY;
|
|
5174
|
+
const lastLine = sources[lastRow] ?? lastRow;
|
|
5175
|
+
const from = Math.max(0, firstLine - MARGIN_LINES);
|
|
5176
|
+
const to = lastLine + MARGIN_LINES;
|
|
5177
|
+
const previous = painted;
|
|
5178
|
+
if (force || previous === undefined || previous.to < from || previous.from > to) {
|
|
5179
|
+
buffer.clearAllHighlights();
|
|
5180
|
+
for (let line = from;line <= to; line++)
|
|
5181
|
+
paintLine(line, content);
|
|
5182
|
+
} else {
|
|
5183
|
+
for (let line = previous.from;line < from; line++)
|
|
5184
|
+
buffer.clearRow(line);
|
|
5185
|
+
for (let line = to + 1;line <= previous.to; line++)
|
|
5186
|
+
buffer.clearRow(line);
|
|
5187
|
+
for (let line = from;line < previous.from; line++)
|
|
5188
|
+
paintLine(line, content);
|
|
5189
|
+
for (let line = previous.to + 1;line <= to; line++)
|
|
5190
|
+
paintLine(line, content);
|
|
5191
|
+
}
|
|
5192
|
+
painted = { from, to };
|
|
5193
|
+
appliedScrollY = scrollY;
|
|
5194
|
+
appliedHeight = height;
|
|
5195
|
+
};
|
|
5196
|
+
onPaneLifecyclePass(text, () => paint(false));
|
|
5197
|
+
return {
|
|
5198
|
+
install(full, next) {
|
|
5199
|
+
content = next;
|
|
5200
|
+
active = true;
|
|
5201
|
+
const changed = installed !== full;
|
|
5202
|
+
if (changed) {
|
|
5203
|
+
installed = full;
|
|
5204
|
+
buffer.setText(full);
|
|
5205
|
+
rowSources = undefined;
|
|
5206
|
+
painted = undefined;
|
|
5207
|
+
}
|
|
5208
|
+
paint(changed);
|
|
5209
|
+
},
|
|
5210
|
+
repaint() {
|
|
5211
|
+
paint(true);
|
|
5212
|
+
},
|
|
5213
|
+
release() {
|
|
5214
|
+
if (!active)
|
|
5215
|
+
return;
|
|
5216
|
+
buffer.clearAllHighlights();
|
|
5217
|
+
active = false;
|
|
5218
|
+
installed = "";
|
|
5219
|
+
rowSources = undefined;
|
|
5220
|
+
rowSourcesWidth = -1;
|
|
5221
|
+
appliedScrollY = -1;
|
|
5222
|
+
appliedHeight = -1;
|
|
5223
|
+
painted = undefined;
|
|
5224
|
+
}
|
|
5225
|
+
};
|
|
5226
|
+
}
|
|
5227
|
+
|
|
5228
|
+
// src/ui/panes/list-text.ts
|
|
5229
|
+
var painters = new WeakMap;
|
|
5230
|
+
function resolveSegment(text, style, color) {
|
|
5231
|
+
let fg3;
|
|
5232
|
+
let dim2;
|
|
5233
|
+
if (color !== undefined) {
|
|
5234
|
+
fg3 = parseColor(color);
|
|
5235
|
+
} else {
|
|
5236
|
+
switch (style) {
|
|
5237
|
+
case "dim":
|
|
5238
|
+
dim2 = true;
|
|
5239
|
+
break;
|
|
5240
|
+
case "cyan":
|
|
5241
|
+
fg3 = ANSI_CYAN;
|
|
5242
|
+
break;
|
|
5243
|
+
case "green":
|
|
5244
|
+
fg3 = ANSI_GREEN;
|
|
5245
|
+
break;
|
|
5246
|
+
case "yellow":
|
|
5247
|
+
fg3 = ANSI_YELLOW;
|
|
5248
|
+
break;
|
|
5249
|
+
case "magenta":
|
|
5250
|
+
fg3 = ANSI_MAGENTA;
|
|
5251
|
+
break;
|
|
5252
|
+
case "default":
|
|
5253
|
+
case undefined:
|
|
5254
|
+
break;
|
|
5255
|
+
}
|
|
5256
|
+
}
|
|
5257
|
+
return {
|
|
5258
|
+
text,
|
|
5259
|
+
...fg3 === undefined ? {} : { fg: fg3 },
|
|
5260
|
+
...dim2 === undefined ? {} : { dim: dim2 }
|
|
5261
|
+
};
|
|
5262
|
+
}
|
|
5263
|
+
function styleKey(fg3, bold3, dim2, bg2) {
|
|
5264
|
+
const fgKey = fg3 === undefined ? "" : fg3.toInts().join(",");
|
|
5265
|
+
const bgKey = bg2 === undefined ? "" : bg2.toInts().join(",");
|
|
5266
|
+
return `${fgKey}|${bold3 ? 1 : 0}|${dim2 ? 1 : 0}|${bgKey}`;
|
|
5267
|
+
}
|
|
5268
|
+
function styleIdFor(record, fg3, bold3, dim2, bg2) {
|
|
5269
|
+
const key = styleKey(fg3, bold3, dim2, bg2);
|
|
5270
|
+
const cached = record.styleIds.get(key);
|
|
5271
|
+
if (cached !== undefined)
|
|
5272
|
+
return cached;
|
|
5273
|
+
const id = record.buffer.registerStyle(`githunk.list.${record.styleIds.size}`, {
|
|
5274
|
+
...fg3 === undefined ? {} : { fg: fg3 },
|
|
5275
|
+
...bg2 === undefined ? {} : { bg: bg2 },
|
|
5276
|
+
...bold3 ? { bold: bold3 } : {},
|
|
5277
|
+
...dim2 ? { dim: dim2 } : {}
|
|
5278
|
+
});
|
|
5279
|
+
record.styleIds.set(key, id);
|
|
5280
|
+
return id;
|
|
5281
|
+
}
|
|
5282
|
+
function rowVisual(state, focused, hoveredId, rowIndexById, range, displayRow) {
|
|
5283
|
+
if (displayRow.kind !== "item")
|
|
5284
|
+
return 0;
|
|
5285
|
+
if (focused && displayRow.id === state.selectedId)
|
|
5286
|
+
return 1;
|
|
5287
|
+
if (range !== undefined) {
|
|
5288
|
+
const index = rowIndexById.get(displayRow.id);
|
|
5289
|
+
if (index !== undefined && index >= range.startIndex && index <= range.endIndex)
|
|
5290
|
+
return 2;
|
|
5291
|
+
}
|
|
5292
|
+
if (displayRow.id === hoveredId)
|
|
5293
|
+
return 3;
|
|
5294
|
+
return 0;
|
|
5295
|
+
}
|
|
5296
|
+
function layoutFor(state, safeWidth) {
|
|
5297
|
+
const displayRows = state.displayRows;
|
|
5298
|
+
const rowMap = new Map(state.rows.map((row) => [row.id, row]));
|
|
5299
|
+
const visibleRows = displayRows.flatMap((dr) => {
|
|
5300
|
+
if (dr.kind !== "item")
|
|
5301
|
+
return [];
|
|
5302
|
+
const row = rowMap.get(dr.id);
|
|
5303
|
+
return row === undefined ? [] : [row];
|
|
5304
|
+
});
|
|
5305
|
+
const layout = computeColumnLayout(visibleRows, safeWidth);
|
|
5306
|
+
const rowTexts = [];
|
|
5307
|
+
const rowSegments = [];
|
|
5308
|
+
for (const dr of displayRows) {
|
|
5309
|
+
if (dr.kind !== "item") {
|
|
5310
|
+
const truncated = [...dr.text].slice(0, safeWidth).join("");
|
|
5311
|
+
rowTexts.push(truncated);
|
|
5312
|
+
rowSegments.push(truncated.length === 0 ? [] : [{ text: truncated }]);
|
|
5313
|
+
continue;
|
|
5314
|
+
}
|
|
5315
|
+
const row = rowMap.get(dr.id);
|
|
5316
|
+
const laidOut = row === undefined ? [] : layoutListRowSegments(row, layout).map((segment) => resolveSegment(segment.text, segment.style, segment.color));
|
|
5317
|
+
const joined = laidOut.map((segment) => segment.text).join("");
|
|
5318
|
+
const pad = Math.max(0, safeWidth - cellWidth(joined));
|
|
5319
|
+
rowTexts.push(pad === 0 ? joined : `${joined}${" ".repeat(pad)}`);
|
|
5320
|
+
rowSegments.push(laidOut);
|
|
5321
|
+
}
|
|
5322
|
+
return { rows: state.rows, width: safeWidth, rowTexts, rowSegments, joined: rowTexts.join(`
|
|
5323
|
+
`) };
|
|
5324
|
+
}
|
|
5325
|
+
function visualsFor(state, focused, hoveredId) {
|
|
5326
|
+
const rowIndexById = new Map(state.rows.map((row, index) => [row.id, index]));
|
|
5327
|
+
const rangeActive = focused && isListRangeActive(state);
|
|
5328
|
+
const range = rangeActive ? getListSelectionRange(state) : undefined;
|
|
5329
|
+
return state.displayRows.map((dr) => rowVisual(state, focused, hoveredId, rowIndexById, range, dr));
|
|
5330
|
+
}
|
|
5331
|
+
function paintRow(record, line) {
|
|
5332
|
+
const snap = record.ref.snap;
|
|
5333
|
+
if (snap === undefined)
|
|
5334
|
+
return;
|
|
5335
|
+
const segments = snap.rowSegments[line];
|
|
5336
|
+
const visual = snap.visuals[line];
|
|
5337
|
+
if (segments === undefined || visual === undefined)
|
|
5338
|
+
return;
|
|
5339
|
+
const { buffer } = record;
|
|
5340
|
+
buffer.clearRow(line);
|
|
5341
|
+
const bg2 = visual === 1 || visual === 2 ? SELECTED_LINE_BG : visual === 3 ? HOVER_LINE_BG : undefined;
|
|
5342
|
+
let column = 0;
|
|
5343
|
+
for (const segment of segments) {
|
|
5344
|
+
const cells = cellWidth(segment.text);
|
|
5345
|
+
if (cells > 0) {
|
|
5346
|
+
if (visual === 1) {
|
|
5347
|
+
buffer.addHighlight(line, {
|
|
5348
|
+
start: column,
|
|
5349
|
+
end: column + cells,
|
|
5350
|
+
styleId: styleIdFor(record, segment.fg === undefined ? undefined : brightenAnsiForeground(segment.fg), true, segment.dim === true, bg2)
|
|
5351
|
+
});
|
|
5352
|
+
} else if (bg2 !== undefined) {
|
|
5353
|
+
buffer.addHighlight(line, {
|
|
5354
|
+
start: column,
|
|
5355
|
+
end: column + cells,
|
|
5356
|
+
styleId: styleIdFor(record, segment.fg, false, segment.dim === true, bg2)
|
|
5357
|
+
});
|
|
5358
|
+
} else if (segment.fg !== undefined || segment.dim === true) {
|
|
5359
|
+
buffer.addHighlight(line, {
|
|
5360
|
+
start: column,
|
|
5361
|
+
end: column + cells,
|
|
5362
|
+
styleId: styleIdFor(record, segment.fg, false, segment.dim === true, undefined)
|
|
5363
|
+
});
|
|
5364
|
+
}
|
|
5365
|
+
}
|
|
5366
|
+
column += cells;
|
|
5367
|
+
}
|
|
5368
|
+
if (bg2 !== undefined) {
|
|
5369
|
+
buffer.addHighlight(line, { start: column, end: LINE_END_COLS, styleId: styleIdFor(record, undefined, false, false, bg2) });
|
|
5370
|
+
}
|
|
5371
|
+
}
|
|
5372
|
+
function ensurePainter(text, buffer) {
|
|
5373
|
+
const existing = painters.get(text);
|
|
5374
|
+
if (existing !== undefined)
|
|
5375
|
+
return existing;
|
|
5376
|
+
const ref = { snap: undefined };
|
|
5377
|
+
const record = {
|
|
5378
|
+
buffer,
|
|
5379
|
+
viewport: undefined,
|
|
5380
|
+
ref,
|
|
5381
|
+
styleIds: new Map,
|
|
5382
|
+
cache: undefined,
|
|
5383
|
+
joined: "",
|
|
5384
|
+
visuals: []
|
|
5385
|
+
};
|
|
5386
|
+
record.viewport = createViewportHighlights(text, {
|
|
5387
|
+
buffer,
|
|
5388
|
+
paintLine: (line) => paintRow(record, line)
|
|
5389
|
+
});
|
|
5390
|
+
painters.set(text, record);
|
|
5391
|
+
return record;
|
|
5392
|
+
}
|
|
5393
|
+
function installListText(text, content) {
|
|
5394
|
+
const buffer = paneTextBuffer(text);
|
|
5395
|
+
if (buffer === undefined) {
|
|
5396
|
+
text.content = renderListRows(content.state, content.focused, content.width, content.hoveredId);
|
|
5397
|
+
return;
|
|
5398
|
+
}
|
|
5399
|
+
const record = ensurePainter(text, buffer);
|
|
5400
|
+
const safeWidth = Math.max(0, Math.floor(content.width));
|
|
5401
|
+
const previousCache = record.cache;
|
|
5402
|
+
const cache = previousCache !== undefined && previousCache.rows === content.state.rows && previousCache.width === safeWidth ? previousCache : layoutFor(content.state, safeWidth);
|
|
5403
|
+
record.cache = cache;
|
|
5404
|
+
const visuals = visualsFor(content.state, content.focused, content.hoveredId);
|
|
5405
|
+
record.ref.snap = { rowSegments: cache.rowSegments, visuals };
|
|
5406
|
+
if (cache.joined !== record.joined) {
|
|
5407
|
+
record.joined = cache.joined;
|
|
5408
|
+
record.visuals = visuals;
|
|
5409
|
+
record.viewport.install(cache.joined, record.ref);
|
|
5410
|
+
return;
|
|
5411
|
+
}
|
|
5412
|
+
if (cache !== previousCache) {
|
|
5413
|
+
record.visuals = visuals;
|
|
5414
|
+
record.viewport.repaint();
|
|
5415
|
+
record.buffer.refresh();
|
|
5416
|
+
return;
|
|
5417
|
+
}
|
|
5418
|
+
const previous = record.visuals;
|
|
5419
|
+
record.visuals = visuals;
|
|
5420
|
+
let repainted = false;
|
|
5421
|
+
const lines = Math.max(previous.length, visuals.length);
|
|
5422
|
+
for (let line = 0;line < lines; line++) {
|
|
5423
|
+
if (previous[line] !== visuals[line]) {
|
|
5424
|
+
paintRow(record, line);
|
|
5425
|
+
repainted = true;
|
|
5426
|
+
}
|
|
5427
|
+
}
|
|
5428
|
+
if (repainted)
|
|
5429
|
+
record.buffer.refresh();
|
|
5430
|
+
}
|
|
5431
|
+
function releaseListText(text) {
|
|
5432
|
+
const record = painters.get(text);
|
|
5433
|
+
if (record === undefined)
|
|
5434
|
+
return;
|
|
5435
|
+
record.viewport.release();
|
|
5436
|
+
record.buffer.refresh();
|
|
5437
|
+
painters.delete(text);
|
|
5438
|
+
}
|
|
5439
|
+
|
|
5020
5440
|
// src/ui/panes/branches-pane.ts
|
|
5021
5441
|
function localBranchRows(model, filter = "", options = {}) {
|
|
5022
5442
|
const listing = model.branches;
|
|
@@ -5067,8 +5487,7 @@ function createBranchesPane(renderer, model) {
|
|
|
5067
5487
|
const rows = localBranchRows(model);
|
|
5068
5488
|
const displayRows = rows.length === 0 ? [{ kind: "message", text: "No branches" }] : undefined;
|
|
5069
5489
|
const state = createListState(rows, displayRows);
|
|
5070
|
-
|
|
5071
|
-
pane.update(content);
|
|
5490
|
+
installListText(pane.text, { state, width: 80, focused: false });
|
|
5072
5491
|
pane.syncScrollbar();
|
|
5073
5492
|
return pane;
|
|
5074
5493
|
}
|
|
@@ -5389,47 +5808,6 @@ function commitGraphRows(commits, getColor) {
|
|
|
5389
5808
|
|
|
5390
5809
|
// src/ui/author-style.ts
|
|
5391
5810
|
import { createHash as createHash2 } from "node:crypto";
|
|
5392
|
-
|
|
5393
|
-
// src/ui/cell-width.ts
|
|
5394
|
-
var WIDE_RANGES = [
|
|
5395
|
-
[4352, 4447],
|
|
5396
|
-
[11904, 42191],
|
|
5397
|
-
[44032, 55203],
|
|
5398
|
-
[63744, 64255],
|
|
5399
|
-
[65072, 65135],
|
|
5400
|
-
[65280, 65376],
|
|
5401
|
-
[65504, 65510],
|
|
5402
|
-
[127744, 129535],
|
|
5403
|
-
[129648, 129791],
|
|
5404
|
-
[131072, 262141]
|
|
5405
|
-
];
|
|
5406
|
-
function isWide(grapheme) {
|
|
5407
|
-
const code = grapheme.codePointAt(0);
|
|
5408
|
-
if (code === undefined)
|
|
5409
|
-
return false;
|
|
5410
|
-
for (const [low, high] of WIDE_RANGES) {
|
|
5411
|
-
if (code >= low && code <= high)
|
|
5412
|
-
return true;
|
|
5413
|
-
}
|
|
5414
|
-
return false;
|
|
5415
|
-
}
|
|
5416
|
-
function cellWidth(value) {
|
|
5417
|
-
let ascii = true;
|
|
5418
|
-
for (let index = 0;index < value.length; index++) {
|
|
5419
|
-
if (value.charCodeAt(index) > 127) {
|
|
5420
|
-
ascii = false;
|
|
5421
|
-
break;
|
|
5422
|
-
}
|
|
5423
|
-
}
|
|
5424
|
-
if (ascii)
|
|
5425
|
-
return value.length;
|
|
5426
|
-
let width = 0;
|
|
5427
|
-
for (const codePoint of value)
|
|
5428
|
-
width += isWide(codePoint) ? 2 : 1;
|
|
5429
|
-
return width;
|
|
5430
|
-
}
|
|
5431
|
-
|
|
5432
|
-
// src/ui/author-style.ts
|
|
5433
5811
|
var initialsCache = new Map;
|
|
5434
5812
|
var colorCache = new Map;
|
|
5435
5813
|
function randInt(bytes, max) {
|
|
@@ -5559,20 +5937,22 @@ function buildCommitRows(commits, now, filter = "") {
|
|
|
5559
5937
|
const shortHash2 = commit.oid.length >= 8 ? commit.oid.slice(0, 8) : commit.shortOid;
|
|
5560
5938
|
const initials = authorInitials(commit.authorName).padEnd(AUTHOR_COLUMN_WIDTH, " ");
|
|
5561
5939
|
const relative = formatRelativeTime(commit.authoredAt, now);
|
|
5940
|
+
const graphText = graph?.text ?? "";
|
|
5941
|
+
const graphSegments = graph?.segments ?? [];
|
|
5942
|
+
const subjectSegments = commit.subject.length === 0 ? [] : [{ text: commit.subject }];
|
|
5562
5943
|
return {
|
|
5563
5944
|
id: commit.oid,
|
|
5564
5945
|
columns: [
|
|
5565
5946
|
{ text: shortHash2, priority: 1, color: commitHashColor(commit.status) },
|
|
5566
|
-
{ text: initials, priority:
|
|
5567
|
-
{ text:
|
|
5568
|
-
{ text:
|
|
5569
|
-
{ text: relative, priority: 4, style: "dim" }
|
|
5947
|
+
{ text: initials, priority: 2, color: authorColor(commit.authorName) },
|
|
5948
|
+
{ text: `${graphText}${commit.subject}`, priority: 2, flex: true, segments: [...graphSegments, ...subjectSegments] },
|
|
5949
|
+
{ text: relative, priority: 0, style: "dim" }
|
|
5570
5950
|
]
|
|
5571
5951
|
};
|
|
5572
5952
|
});
|
|
5573
5953
|
if (filter.length === 0)
|
|
5574
5954
|
return rows;
|
|
5575
|
-
return [...filterItems(filter, rows, (row) => `${row.columns[0]?.text ?? ""} ${row.columns[
|
|
5955
|
+
return [...filterItems(filter, rows, (row) => `${row.columns[0]?.text ?? ""} ${row.columns[2]?.text ?? row.id}`)];
|
|
5576
5956
|
}
|
|
5577
5957
|
function createCommitsPane(renderer, model) {
|
|
5578
5958
|
const pane = createPane(renderer, "commits", "", "No commit selected", false, {
|
|
@@ -5586,6 +5966,7 @@ function updateCommitsPane(pane, model) {
|
|
|
5586
5966
|
if (commits.length === 0) {
|
|
5587
5967
|
const empty = createListState([]);
|
|
5588
5968
|
paneStates.set(pane, empty);
|
|
5969
|
+
releaseListText(pane.text);
|
|
5589
5970
|
pane.update(model.loading ? "Loading…" : "No commits");
|
|
5590
5971
|
return;
|
|
5591
5972
|
}
|
|
@@ -5599,8 +5980,7 @@ function updateCommitsPane(pane, model) {
|
|
|
5599
5980
|
state = withPrev;
|
|
5600
5981
|
}
|
|
5601
5982
|
paneStates.set(pane, state);
|
|
5602
|
-
|
|
5603
|
-
pane.update(content);
|
|
5983
|
+
installListText(pane.text, { state, width: 80, focused: false });
|
|
5604
5984
|
pane.box.bottomTitle = undefined;
|
|
5605
5985
|
}
|
|
5606
5986
|
|
|
@@ -5736,183 +6116,56 @@ function parseAnsi(input) {
|
|
|
5736
6116
|
let runStart = 0;
|
|
5737
6117
|
let runStyle = { ...DEFAULT_STYLE };
|
|
5738
6118
|
const closeRun = () => {
|
|
5739
|
-
if (column > runStart && styled(runStyle)) {
|
|
5740
|
-
spans.push({
|
|
5741
|
-
row,
|
|
5742
|
-
start: runStart,
|
|
5743
|
-
end: column,
|
|
5744
|
-
...runStyle.fg === undefined ? {} : { fg: runStyle.fg },
|
|
5745
|
-
...runStyle.bold ? { bold: true } : {},
|
|
5746
|
-
...runStyle.dim ? { dim: true } : {}
|
|
5747
|
-
});
|
|
5748
|
-
}
|
|
5749
|
-
runStart = column;
|
|
5750
|
-
};
|
|
5751
|
-
for (let index = 0;index < input.length; ) {
|
|
5752
|
-
const char = input[index];
|
|
5753
|
-
if (char === "\x1B") {
|
|
5754
|
-
const length = escapeLength(input, index);
|
|
5755
|
-
if (input[index + 1] === "[" && input[index + length - 1] === "m") {
|
|
5756
|
-
const next = applySgr(style, parseParams(input.slice(index + 2, index + length - 1)));
|
|
5757
|
-
if (!sameStyle(next, runStyle)) {
|
|
5758
|
-
closeRun();
|
|
5759
|
-
runStyle = next;
|
|
5760
|
-
}
|
|
5761
|
-
style = next;
|
|
5762
|
-
}
|
|
5763
|
-
index += length;
|
|
5764
|
-
continue;
|
|
5765
|
-
}
|
|
5766
|
-
if (char === `
|
|
5767
|
-
`) {
|
|
5768
|
-
closeRun();
|
|
5769
|
-
out.push(char);
|
|
5770
|
-
row++;
|
|
5771
|
-
column = 0;
|
|
5772
|
-
runStart = 0;
|
|
5773
|
-
index += 1;
|
|
5774
|
-
continue;
|
|
5775
|
-
}
|
|
5776
|
-
const codePoint = input.codePointAt(index);
|
|
5777
|
-
const size = codePoint > 65535 ? 2 : 1;
|
|
5778
|
-
out.push(input.slice(index, index + size));
|
|
5779
|
-
column += 1;
|
|
5780
|
-
index += size;
|
|
5781
|
-
}
|
|
5782
|
-
closeRun();
|
|
5783
|
-
return { text: out.join(""), spans };
|
|
5784
|
-
}
|
|
5785
|
-
|
|
5786
|
-
// src/ui/panes/command-log-pane.ts
|
|
5787
|
-
import { BoxRenderable as BoxRenderable3, TextRenderable as TextRenderable2 } from "@opentui/core";
|
|
5788
|
-
|
|
5789
|
-
// src/ui/panes/pane-text.ts
|
|
5790
|
-
function internalsOf(text) {
|
|
5791
|
-
const candidate = text;
|
|
5792
|
-
const buffer = candidate.textBuffer;
|
|
5793
|
-
const style = candidate._textBufferSyntaxStyle;
|
|
5794
|
-
if (buffer === undefined || style === undefined)
|
|
5795
|
-
return;
|
|
5796
|
-
if (typeof buffer.setText !== "function" || typeof buffer.addHighlight !== "function" || typeof buffer.clearAllHighlights !== "function")
|
|
5797
|
-
return;
|
|
5798
|
-
if (typeof buffer.clearLineHighlights !== "function")
|
|
5799
|
-
return;
|
|
5800
|
-
if (typeof style.registerStyle !== "function" || typeof candidate.updateTextInfo !== "function")
|
|
5801
|
-
return;
|
|
5802
|
-
return candidate;
|
|
5803
|
-
}
|
|
5804
|
-
function paneTextBuffer(text) {
|
|
5805
|
-
const internals = internalsOf(text);
|
|
5806
|
-
if (internals === undefined)
|
|
5807
|
-
return;
|
|
5808
|
-
internals._hasManualStyledText = true;
|
|
5809
|
-
return {
|
|
5810
|
-
setText(value) {
|
|
5811
|
-
internals.textBuffer.setText(value);
|
|
5812
|
-
internals.updateTextInfo();
|
|
5813
|
-
},
|
|
5814
|
-
addHighlight(row, highlight) {
|
|
5815
|
-
internals.textBuffer.addHighlight(row, highlight);
|
|
5816
|
-
},
|
|
5817
|
-
clearRow(row) {
|
|
5818
|
-
internals.textBuffer.clearLineHighlights(row);
|
|
5819
|
-
},
|
|
5820
|
-
clearAllHighlights() {
|
|
5821
|
-
internals.textBuffer.clearAllHighlights();
|
|
5822
|
-
},
|
|
5823
|
-
registerStyle(name, definition) {
|
|
5824
|
-
return internals._textBufferSyntaxStyle.registerStyle(name, definition);
|
|
5825
|
-
}
|
|
5826
|
-
};
|
|
5827
|
-
}
|
|
5828
|
-
function onPaneLifecyclePass(text, callback) {
|
|
5829
|
-
const host = text;
|
|
5830
|
-
const previous = host.onLifecyclePass;
|
|
5831
|
-
host.onLifecyclePass = () => {
|
|
5832
|
-
previous?.call(text);
|
|
5833
|
-
callback();
|
|
5834
|
-
};
|
|
5835
|
-
}
|
|
5836
|
-
|
|
5837
|
-
// src/ui/panes/viewport-highlights.ts
|
|
5838
|
-
var MARGIN_LINES = 32;
|
|
5839
|
-
var LINE_END_COLS = 1e6;
|
|
5840
|
-
function createViewportHighlights(text, spec) {
|
|
5841
|
-
const { buffer, paintLine } = spec;
|
|
5842
|
-
let content;
|
|
5843
|
-
let installed = "";
|
|
5844
|
-
let active = false;
|
|
5845
|
-
let rowSources;
|
|
5846
|
-
let rowSourcesWidth = -1;
|
|
5847
|
-
let appliedScrollY = -1;
|
|
5848
|
-
let appliedHeight = -1;
|
|
5849
|
-
let painted;
|
|
5850
|
-
const paint = (force) => {
|
|
5851
|
-
if (!active)
|
|
5852
|
-
return;
|
|
5853
|
-
const height = Math.max(1, Math.floor(text.height));
|
|
5854
|
-
const scrollY = Math.max(0, Math.floor(text.scrollY));
|
|
5855
|
-
const width = Math.max(1, Math.floor(text.width));
|
|
5856
|
-
if (!force && painted !== undefined && appliedScrollY === scrollY && appliedHeight === height && rowSourcesWidth === width)
|
|
5857
|
-
return;
|
|
5858
|
-
if (rowSources === undefined || rowSourcesWidth !== width) {
|
|
5859
|
-
rowSources = text.lineInfo.lineSources;
|
|
5860
|
-
rowSourcesWidth = width;
|
|
5861
|
-
}
|
|
5862
|
-
const sources = rowSources;
|
|
5863
|
-
const lastRow = Math.max(0, Math.min(scrollY + height - 1, sources.length - 1));
|
|
5864
|
-
const firstLine = sources[Math.min(scrollY, lastRow)] ?? scrollY;
|
|
5865
|
-
const lastLine = sources[lastRow] ?? lastRow;
|
|
5866
|
-
const from = Math.max(0, firstLine - MARGIN_LINES);
|
|
5867
|
-
const to = lastLine + MARGIN_LINES;
|
|
5868
|
-
const previous = painted;
|
|
5869
|
-
if (previous === undefined || previous.to < from || previous.from > to) {
|
|
5870
|
-
buffer.clearAllHighlights();
|
|
5871
|
-
for (let line = from;line <= to; line++)
|
|
5872
|
-
paintLine(line, content);
|
|
5873
|
-
} else {
|
|
5874
|
-
for (let line = previous.from;line < from; line++)
|
|
5875
|
-
buffer.clearRow(line);
|
|
5876
|
-
for (let line = to + 1;line <= previous.to; line++)
|
|
5877
|
-
buffer.clearRow(line);
|
|
5878
|
-
for (let line = from;line < previous.from; line++)
|
|
5879
|
-
paintLine(line, content);
|
|
5880
|
-
for (let line = previous.to + 1;line <= to; line++)
|
|
5881
|
-
paintLine(line, content);
|
|
5882
|
-
}
|
|
5883
|
-
painted = { from, to };
|
|
5884
|
-
appliedScrollY = scrollY;
|
|
5885
|
-
appliedHeight = height;
|
|
5886
|
-
};
|
|
5887
|
-
onPaneLifecyclePass(text, () => paint(false));
|
|
5888
|
-
return {
|
|
5889
|
-
install(full, next) {
|
|
5890
|
-
content = next;
|
|
5891
|
-
active = true;
|
|
5892
|
-
const changed = installed !== full;
|
|
5893
|
-
if (changed) {
|
|
5894
|
-
installed = full;
|
|
5895
|
-
buffer.setText(full);
|
|
5896
|
-
rowSources = undefined;
|
|
5897
|
-
painted = undefined;
|
|
5898
|
-
}
|
|
5899
|
-
paint(changed);
|
|
5900
|
-
},
|
|
5901
|
-
release() {
|
|
5902
|
-
if (!active)
|
|
5903
|
-
return;
|
|
5904
|
-
buffer.clearAllHighlights();
|
|
5905
|
-
active = false;
|
|
5906
|
-
installed = "";
|
|
5907
|
-
rowSources = undefined;
|
|
5908
|
-
rowSourcesWidth = -1;
|
|
5909
|
-
appliedScrollY = -1;
|
|
5910
|
-
appliedHeight = -1;
|
|
5911
|
-
painted = undefined;
|
|
6119
|
+
if (column > runStart && styled(runStyle)) {
|
|
6120
|
+
spans.push({
|
|
6121
|
+
row,
|
|
6122
|
+
start: runStart,
|
|
6123
|
+
end: column,
|
|
6124
|
+
...runStyle.fg === undefined ? {} : { fg: runStyle.fg },
|
|
6125
|
+
...runStyle.bold ? { bold: true } : {},
|
|
6126
|
+
...runStyle.dim ? { dim: true } : {}
|
|
6127
|
+
});
|
|
5912
6128
|
}
|
|
6129
|
+
runStart = column;
|
|
5913
6130
|
};
|
|
6131
|
+
for (let index = 0;index < input.length; ) {
|
|
6132
|
+
const char = input[index];
|
|
6133
|
+
if (char === "\x1B") {
|
|
6134
|
+
const length = escapeLength(input, index);
|
|
6135
|
+
if (input[index + 1] === "[" && input[index + length - 1] === "m") {
|
|
6136
|
+
const next = applySgr(style, parseParams(input.slice(index + 2, index + length - 1)));
|
|
6137
|
+
if (!sameStyle(next, runStyle)) {
|
|
6138
|
+
closeRun();
|
|
6139
|
+
runStyle = next;
|
|
6140
|
+
}
|
|
6141
|
+
style = next;
|
|
6142
|
+
}
|
|
6143
|
+
index += length;
|
|
6144
|
+
continue;
|
|
6145
|
+
}
|
|
6146
|
+
if (char === `
|
|
6147
|
+
`) {
|
|
6148
|
+
closeRun();
|
|
6149
|
+
out.push(char);
|
|
6150
|
+
row++;
|
|
6151
|
+
column = 0;
|
|
6152
|
+
runStart = 0;
|
|
6153
|
+
index += 1;
|
|
6154
|
+
continue;
|
|
6155
|
+
}
|
|
6156
|
+
const codePoint = input.codePointAt(index);
|
|
6157
|
+
const size = codePoint > 65535 ? 2 : 1;
|
|
6158
|
+
out.push(input.slice(index, index + size));
|
|
6159
|
+
column += 1;
|
|
6160
|
+
index += size;
|
|
6161
|
+
}
|
|
6162
|
+
closeRun();
|
|
6163
|
+
return { text: out.join(""), spans };
|
|
5914
6164
|
}
|
|
5915
6165
|
|
|
6166
|
+
// src/ui/panes/command-log-pane.ts
|
|
6167
|
+
import { BoxRenderable as BoxRenderable3, TextRenderable as TextRenderable2 } from "@opentui/core";
|
|
6168
|
+
|
|
5916
6169
|
// src/ui/panes/command-log-text.ts
|
|
5917
6170
|
var STYLE_DEFINITIONS = {
|
|
5918
6171
|
action: { fg: ANSI_YELLOW },
|
|
@@ -5947,7 +6200,7 @@ function registerStyles(buffer) {
|
|
|
5947
6200
|
}
|
|
5948
6201
|
return ids;
|
|
5949
6202
|
}
|
|
5950
|
-
var
|
|
6203
|
+
var painters2 = new WeakMap;
|
|
5951
6204
|
function installCommandLogText(text, lines) {
|
|
5952
6205
|
const full = lines.map((line) => line.spans.map((span) => span.text).join("")).join(`
|
|
5953
6206
|
`);
|
|
@@ -5956,7 +6209,7 @@ function installCommandLogText(text, lines) {
|
|
|
5956
6209
|
text.content = full;
|
|
5957
6210
|
return;
|
|
5958
6211
|
}
|
|
5959
|
-
let painter =
|
|
6212
|
+
let painter = painters2.get(text);
|
|
5960
6213
|
if (painter === undefined) {
|
|
5961
6214
|
const styleIds = registerStyles(buffer);
|
|
5962
6215
|
painter = createViewportHighlights(text, {
|
|
@@ -5970,7 +6223,7 @@ function installCommandLogText(text, lines) {
|
|
|
5970
6223
|
}
|
|
5971
6224
|
}
|
|
5972
6225
|
});
|
|
5973
|
-
|
|
6226
|
+
painters2.set(text, painter);
|
|
5974
6227
|
}
|
|
5975
6228
|
painter.install(full, lines);
|
|
5976
6229
|
}
|
|
@@ -6452,7 +6705,7 @@ function createFilesPane(renderer, model) {
|
|
|
6452
6705
|
const initialRows = filesTreeRows(createFilesTreeState(model), model);
|
|
6453
6706
|
const displayRows = initialRows.length === 0 ? [{ kind: "message", text: NO_CHANGED_FILES }] : undefined;
|
|
6454
6707
|
const state = createListState(initialRows, displayRows);
|
|
6455
|
-
pane.
|
|
6708
|
+
installListText(pane.text, { state, width: 80, focused: false });
|
|
6456
6709
|
return pane;
|
|
6457
6710
|
}
|
|
6458
6711
|
function anyStagedChanges(model) {
|
|
@@ -6737,14 +6990,14 @@ function changedIndexesInDiffLineRange(document, state) {
|
|
|
6737
6990
|
|
|
6738
6991
|
// src/ui/panes/ansi-text.ts
|
|
6739
6992
|
import { StyledText as StyledText3, bold as boldChunk, dim as dimChunk, fg as fgChunk } from "@opentui/core";
|
|
6740
|
-
var
|
|
6741
|
-
function
|
|
6993
|
+
var painters3 = new WeakMap;
|
|
6994
|
+
function styleKey2(span) {
|
|
6742
6995
|
const color = span.fg;
|
|
6743
6996
|
const colorKey = color === undefined ? "-" : `${color.intent}:${color.slot}:${color.toInts().join(",")}`;
|
|
6744
6997
|
return `${colorKey}|${span.bold === true ? "b" : "-"}${span.dim === true ? "d" : "-"}`;
|
|
6745
6998
|
}
|
|
6746
|
-
function
|
|
6747
|
-
const key =
|
|
6999
|
+
function styleIdFor2(buffer, styleIds, span) {
|
|
7000
|
+
const key = styleKey2(span);
|
|
6748
7001
|
const existing = styleIds.get(key);
|
|
6749
7002
|
if (existing !== undefined)
|
|
6750
7003
|
return existing;
|
|
@@ -6826,7 +7079,7 @@ function installAnsiText(text, content) {
|
|
|
6826
7079
|
}
|
|
6827
7080
|
const { text: full, firstBodyRow } = joined(content);
|
|
6828
7081
|
const spansByRow = groupByRow(content.spans, firstBodyRow);
|
|
6829
|
-
let painter =
|
|
7082
|
+
let painter = painters3.get(text);
|
|
6830
7083
|
if (painter === undefined) {
|
|
6831
7084
|
const styleIds = new Map;
|
|
6832
7085
|
painter = {
|
|
@@ -6838,17 +7091,17 @@ function installAnsiText(text, content) {
|
|
|
6838
7091
|
if (spans === undefined)
|
|
6839
7092
|
return;
|
|
6840
7093
|
for (const span of spans) {
|
|
6841
|
-
buffer.addHighlight(row, { start: span.start, end: span.end, styleId:
|
|
7094
|
+
buffer.addHighlight(row, { start: span.start, end: span.end, styleId: styleIdFor2(buffer, styleIds, span) });
|
|
6842
7095
|
}
|
|
6843
7096
|
}
|
|
6844
7097
|
})
|
|
6845
7098
|
};
|
|
6846
|
-
|
|
7099
|
+
painters3.set(text, painter);
|
|
6847
7100
|
}
|
|
6848
7101
|
painter.highlights.install(full, spansByRow);
|
|
6849
7102
|
}
|
|
6850
7103
|
function releaseAnsiText(text) {
|
|
6851
|
-
|
|
7104
|
+
painters3.get(text)?.highlights.release();
|
|
6852
7105
|
}
|
|
6853
7106
|
|
|
6854
7107
|
// src/ui/panes/diff-text.ts
|
|
@@ -6937,7 +7190,7 @@ function statSpansForRow(value, spans) {
|
|
|
6937
7190
|
function preambleSpansForRow(value, spans) {
|
|
6938
7191
|
return spans === undefined ? [plainChunk3(value)] : statSpansForRow(value, spans);
|
|
6939
7192
|
}
|
|
6940
|
-
var
|
|
7193
|
+
var painters4 = new WeakMap;
|
|
6941
7194
|
function registerStyles2(buffer) {
|
|
6942
7195
|
const ids = {};
|
|
6943
7196
|
for (const [name, definition] of Object.entries(STYLE_DEFINITIONS2)) {
|
|
@@ -6975,7 +7228,7 @@ function styledChunk(style, value) {
|
|
|
6975
7228
|
}
|
|
6976
7229
|
function paintAsChunks2(text, content) {
|
|
6977
7230
|
const { text: full, firstDiffRow } = joined2(content);
|
|
6978
|
-
const preambleSpans = statSpansForPreamble(content.preamble);
|
|
7231
|
+
const preambleSpans = content.preambleSpans ?? statSpansForPreamble(content.preamble);
|
|
6979
7232
|
const rows = full.split(`
|
|
6980
7233
|
`);
|
|
6981
7234
|
const chunks = [];
|
|
@@ -7008,13 +7261,15 @@ function installDiffText(text, content) {
|
|
|
7008
7261
|
const paint = {
|
|
7009
7262
|
displayLines: content.displayLines,
|
|
7010
7263
|
firstDiffRow,
|
|
7011
|
-
preambleSpans: statSpansForPreamble(content.preamble)
|
|
7264
|
+
preambleSpans: content.preambleSpans ?? statSpansForPreamble(content.preamble),
|
|
7265
|
+
...content.highlightScrollY === undefined ? {} : { highlightScrollY: content.highlightScrollY }
|
|
7012
7266
|
};
|
|
7013
|
-
let painter =
|
|
7267
|
+
let painter = painters4.get(text);
|
|
7014
7268
|
if (painter === undefined) {
|
|
7015
7269
|
const styleIds = registerStyles2(buffer);
|
|
7016
7270
|
painter = createViewportHighlights(text, {
|
|
7017
7271
|
buffer,
|
|
7272
|
+
scrollY: (current) => current.highlightScrollY?.() ?? text.scrollY,
|
|
7018
7273
|
paintLine: (row, current) => {
|
|
7019
7274
|
const preambleSpans = current.preambleSpans.get(row);
|
|
7020
7275
|
if (preambleSpans !== undefined) {
|
|
@@ -7031,12 +7286,508 @@ function installDiffText(text, content) {
|
|
|
7031
7286
|
buffer.addHighlight(row, { start: display.gutterCols, end: LINE_END_COLS, styleId: styleIds[display.style] });
|
|
7032
7287
|
}
|
|
7033
7288
|
});
|
|
7034
|
-
|
|
7289
|
+
painters4.set(text, painter);
|
|
7035
7290
|
}
|
|
7036
7291
|
painter.install(full, paint);
|
|
7037
7292
|
}
|
|
7038
7293
|
function releaseDiffText(text) {
|
|
7039
|
-
|
|
7294
|
+
painters4.get(text)?.release();
|
|
7295
|
+
}
|
|
7296
|
+
|
|
7297
|
+
// src/domain/diff/virtual.ts
|
|
7298
|
+
var VIRTUAL_DIFF_LINE_THRESHOLD = 1e4;
|
|
7299
|
+
function isSourceLine(line) {
|
|
7300
|
+
return line.kind === "context" || line.kind === "addition" || line.kind === "deletion";
|
|
7301
|
+
}
|
|
7302
|
+
function styleFor2(line) {
|
|
7303
|
+
if (line.kind === "addition")
|
|
7304
|
+
return "addition";
|
|
7305
|
+
if (line.kind === "deletion")
|
|
7306
|
+
return "deletion";
|
|
7307
|
+
if (line.kind === "hunk-header")
|
|
7308
|
+
return "hunk-header";
|
|
7309
|
+
if (line.kind === "metadata" || line.kind === "no-newline")
|
|
7310
|
+
return "metadata";
|
|
7311
|
+
return "plain";
|
|
7312
|
+
}
|
|
7313
|
+
function lineNumberWidth2(document) {
|
|
7314
|
+
let largest = 1;
|
|
7315
|
+
for (const line of document.lines) {
|
|
7316
|
+
largest = Math.max(largest, line.oldLine ?? 0, line.newLine ?? 0);
|
|
7317
|
+
}
|
|
7318
|
+
return String(largest).length;
|
|
7319
|
+
}
|
|
7320
|
+
function linePrefix(line, width) {
|
|
7321
|
+
if (!isSourceLine(line))
|
|
7322
|
+
return "";
|
|
7323
|
+
const old = line.oldLine === undefined ? "" : String(line.oldLine);
|
|
7324
|
+
const next = line.newLine === undefined ? "" : String(line.newLine);
|
|
7325
|
+
return `${old.padStart(width, " ")} ${next.padStart(width, " ")} `;
|
|
7326
|
+
}
|
|
7327
|
+
function withoutLineEnding2(raw) {
|
|
7328
|
+
if (raw.endsWith(`\r
|
|
7329
|
+
`))
|
|
7330
|
+
return raw.slice(0, -2);
|
|
7331
|
+
if (raw.endsWith(`
|
|
7332
|
+
`) || raw.endsWith("\r"))
|
|
7333
|
+
return raw.slice(0, -1);
|
|
7334
|
+
return raw;
|
|
7335
|
+
}
|
|
7336
|
+
function normalizePreamble(preamble) {
|
|
7337
|
+
if (preamble.length === 0)
|
|
7338
|
+
return { text: "", rows: [], starts: [], ends: [] };
|
|
7339
|
+
const text = preamble.endsWith(`
|
|
7340
|
+
`) ? preamble : `${preamble}
|
|
7341
|
+
`;
|
|
7342
|
+
const rows = text.slice(0, -1).split(`
|
|
7343
|
+
`).map(withoutLineEnding2);
|
|
7344
|
+
const starts = [];
|
|
7345
|
+
const ends = [];
|
|
7346
|
+
let start = 0;
|
|
7347
|
+
for (let row = 0;row < rows.length; row += 1) {
|
|
7348
|
+
const newline = text.indexOf(`
|
|
7349
|
+
`, start);
|
|
7350
|
+
starts.push(start);
|
|
7351
|
+
ends.push(newline < 0 ? text.length : newline + 1);
|
|
7352
|
+
start = newline < 0 ? text.length : newline + 1;
|
|
7353
|
+
}
|
|
7354
|
+
return { text, rows, starts, ends };
|
|
7355
|
+
}
|
|
7356
|
+
function boundedIndex(value, length) {
|
|
7357
|
+
if (!Number.isFinite(value))
|
|
7358
|
+
return value < 0 ? 0 : length;
|
|
7359
|
+
return Math.min(length, Math.max(0, Math.floor(value)));
|
|
7360
|
+
}
|
|
7361
|
+
function createVirtualDiffLayout(document, preamble) {
|
|
7362
|
+
const normalized = normalizePreamble(preamble);
|
|
7363
|
+
const width = lineNumberWidth2(document);
|
|
7364
|
+
const prefixes = document.lines.map((line) => linePrefix(line, width));
|
|
7365
|
+
const displayStarts = new Array(document.lines.length);
|
|
7366
|
+
let displayLength = normalized.text.length;
|
|
7367
|
+
let contentWidth = 0;
|
|
7368
|
+
for (const row of normalized.rows)
|
|
7369
|
+
contentWidth = Math.max(contentWidth, cellWidth(row));
|
|
7370
|
+
for (let index = 0;index < document.lines.length; index += 1) {
|
|
7371
|
+
const line = document.lines[index];
|
|
7372
|
+
const prefix = prefixes[index];
|
|
7373
|
+
const text = `${prefix}${withoutLineEnding2(line.raw)}`;
|
|
7374
|
+
displayStarts[index] = displayLength;
|
|
7375
|
+
displayLength += prefix.length + line.raw.length;
|
|
7376
|
+
contentWidth = Math.max(contentWidth, cellWidth(text));
|
|
7377
|
+
}
|
|
7378
|
+
const totalRows = normalized.rows.length + document.lines.length;
|
|
7379
|
+
const bodyRow = (lineIndex) => {
|
|
7380
|
+
const line = document.lines[lineIndex];
|
|
7381
|
+
const prefix = prefixes[lineIndex];
|
|
7382
|
+
return {
|
|
7383
|
+
text: `${prefix}${withoutLineEnding2(line.raw)}`,
|
|
7384
|
+
gutterCols: prefix.length,
|
|
7385
|
+
style: styleFor2(line),
|
|
7386
|
+
lineIndex,
|
|
7387
|
+
rawStartUtf16: line.startUtf16,
|
|
7388
|
+
rawEndUtf16: line.endUtf16,
|
|
7389
|
+
displayStartUtf16: displayStarts[lineIndex],
|
|
7390
|
+
displayEndUtf16: displayStarts[lineIndex] + prefix.length + line.raw.length
|
|
7391
|
+
};
|
|
7392
|
+
};
|
|
7393
|
+
const rowAt = (row) => {
|
|
7394
|
+
if (!Number.isSafeInteger(row) || row < 0 || row >= totalRows)
|
|
7395
|
+
return;
|
|
7396
|
+
if (row < normalized.rows.length) {
|
|
7397
|
+
const text = normalized.rows[row];
|
|
7398
|
+
return {
|
|
7399
|
+
text,
|
|
7400
|
+
gutterCols: 0,
|
|
7401
|
+
style: "plain",
|
|
7402
|
+
displayStartUtf16: normalized.starts[row],
|
|
7403
|
+
displayEndUtf16: normalized.ends[row]
|
|
7404
|
+
};
|
|
7405
|
+
}
|
|
7406
|
+
return bodyRow(row - normalized.rows.length);
|
|
7407
|
+
};
|
|
7408
|
+
const window = (scrollTop, viewportHeight, overscan) => {
|
|
7409
|
+
const viewport = Math.max(0, Math.floor(Number.isFinite(viewportHeight) ? viewportHeight : 0));
|
|
7410
|
+
if (totalRows === 0 || viewport === 0)
|
|
7411
|
+
return [0, -1];
|
|
7412
|
+
const margin = Math.max(0, Math.floor(Number.isFinite(overscan) ? overscan : 0));
|
|
7413
|
+
const maxScroll = Math.max(0, totalRows - viewport);
|
|
7414
|
+
const top = Math.min(maxScroll, Math.max(0, Math.floor(Number.isFinite(scrollTop) ? scrollTop : 0)));
|
|
7415
|
+
return [Math.max(0, top - margin), Math.min(totalRows - 1, top + viewport - 1 + margin)];
|
|
7416
|
+
};
|
|
7417
|
+
const displayOffsetsForLines = (startIndex, endIndex) => {
|
|
7418
|
+
let start = boundedIndex(startIndex, document.lines.length);
|
|
7419
|
+
let end = boundedIndex(endIndex, document.lines.length);
|
|
7420
|
+
if (end < start)
|
|
7421
|
+
[start, end] = [end, start];
|
|
7422
|
+
const rawStartUtf16 = start < document.lines.length ? document.lines[start].startUtf16 : document.text.length;
|
|
7423
|
+
const rawEndUtf16 = end < document.lines.length ? document.lines[end].startUtf16 : document.text.length;
|
|
7424
|
+
const displayStartUtf16 = start < document.lines.length ? displayStarts[start] : displayLength;
|
|
7425
|
+
const displayEndUtf16 = end < document.lines.length ? displayStarts[end] : displayLength;
|
|
7426
|
+
return { rawStartUtf16, rawEndUtf16, displayStartUtf16, displayEndUtf16 };
|
|
7427
|
+
};
|
|
7428
|
+
const rawOffsetAt = (row, column) => {
|
|
7429
|
+
const value = rowAt(row);
|
|
7430
|
+
if (value?.lineIndex === undefined || value.rawStartUtf16 === undefined || value.rawEndUtf16 === undefined)
|
|
7431
|
+
return;
|
|
7432
|
+
const line = document.lines[value.lineIndex];
|
|
7433
|
+
const target = Math.max(0, Math.floor(Number.isFinite(column) ? column : 0));
|
|
7434
|
+
if (target <= value.gutterCols)
|
|
7435
|
+
return line.startUtf16;
|
|
7436
|
+
const body = withoutLineEnding2(line.raw);
|
|
7437
|
+
const bodyColumn = target - value.gutterCols;
|
|
7438
|
+
let cells = 0;
|
|
7439
|
+
let utf16 = 0;
|
|
7440
|
+
for (const codePoint of body) {
|
|
7441
|
+
const widthInCells = cellWidth(codePoint);
|
|
7442
|
+
if (bodyColumn <= cells)
|
|
7443
|
+
return line.startUtf16 + utf16;
|
|
7444
|
+
utf16 += codePoint.length;
|
|
7445
|
+
cells += widthInCells;
|
|
7446
|
+
if (bodyColumn <= cells)
|
|
7447
|
+
return line.startUtf16 + utf16;
|
|
7448
|
+
}
|
|
7449
|
+
return line.endUtf16;
|
|
7450
|
+
};
|
|
7451
|
+
return { preambleRows: normalized.rows.length, totalRows, contentWidth, rowAt, window, displayOffsetsForLines, rawOffsetAt };
|
|
7452
|
+
}
|
|
7453
|
+
|
|
7454
|
+
// src/ui/panes/virtual-main-pane.ts
|
|
7455
|
+
var ACCESSORS = ["scrollY", "scrollHeight", "maxScrollY", "scrollX", "scrollWidth", "maxScrollX"];
|
|
7456
|
+
var virtualPanes = new WeakMap;
|
|
7457
|
+
var VIRTUAL_MAIN_OVERSCAN_MIN = 10;
|
|
7458
|
+
function prototypeDescriptor(text, name) {
|
|
7459
|
+
let prototype = Object.getPrototypeOf(text);
|
|
7460
|
+
while (prototype !== null) {
|
|
7461
|
+
const descriptor = Object.getOwnPropertyDescriptor(prototype, name);
|
|
7462
|
+
if (descriptor !== undefined)
|
|
7463
|
+
return descriptor;
|
|
7464
|
+
prototype = Object.getPrototypeOf(prototype);
|
|
7465
|
+
}
|
|
7466
|
+
return;
|
|
7467
|
+
}
|
|
7468
|
+
function isFiniteNonNegative(value) {
|
|
7469
|
+
return Number.isFinite(value) ? Math.max(0, value) : 0;
|
|
7470
|
+
}
|
|
7471
|
+
function documentSelection(document, startUtf16, endUtf16) {
|
|
7472
|
+
const line = document.lines.find((entry) => startUtf16 >= entry.startUtf16 && startUtf16 <= entry.endUtf16) ?? document.lines[0];
|
|
7473
|
+
return {
|
|
7474
|
+
valid: true,
|
|
7475
|
+
startUtf16,
|
|
7476
|
+
endUtf16,
|
|
7477
|
+
...line === undefined ? {} : {
|
|
7478
|
+
fileIndex: line.fileIndex,
|
|
7479
|
+
...line.hunkIndex === undefined ? {} : { hunkIndex: line.hunkIndex }
|
|
7480
|
+
},
|
|
7481
|
+
active: true
|
|
7482
|
+
};
|
|
7483
|
+
}
|
|
7484
|
+
function dimensions(text) {
|
|
7485
|
+
return {
|
|
7486
|
+
height: Math.max(1, Math.floor(isFiniteNonNegative(text.height))),
|
|
7487
|
+
width: Math.max(0, Math.floor(isFiniteNonNegative(text.width)))
|
|
7488
|
+
};
|
|
7489
|
+
}
|
|
7490
|
+
function padDisplayRow(value, width) {
|
|
7491
|
+
return `${value}${" ".repeat(Math.max(0, width - cellWidth(value)))}`;
|
|
7492
|
+
}
|
|
7493
|
+
function withoutLineEnding3(raw) {
|
|
7494
|
+
if (raw.endsWith(`\r
|
|
7495
|
+
`))
|
|
7496
|
+
return raw.slice(0, -2);
|
|
7497
|
+
if (raw.endsWith(`
|
|
7498
|
+
`) || raw.endsWith("\r"))
|
|
7499
|
+
return raw.slice(0, -1);
|
|
7500
|
+
return raw;
|
|
7501
|
+
}
|
|
7502
|
+
function rawDisplayCells(raw, relativeUtf16, includeLineEnding) {
|
|
7503
|
+
const body = withoutLineEnding3(raw);
|
|
7504
|
+
const prefixLength = Math.min(body.length, Math.max(0, Math.floor(relativeUtf16)));
|
|
7505
|
+
const cells = cellWidth(body.slice(0, prefixLength));
|
|
7506
|
+
return cells + (includeLineEnding && prefixLength >= body.length && body.length < raw.length ? 1 : 0);
|
|
7507
|
+
}
|
|
7508
|
+
function installAccessors(pane, state, rerender) {
|
|
7509
|
+
const text = pane.text;
|
|
7510
|
+
for (const name of ACCESSORS) {
|
|
7511
|
+
const descriptor = state.originalDescriptors.get(name);
|
|
7512
|
+
if (descriptor === undefined)
|
|
7513
|
+
continue;
|
|
7514
|
+
const nextDescriptor = {
|
|
7515
|
+
configurable: true,
|
|
7516
|
+
enumerable: descriptor.enumerable ?? false,
|
|
7517
|
+
get: () => {
|
|
7518
|
+
if (!state.active)
|
|
7519
|
+
return descriptor.get?.call(text);
|
|
7520
|
+
const layout = state.layout;
|
|
7521
|
+
if (name === "scrollY")
|
|
7522
|
+
return state.scrollY;
|
|
7523
|
+
if (name === "scrollX")
|
|
7524
|
+
return state.scrollX;
|
|
7525
|
+
if (name === "scrollHeight")
|
|
7526
|
+
return layout?.totalRows ?? descriptor.get?.call(text) ?? 0;
|
|
7527
|
+
if (name === "scrollWidth")
|
|
7528
|
+
return layout?.contentWidth ?? descriptor.get?.call(text) ?? 0;
|
|
7529
|
+
const viewport = name === "maxScrollY" ? state.viewportHeight : state.viewportWidth;
|
|
7530
|
+
const size = name === "maxScrollY" ? layout?.totalRows ?? 0 : layout?.contentWidth ?? 0;
|
|
7531
|
+
return Math.max(0, size - viewport);
|
|
7532
|
+
},
|
|
7533
|
+
...name === "scrollY" || name === "scrollX" ? {
|
|
7534
|
+
set: (value) => {
|
|
7535
|
+
if (!state.active) {
|
|
7536
|
+
descriptor.set?.call(text, value);
|
|
7537
|
+
return;
|
|
7538
|
+
}
|
|
7539
|
+
const numeric = typeof value === "number" ? value : Number(value);
|
|
7540
|
+
if (name === "scrollY") {
|
|
7541
|
+
const max = Math.max(0, (state.layout?.totalRows ?? 0) - state.viewportHeight);
|
|
7542
|
+
const next = Math.min(max, Math.floor(isFiniteNonNegative(numeric)));
|
|
7543
|
+
if (state.scrollY === next)
|
|
7544
|
+
return;
|
|
7545
|
+
state.scrollY = next;
|
|
7546
|
+
rerender();
|
|
7547
|
+
} else {
|
|
7548
|
+
const max = Math.max(0, (state.layout?.contentWidth ?? 0) - state.viewportWidth);
|
|
7549
|
+
const next = Math.min(max, Math.floor(isFiniteNonNegative(numeric)));
|
|
7550
|
+
state.scrollX = next;
|
|
7551
|
+
descriptor.set?.call(text, next);
|
|
7552
|
+
pane.text.requestRender();
|
|
7553
|
+
}
|
|
7554
|
+
}
|
|
7555
|
+
} : {}
|
|
7556
|
+
};
|
|
7557
|
+
Object.defineProperty(text, name, nextDescriptor);
|
|
7558
|
+
}
|
|
7559
|
+
}
|
|
7560
|
+
function createAdapter(pane) {
|
|
7561
|
+
const text = pane.text;
|
|
7562
|
+
const originalOwnDescriptors = new Map(ACCESSORS.map((name) => [name, Object.getOwnPropertyDescriptor(text, name)]));
|
|
7563
|
+
const originalDescriptors = new Map(ACCESSORS.map((name) => [name, Object.getOwnPropertyDescriptor(text, name) ?? prototypeDescriptor(text, name)]));
|
|
7564
|
+
const state = {
|
|
7565
|
+
active: false,
|
|
7566
|
+
document: undefined,
|
|
7567
|
+
layout: undefined,
|
|
7568
|
+
preamble: "",
|
|
7569
|
+
scrollY: 0,
|
|
7570
|
+
scrollX: 0,
|
|
7571
|
+
viewportHeight: Math.max(1, Math.floor(text.height)),
|
|
7572
|
+
viewportWidth: Math.max(0, Math.floor(text.width)),
|
|
7573
|
+
rawSelection: undefined,
|
|
7574
|
+
renderedWindow: undefined,
|
|
7575
|
+
preambleSpans: new Map,
|
|
7576
|
+
originalDescriptors,
|
|
7577
|
+
originalOwnDescriptors
|
|
7578
|
+
};
|
|
7579
|
+
const restoreAccessors = () => {
|
|
7580
|
+
const target = text;
|
|
7581
|
+
for (const name of ACCESSORS) {
|
|
7582
|
+
delete target[name];
|
|
7583
|
+
const own = state.originalOwnDescriptors.get(name);
|
|
7584
|
+
if (own !== undefined)
|
|
7585
|
+
Object.defineProperty(target, name, own);
|
|
7586
|
+
}
|
|
7587
|
+
};
|
|
7588
|
+
const visibleSelection = () => {
|
|
7589
|
+
const selection = state.rawSelection;
|
|
7590
|
+
const layout = state.layout;
|
|
7591
|
+
const window = state.renderedWindow;
|
|
7592
|
+
if (selection === undefined || layout === undefined || window === undefined)
|
|
7593
|
+
return;
|
|
7594
|
+
let start;
|
|
7595
|
+
let end;
|
|
7596
|
+
let localOffset = 0;
|
|
7597
|
+
for (let row = window[0];row <= window[1]; row += 1) {
|
|
7598
|
+
const current = layout.rowAt(row);
|
|
7599
|
+
if (current === undefined)
|
|
7600
|
+
continue;
|
|
7601
|
+
const rowStart = localOffset;
|
|
7602
|
+
localOffset += layout.contentWidth + (row < window[1] ? 1 : 0);
|
|
7603
|
+
if (current.lineIndex === undefined || current.rawStartUtf16 === undefined || current.rawEndUtf16 === undefined)
|
|
7604
|
+
continue;
|
|
7605
|
+
const line = state.document?.lines[current.lineIndex];
|
|
7606
|
+
if (line === undefined)
|
|
7607
|
+
continue;
|
|
7608
|
+
const overlapStart = Math.max(selection.startUtf16, current.rawStartUtf16);
|
|
7609
|
+
const overlapEnd = Math.min(selection.endUtf16, current.rawEndUtf16);
|
|
7610
|
+
if (overlapStart >= overlapEnd)
|
|
7611
|
+
continue;
|
|
7612
|
+
const displayStart = rowStart + (overlapStart === current.rawStartUtf16 ? 0 : current.gutterCols + rawDisplayCells(line.raw, overlapStart - current.rawStartUtf16, false));
|
|
7613
|
+
const displayEnd = rowStart + current.gutterCols + rawDisplayCells(line.raw, overlapEnd - current.rawStartUtf16, overlapEnd > current.rawStartUtf16 + withoutLineEnding3(line.raw).length);
|
|
7614
|
+
start = start === undefined ? displayStart : Math.min(start, displayStart);
|
|
7615
|
+
end = end === undefined ? displayEnd : Math.max(end, displayEnd);
|
|
7616
|
+
}
|
|
7617
|
+
return start === undefined || end === undefined ? undefined : { start, end };
|
|
7618
|
+
};
|
|
7619
|
+
const paintSelection = () => {
|
|
7620
|
+
const selected = visibleSelection();
|
|
7621
|
+
const surface = text;
|
|
7622
|
+
if (selected === undefined)
|
|
7623
|
+
surface.resetSelection?.();
|
|
7624
|
+
else
|
|
7625
|
+
surface.setSelection?.(selected.start, selected.end);
|
|
7626
|
+
};
|
|
7627
|
+
const renderWindow = () => {
|
|
7628
|
+
if (!state.active || state.layout === undefined)
|
|
7629
|
+
return;
|
|
7630
|
+
const current = dimensions(text);
|
|
7631
|
+
state.viewportHeight = current.height;
|
|
7632
|
+
state.viewportWidth = current.width;
|
|
7633
|
+
const max = Math.max(0, state.layout.totalRows - state.viewportHeight);
|
|
7634
|
+
if (state.scrollY > max)
|
|
7635
|
+
state.scrollY = max;
|
|
7636
|
+
const maxX = Math.max(0, state.layout.contentWidth - state.viewportWidth);
|
|
7637
|
+
if (state.scrollX > maxX)
|
|
7638
|
+
state.scrollX = maxX;
|
|
7639
|
+
const overscan = Math.max(VIRTUAL_MAIN_OVERSCAN_MIN, state.viewportHeight);
|
|
7640
|
+
const window = state.layout.window(state.scrollY, state.viewportHeight, overscan);
|
|
7641
|
+
const localScrollY = state.scrollY - window[0];
|
|
7642
|
+
state.renderedWindow = window;
|
|
7643
|
+
const rows = [];
|
|
7644
|
+
const displays = [];
|
|
7645
|
+
const preambleRows = [];
|
|
7646
|
+
const preambleSpans = new Map;
|
|
7647
|
+
const first = window[0];
|
|
7648
|
+
const last = window[1];
|
|
7649
|
+
if (last >= first && first < state.layout.preambleRows) {
|
|
7650
|
+
const preambleLast = Math.min(last, state.layout.preambleRows - 1);
|
|
7651
|
+
for (let row = first;row <= preambleLast; row += 1) {
|
|
7652
|
+
const value = state.layout.rowAt(row);
|
|
7653
|
+
if (value !== undefined)
|
|
7654
|
+
preambleRows.push(padDisplayRow(value.text, state.layout.contentWidth));
|
|
7655
|
+
const spans = state.preambleSpans.get(row);
|
|
7656
|
+
if (spans !== undefined)
|
|
7657
|
+
preambleSpans.set(row - first, spans);
|
|
7658
|
+
}
|
|
7659
|
+
}
|
|
7660
|
+
const bodyFirst = Math.max(first, state.layout.preambleRows);
|
|
7661
|
+
for (let row = bodyFirst;row <= last; row += 1) {
|
|
7662
|
+
const value = state.layout.rowAt(row);
|
|
7663
|
+
if (value === undefined || value.lineIndex === undefined)
|
|
7664
|
+
continue;
|
|
7665
|
+
rows.push(padDisplayRow(value.text, state.layout.contentWidth));
|
|
7666
|
+
displays.push({ gutterCols: value.gutterCols, style: value.style });
|
|
7667
|
+
}
|
|
7668
|
+
const preamble = preambleRows.length === 0 ? "" : `${preambleRows.join(`
|
|
7669
|
+
`)}
|
|
7670
|
+
`;
|
|
7671
|
+
installDiffText(text, { preamble, body: rows.join(`
|
|
7672
|
+
`), displayLines: displays, highlightScrollY: () => localScrollY, preambleSpans });
|
|
7673
|
+
const originalScrollY = state.originalDescriptors.get("scrollY")?.set;
|
|
7674
|
+
originalScrollY?.call(text, localScrollY);
|
|
7675
|
+
const originalScrollX = state.originalDescriptors.get("scrollX")?.set;
|
|
7676
|
+
originalScrollX?.call(text, state.scrollX);
|
|
7677
|
+
paintSelection();
|
|
7678
|
+
pane.syncScrollbar(state.viewportHeight);
|
|
7679
|
+
text.requestRender?.();
|
|
7680
|
+
};
|
|
7681
|
+
const rerender = () => renderWindow();
|
|
7682
|
+
const adapter = {
|
|
7683
|
+
install(document, preamble) {
|
|
7684
|
+
if (!state.active) {
|
|
7685
|
+
state.scrollY = isFiniteNonNegative(Number(text.scrollY));
|
|
7686
|
+
state.scrollX = isFiniteNonNegative(Number(text.scrollX));
|
|
7687
|
+
}
|
|
7688
|
+
state.active = true;
|
|
7689
|
+
state.document = document;
|
|
7690
|
+
state.layout = createVirtualDiffLayout(document, preamble);
|
|
7691
|
+
state.preamble = preamble;
|
|
7692
|
+
state.preambleSpans = statSpansForPreamble(preamble);
|
|
7693
|
+
const current = dimensions(text);
|
|
7694
|
+
state.viewportHeight = current.height;
|
|
7695
|
+
state.viewportWidth = current.width;
|
|
7696
|
+
installAccessors(pane, state, rerender);
|
|
7697
|
+
text.wrapMode = "none";
|
|
7698
|
+
renderWindow();
|
|
7699
|
+
},
|
|
7700
|
+
deactivate() {
|
|
7701
|
+
if (!state.active)
|
|
7702
|
+
return;
|
|
7703
|
+
const originalY = state.originalDescriptors.get("scrollY")?.set;
|
|
7704
|
+
const originalX = state.originalDescriptors.get("scrollX")?.set;
|
|
7705
|
+
originalY?.call(text, state.scrollY);
|
|
7706
|
+
originalX?.call(text, state.scrollX);
|
|
7707
|
+
state.active = false;
|
|
7708
|
+
state.document = undefined;
|
|
7709
|
+
state.layout = undefined;
|
|
7710
|
+
state.rawSelection = undefined;
|
|
7711
|
+
state.renderedWindow = undefined;
|
|
7712
|
+
releaseDiffText(text);
|
|
7713
|
+
state.preambleSpans = new Map;
|
|
7714
|
+
restoreAccessors();
|
|
7715
|
+
clearScrollbarViewportOverride(text);
|
|
7716
|
+
text.wrapMode = "char";
|
|
7717
|
+
},
|
|
7718
|
+
isActive: () => state.active,
|
|
7719
|
+
layout: () => state.layout,
|
|
7720
|
+
lineOffsets: (startIndex, endIndex) => state.layout?.displayOffsetsForLines(startIndex, endIndex),
|
|
7721
|
+
visualRowRange: (startIndex, endIndex) => {
|
|
7722
|
+
if (state.layout === undefined)
|
|
7723
|
+
return;
|
|
7724
|
+
const start = state.layout.preambleRows + Math.max(0, startIndex);
|
|
7725
|
+
const end = state.layout.preambleRows + Math.max(startIndex, endIndex);
|
|
7726
|
+
return { startRow: start, endRow: end };
|
|
7727
|
+
},
|
|
7728
|
+
setLineSelection(startUtf16, endUtf16) {
|
|
7729
|
+
if (!state.active || state.document === undefined)
|
|
7730
|
+
return;
|
|
7731
|
+
state.rawSelection = documentSelection(state.document, startUtf16, endUtf16);
|
|
7732
|
+
paintSelection();
|
|
7733
|
+
},
|
|
7734
|
+
setPointerSelection(startRow, startColumn, endRow, endColumn) {
|
|
7735
|
+
if (!state.active || state.layout === undefined || state.document === undefined)
|
|
7736
|
+
return;
|
|
7737
|
+
const start = state.layout.rawOffsetAt(Math.max(0, Math.floor(state.scrollY + startRow)), Math.max(0, Math.floor(state.scrollX + startColumn)));
|
|
7738
|
+
const end = state.layout.rawOffsetAt(Math.max(0, Math.floor(state.scrollY + endRow)), Math.max(0, Math.floor(state.scrollX + endColumn)));
|
|
7739
|
+
if (start === undefined || end === undefined) {
|
|
7740
|
+
state.rawSelection = undefined;
|
|
7741
|
+
paintSelection();
|
|
7742
|
+
return;
|
|
7743
|
+
}
|
|
7744
|
+
const selection = documentSelection(state.document, Math.min(start, end), Math.max(start, end));
|
|
7745
|
+
state.rawSelection = selection;
|
|
7746
|
+
paintSelection();
|
|
7747
|
+
return selection;
|
|
7748
|
+
},
|
|
7749
|
+
selection: () => state.rawSelection,
|
|
7750
|
+
resetSelection() {
|
|
7751
|
+
state.rawSelection = undefined;
|
|
7752
|
+
text.resetSelection?.();
|
|
7753
|
+
},
|
|
7754
|
+
clampScroll() {
|
|
7755
|
+
if (!state.active || state.layout === undefined) {
|
|
7756
|
+
const originalY = state.originalDescriptors.get("scrollY")?.set;
|
|
7757
|
+
const originalX = state.originalDescriptors.get("scrollX")?.set;
|
|
7758
|
+
originalY?.call(text, text.scrollY);
|
|
7759
|
+
originalX?.call(text, text.scrollX);
|
|
7760
|
+
return;
|
|
7761
|
+
}
|
|
7762
|
+
const maxY = Math.max(0, state.layout.totalRows - state.viewportHeight);
|
|
7763
|
+
const maxX = Math.max(0, state.layout.contentWidth - state.viewportWidth);
|
|
7764
|
+
state.scrollY = Math.min(maxY, Math.max(0, state.scrollY));
|
|
7765
|
+
state.scrollX = Math.min(maxX, Math.max(0, state.scrollX));
|
|
7766
|
+
renderWindow();
|
|
7767
|
+
}
|
|
7768
|
+
};
|
|
7769
|
+
onPaneLifecyclePass(text, () => {
|
|
7770
|
+
if (!state.active || state.layout === undefined)
|
|
7771
|
+
return;
|
|
7772
|
+
const current = dimensions(text);
|
|
7773
|
+
if (current.height !== state.viewportHeight || current.width !== state.viewportWidth)
|
|
7774
|
+
renderWindow();
|
|
7775
|
+
});
|
|
7776
|
+
return adapter;
|
|
7777
|
+
}
|
|
7778
|
+
function createVirtualMainPane(pane) {
|
|
7779
|
+
const existing = virtualPanes.get(pane);
|
|
7780
|
+
if (existing !== undefined)
|
|
7781
|
+
return existing;
|
|
7782
|
+
const adapter = createAdapter(pane);
|
|
7783
|
+
virtualPanes.set(pane, adapter);
|
|
7784
|
+
return adapter;
|
|
7785
|
+
}
|
|
7786
|
+
function virtualMainPaneFor(pane) {
|
|
7787
|
+
return virtualPanes.get(pane);
|
|
7788
|
+
}
|
|
7789
|
+
function isVirtualDiffDocument(document) {
|
|
7790
|
+
return document.lines.length > VIRTUAL_DIFF_LINE_THRESHOLD;
|
|
7040
7791
|
}
|
|
7041
7792
|
|
|
7042
7793
|
// src/ui/panes/main-pane.ts
|
|
@@ -7071,6 +7822,7 @@ function createMainPane(renderer, _model) {
|
|
|
7071
7822
|
const pane = createPane(renderer, "main", "0 Main", "", true);
|
|
7072
7823
|
pane.text.selectionBg = SELECTED_LINE_BG;
|
|
7073
7824
|
ensureMainTextSelectionSurface(pane);
|
|
7825
|
+
createVirtualMainPane(pane);
|
|
7074
7826
|
pane.box.title = "0 Main";
|
|
7075
7827
|
paneTitles.set(pane, "0 Main");
|
|
7076
7828
|
return pane;
|
|
@@ -7119,6 +7871,9 @@ function mainDiffVisualRowRange(pane, startIndex, endIndex) {
|
|
|
7119
7871
|
const document = documents.get(pane);
|
|
7120
7872
|
if (document === undefined)
|
|
7121
7873
|
return;
|
|
7874
|
+
const virtual = virtualMainPaneFor(pane);
|
|
7875
|
+
if (virtual?.isActive())
|
|
7876
|
+
return virtual.visualRowRange(startIndex, endIndex);
|
|
7122
7877
|
const content = installedContents.get(pane);
|
|
7123
7878
|
const preambleRows = (normalizedPreamble(content?.preamble ?? "").match(/\n/g) ?? []).length;
|
|
7124
7879
|
const firstSource = preambleRows + Math.max(0, startIndex);
|
|
@@ -7143,7 +7898,16 @@ function getMainDiffLineSelection(pane) {
|
|
|
7143
7898
|
if (document === undefined || state === undefined || state.rangeMode === "none")
|
|
7144
7899
|
return;
|
|
7145
7900
|
const range = diffLineSelectionRange(state);
|
|
7146
|
-
const
|
|
7901
|
+
const virtual = virtualMainPaneFor(pane);
|
|
7902
|
+
const offsets = virtual?.isActive() ? (() => {
|
|
7903
|
+
const value = virtual.lineOffsets(range.startIndex, range.endIndex + 1);
|
|
7904
|
+
return value === undefined ? undefined : {
|
|
7905
|
+
startUtf16: value.rawStartUtf16,
|
|
7906
|
+
endUtf16: value.rawEndUtf16,
|
|
7907
|
+
displayStartUtf16: value.displayStartUtf16,
|
|
7908
|
+
displayEndUtf16: value.displayEndUtf16
|
|
7909
|
+
};
|
|
7910
|
+
})() : mainDiffLineOffsets(document, range.startIndex, range.endIndex, installedContents.get(pane)?.preamble ?? "");
|
|
7147
7911
|
if (offsets === undefined)
|
|
7148
7912
|
return;
|
|
7149
7913
|
return {
|
|
@@ -7154,16 +7918,42 @@ function getMainDiffLineSelection(pane) {
|
|
|
7154
7918
|
};
|
|
7155
7919
|
}
|
|
7156
7920
|
function applyMainDiffLineVisualSelection(pane, resetWhenInactive = true) {
|
|
7157
|
-
const
|
|
7921
|
+
const virtual = virtualMainPaneFor(pane);
|
|
7158
7922
|
const selection = getMainDiffLineSelection(pane);
|
|
7159
|
-
if (
|
|
7923
|
+
if (virtual?.isActive()) {
|
|
7924
|
+
if (selection !== undefined)
|
|
7925
|
+
virtual.setLineSelection(selection.startUtf16, selection.endUtf16);
|
|
7926
|
+
else if (resetWhenInactive)
|
|
7927
|
+
virtual.resetSelection();
|
|
7928
|
+
return;
|
|
7929
|
+
}
|
|
7930
|
+
const text = pane.text;
|
|
7931
|
+
if (selection !== undefined)
|
|
7160
7932
|
text.setSelection?.(selection.displayStartUtf16, selection.displayEndUtf16);
|
|
7161
|
-
|
|
7933
|
+
else if (resetWhenInactive)
|
|
7162
7934
|
text.resetSelection?.();
|
|
7163
|
-
|
|
7935
|
+
}
|
|
7936
|
+
function getMainPointerSelection(pane) {
|
|
7937
|
+
return virtualMainPaneFor(pane)?.selection();
|
|
7164
7938
|
}
|
|
7165
7939
|
function setMainDiffLineRangeState(pane, state) {
|
|
7166
7940
|
lineRanges.set(pane, state);
|
|
7941
|
+
const virtual = virtualMainPaneFor(pane);
|
|
7942
|
+
if (state.rangeMode === "none") {
|
|
7943
|
+
if (virtual?.isActive())
|
|
7944
|
+
virtual.resetSelection();
|
|
7945
|
+
else
|
|
7946
|
+
applyMainDiffLineVisualSelection(pane);
|
|
7947
|
+
return;
|
|
7948
|
+
}
|
|
7949
|
+
const document = documents.get(pane);
|
|
7950
|
+
const range = diffLineSelectionRange(state);
|
|
7951
|
+
const start = document?.lines[range.startIndex];
|
|
7952
|
+
const end = document?.lines[range.endIndex];
|
|
7953
|
+
if (virtual?.isActive() && start !== undefined && end !== undefined) {
|
|
7954
|
+
virtual.setLineSelection(start.startUtf16, end.endUtf16);
|
|
7955
|
+
return;
|
|
7956
|
+
}
|
|
7167
7957
|
applyMainDiffLineVisualSelection(pane);
|
|
7168
7958
|
}
|
|
7169
7959
|
function getMainDocument(pane) {
|
|
@@ -7243,11 +8033,17 @@ function buildPlainContent(content) {
|
|
|
7243
8033
|
return "No content";
|
|
7244
8034
|
}
|
|
7245
8035
|
function clampMainScroll(pane) {
|
|
8036
|
+
const virtual = virtualMainPaneFor(pane);
|
|
8037
|
+
if (virtual?.isActive()) {
|
|
8038
|
+
virtual.clampScroll();
|
|
8039
|
+
return;
|
|
8040
|
+
}
|
|
7246
8041
|
pane.text.scrollY = Math.max(0, Math.min(pane.text.maxScrollY, pane.text.scrollY));
|
|
7247
8042
|
pane.text.scrollX = Math.max(0, Math.min(pane.text.maxScrollX, pane.text.scrollX));
|
|
7248
8043
|
pane.syncScrollbar();
|
|
7249
8044
|
}
|
|
7250
8045
|
function updatePlain(pane, value) {
|
|
8046
|
+
virtualMainPaneFor(pane)?.deactivate();
|
|
7251
8047
|
releaseDiffText(pane.text);
|
|
7252
8048
|
releaseAnsiText(pane.text);
|
|
7253
8049
|
pane.update(value);
|
|
@@ -7255,20 +8051,25 @@ function updatePlain(pane, value) {
|
|
|
7255
8051
|
function installMainContent(pane, content, tooSmall) {
|
|
7256
8052
|
const previousContent = installedContents.get(pane);
|
|
7257
8053
|
const previousText = renderedTexts.get(pane);
|
|
7258
|
-
const
|
|
8054
|
+
const virtualDocument = content.document !== undefined && isVirtualDiffDocument(content.document);
|
|
8055
|
+
const nextText = virtualDocument ? undefined : renderedTextFor(content);
|
|
7259
8056
|
const previousIdentity = previousContent === undefined ? undefined : `${previousContent.source}:${previousContent.stableId}`;
|
|
7260
8057
|
const nextIdentity = `${content.source}:${content.stableId}`;
|
|
7261
8058
|
const sameIdentity = previousIdentity !== undefined && previousIdentity === nextIdentity;
|
|
7262
|
-
const identicalText = previousText !== undefined && previousText === nextText;
|
|
8059
|
+
const identicalText = virtualDocument ? previousContent?.document?.text === content.document?.text && previousContent?.preamble === content.preamble : previousText !== undefined && previousText === nextText;
|
|
7263
8060
|
const previousWasDocument = documents.has(pane);
|
|
7264
8061
|
const replacingDocument = previousWasDocument && content.document === undefined;
|
|
7265
8062
|
const enteringDocument = !previousWasDocument && content.document !== undefined;
|
|
7266
8063
|
const leavingAnsi = previousContent?.ansi !== undefined && content.ansi === undefined;
|
|
7267
8064
|
installedContents.set(pane, content);
|
|
7268
|
-
|
|
8065
|
+
if (nextText === undefined)
|
|
8066
|
+
renderedTexts.delete(pane);
|
|
8067
|
+
else
|
|
8068
|
+
renderedTexts.set(pane, nextText);
|
|
7269
8069
|
paneTitles.set(pane, `0 Main — ${content.label}`);
|
|
7270
8070
|
const previousRange = lineRanges.get(pane);
|
|
7271
8071
|
const clearSelection = () => {
|
|
8072
|
+
virtualMainPaneFor(pane)?.resetSelection();
|
|
7272
8073
|
const view = pane.text;
|
|
7273
8074
|
if (view !== null && typeof view === "object" && "resetSelection" in view) {
|
|
7274
8075
|
const reset = view.resetSelection;
|
|
@@ -7339,6 +8140,16 @@ function installMainContent(pane, content, tooSmall) {
|
|
|
7339
8140
|
} else {
|
|
7340
8141
|
cursorTargets.delete(pane);
|
|
7341
8142
|
}
|
|
8143
|
+
const virtual = virtualMainPaneFor(pane);
|
|
8144
|
+
if (virtualDocument && virtual !== undefined) {
|
|
8145
|
+
releaseAnsiText(pane.text);
|
|
8146
|
+
virtual.install(doc, content.preamble ?? "");
|
|
8147
|
+
renderedTexts.delete(pane);
|
|
8148
|
+
if (previousRange?.rangeMode !== "none")
|
|
8149
|
+
applyMainDiffLineVisualSelection(pane);
|
|
8150
|
+
return;
|
|
8151
|
+
}
|
|
8152
|
+
virtual?.deactivate();
|
|
7342
8153
|
pane.text.wrapMode = "char";
|
|
7343
8154
|
releaseAnsiText(pane.text);
|
|
7344
8155
|
if (enteringDocument || !sameIdentity || !identicalText) {
|
|
@@ -7353,6 +8164,7 @@ function installMainContent(pane, content, tooSmall) {
|
|
|
7353
8164
|
return;
|
|
7354
8165
|
}
|
|
7355
8166
|
if (content.ansi !== undefined) {
|
|
8167
|
+
virtualMainPaneFor(pane)?.deactivate();
|
|
7356
8168
|
documents.delete(pane);
|
|
7357
8169
|
if (replacingDocument || !sameIdentity || !identicalText)
|
|
7358
8170
|
clearSelection();
|
|
@@ -7364,6 +8176,7 @@ function installMainContent(pane, content, tooSmall) {
|
|
|
7364
8176
|
pane.syncScrollbar();
|
|
7365
8177
|
return;
|
|
7366
8178
|
}
|
|
8179
|
+
virtualMainPaneFor(pane)?.deactivate();
|
|
7367
8180
|
documents.delete(pane);
|
|
7368
8181
|
if (replacingDocument || leavingAnsi || !sameIdentity || !identicalText)
|
|
7369
8182
|
clearSelection();
|
|
@@ -7415,8 +8228,7 @@ function createStashPane(renderer, model) {
|
|
|
7415
8228
|
const rows = stashRows(model);
|
|
7416
8229
|
const displayRows = stashDisplayRows(model, rows);
|
|
7417
8230
|
const state = createListState(rows, displayRows);
|
|
7418
|
-
|
|
7419
|
-
pane.update(content);
|
|
8231
|
+
installListText(pane.text, { state, width: 80, focused: false });
|
|
7420
8232
|
return pane;
|
|
7421
8233
|
}
|
|
7422
8234
|
function selectedStashEntryFromState(state, model) {
|
|
@@ -9336,6 +10148,7 @@ class RootView {
|
|
|
9336
10148
|
lastSplitterPress;
|
|
9337
10149
|
activeSplitterDrag;
|
|
9338
10150
|
gestureOwner;
|
|
10151
|
+
mainPointerAnchor;
|
|
9339
10152
|
pendingClick;
|
|
9340
10153
|
hoveredListRow;
|
|
9341
10154
|
model;
|
|
@@ -9624,6 +10437,10 @@ class RootView {
|
|
|
9624
10437
|
this.syncPreviewForFocus(focus);
|
|
9625
10438
|
};
|
|
9626
10439
|
this.handleResize = () => {
|
|
10440
|
+
if (this.gestureOwner?.kind === "main-selection") {
|
|
10441
|
+
virtualMainPaneFor(this.panes.main)?.resetSelection();
|
|
10442
|
+
this.cancelGesture();
|
|
10443
|
+
}
|
|
9627
10444
|
this.recomputeLayout();
|
|
9628
10445
|
};
|
|
9629
10446
|
this.handleKey = (key) => {
|
|
@@ -9672,6 +10489,10 @@ class RootView {
|
|
|
9672
10489
|
this.applyLayout();
|
|
9673
10490
|
}
|
|
9674
10491
|
update(model, options = {}) {
|
|
10492
|
+
if (this.gestureOwner?.kind === "main-selection") {
|
|
10493
|
+
virtualMainPaneFor(this.panes.main)?.resetSelection();
|
|
10494
|
+
this.cancelGesture();
|
|
10495
|
+
}
|
|
9675
10496
|
this.branchActionGeneration += 1;
|
|
9676
10497
|
this.invalidateBranchCommitsRequest();
|
|
9677
10498
|
if (!options.preserveRemoteCheckout) {
|
|
@@ -9902,7 +10723,11 @@ class RootView {
|
|
|
9902
10723
|
};
|
|
9903
10724
|
}
|
|
9904
10725
|
cancelGesture() {
|
|
10726
|
+
if (this.gestureOwner?.kind === "main-selection") {
|
|
10727
|
+
virtualMainPaneFor(this.panes.main)?.resetSelection();
|
|
10728
|
+
}
|
|
9905
10729
|
this.gestureOwner = undefined;
|
|
10730
|
+
this.mainPointerAnchor = undefined;
|
|
9906
10731
|
this.activeSplitterDrag = undefined;
|
|
9907
10732
|
}
|
|
9908
10733
|
get activeBranchesTab() {
|
|
@@ -10201,14 +11026,15 @@ class RootView {
|
|
|
10201
11026
|
const focused = this.focusManager.active === "branches";
|
|
10202
11027
|
const activeView = this.activeListView("branches");
|
|
10203
11028
|
if (activeView === undefined) {
|
|
11029
|
+
releaseListText(pane.text);
|
|
10204
11030
|
pane.update("");
|
|
10205
11031
|
return;
|
|
10206
11032
|
}
|
|
10207
11033
|
const { state } = activeView;
|
|
10208
11034
|
const win = this.geometry.windows.branches;
|
|
10209
11035
|
const width = sidePaneListWidth(win, state);
|
|
10210
|
-
const
|
|
10211
|
-
pane.
|
|
11036
|
+
const hoveredId = this.hoveredIdFor(activeView);
|
|
11037
|
+
installListText(pane.text, { state, width, focused, ...hoveredId === undefined ? {} : { hoveredId } });
|
|
10212
11038
|
pane.syncScrollbar(sidePaneViewportHeight(win));
|
|
10213
11039
|
}
|
|
10214
11040
|
get filesTitleStyled() {
|
|
@@ -10268,13 +11094,15 @@ class RootView {
|
|
|
10268
11094
|
pane.setTabs?.({ tabs: tabsInput.tabs, activeIndex: tabsInput.activeIndex, focused: tabsInput.focused });
|
|
10269
11095
|
const activeView = this.activeListView("files");
|
|
10270
11096
|
if (activeView === undefined) {
|
|
11097
|
+
releaseListText(pane.text);
|
|
10271
11098
|
pane.update("");
|
|
10272
11099
|
return;
|
|
10273
11100
|
}
|
|
10274
11101
|
const { state } = activeView;
|
|
10275
11102
|
const win = this.geometry.windows.files;
|
|
10276
11103
|
const width = sidePaneListWidth(win, state);
|
|
10277
|
-
|
|
11104
|
+
const hoveredId = this.hoveredIdFor(activeView);
|
|
11105
|
+
installListText(pane.text, { state, width, focused: tabsInput.focused, ...hoveredId === undefined ? {} : { hoveredId } });
|
|
10278
11106
|
pane.syncScrollbar(sidePaneViewportHeight(win));
|
|
10279
11107
|
}
|
|
10280
11108
|
refreshStashState(model) {
|
|
@@ -10288,6 +11116,7 @@ class RootView {
|
|
|
10288
11116
|
const pane = this.panes.stash;
|
|
10289
11117
|
const activeView = this.activeListView("stash");
|
|
10290
11118
|
if (activeView === undefined) {
|
|
11119
|
+
releaseListText(pane.text);
|
|
10291
11120
|
pane.update("");
|
|
10292
11121
|
return;
|
|
10293
11122
|
}
|
|
@@ -10295,8 +11124,8 @@ class RootView {
|
|
|
10295
11124
|
const focused = this.focusManager.active === "stash";
|
|
10296
11125
|
const win = this.geometry.windows.stash;
|
|
10297
11126
|
const width = sidePaneListWidth(win, state);
|
|
10298
|
-
const
|
|
10299
|
-
pane.
|
|
11127
|
+
const hoveredId = this.hoveredIdFor(activeView);
|
|
11128
|
+
installListText(pane.text, { state, width, focused, ...hoveredId === undefined ? {} : { hoveredId } });
|
|
10300
11129
|
pane.syncScrollbar(sidePaneViewportHeight(win));
|
|
10301
11130
|
}
|
|
10302
11131
|
renderSidePanes() {
|
|
@@ -10945,8 +11774,8 @@ class RootView {
|
|
|
10945
11774
|
}
|
|
10946
11775
|
focusedPageStep() {
|
|
10947
11776
|
const focus = this.focusManager.active;
|
|
10948
|
-
const
|
|
10949
|
-
return Math.max(1, heightOf(
|
|
11777
|
+
const dimensions2 = focus === "command-log" ? this.geometry.windows.log : this.geometry.windows[focus] ?? this.geometry.windows.main;
|
|
11778
|
+
return Math.max(1, heightOf(dimensions2) - 2);
|
|
10950
11779
|
}
|
|
10951
11780
|
actionPage(direction) {
|
|
10952
11781
|
if (this.focusManager.active === "main") {
|
|
@@ -12352,7 +13181,7 @@ class RootView {
|
|
|
12352
13181
|
let next = -1;
|
|
12353
13182
|
for (let i = current + 1;i < view.rows.length; i++) {
|
|
12354
13183
|
const row = view.rows[i];
|
|
12355
|
-
const text = `${row.columns[0]?.text ?? ""} ${row.columns[
|
|
13184
|
+
const text = `${row.columns[0]?.text ?? ""} ${row.columns[2]?.text ?? ""}`.toLowerCase();
|
|
12356
13185
|
if (text.includes(normalizedQuery)) {
|
|
12357
13186
|
next = i;
|
|
12358
13187
|
break;
|
|
@@ -12361,7 +13190,7 @@ class RootView {
|
|
|
12361
13190
|
if (next === -1) {
|
|
12362
13191
|
for (let i = 0;i <= current; i++) {
|
|
12363
13192
|
const row = view.rows[i];
|
|
12364
|
-
const text = `${row.columns[0]?.text ?? ""} ${row.columns[
|
|
13193
|
+
const text = `${row.columns[0]?.text ?? ""} ${row.columns[2]?.text ?? ""}`.toLowerCase();
|
|
12365
13194
|
if (text.includes(normalizedQuery)) {
|
|
12366
13195
|
next = i;
|
|
12367
13196
|
break;
|
|
@@ -12387,11 +13216,44 @@ class RootView {
|
|
|
12387
13216
|
const query = this.getFilterForKey(this.filterKey("main"));
|
|
12388
13217
|
if (query.length === 0)
|
|
12389
13218
|
return;
|
|
12390
|
-
const
|
|
13219
|
+
const document = getMainDocument(this.panes.main);
|
|
13220
|
+
const virtual = virtualMainPaneFor(this.panes.main);
|
|
13221
|
+
const normalizedQuery = query.toLowerCase();
|
|
13222
|
+
if (document !== undefined && virtual?.isActive()) {
|
|
13223
|
+
const layout = virtual.layout();
|
|
13224
|
+
const preambleRows = layout?.preambleRows ?? 0;
|
|
13225
|
+
const totalRows = layout?.totalRows ?? preambleRows + document.lines.length;
|
|
13226
|
+
const currentLine2 = this.panes.main.text.scrollY - preambleRows;
|
|
13227
|
+
let nextLine2 = -1;
|
|
13228
|
+
const firstCandidate = Math.max(0, currentLine2 + 1);
|
|
13229
|
+
for (let i = firstCandidate;i < document.lines.length; i += 1) {
|
|
13230
|
+
if (document.lines[i].raw.toLowerCase().includes(normalizedQuery)) {
|
|
13231
|
+
nextLine2 = i;
|
|
13232
|
+
break;
|
|
13233
|
+
}
|
|
13234
|
+
}
|
|
13235
|
+
if (nextLine2 === -1) {
|
|
13236
|
+
for (let i = 0;i <= currentLine2 && i < document.lines.length; i += 1) {
|
|
13237
|
+
if (document.lines[i].raw.toLowerCase().includes(normalizedQuery)) {
|
|
13238
|
+
nextLine2 = i;
|
|
13239
|
+
break;
|
|
13240
|
+
}
|
|
13241
|
+
}
|
|
13242
|
+
}
|
|
13243
|
+
if (nextLine2 !== -1) {
|
|
13244
|
+
this.clearNonStickyMainRange();
|
|
13245
|
+
const targetRow = preambleRows + nextLine2;
|
|
13246
|
+
this.panes.main.text.scrollY = Math.max(0, targetRow - 2);
|
|
13247
|
+
this.panes.main.syncScrollbar();
|
|
13248
|
+
this.panes.main.box.bottomTitle = `Search: ${query} (${targetRow + 1}/${totalRows})`;
|
|
13249
|
+
this.root.requestRender();
|
|
13250
|
+
}
|
|
13251
|
+
return;
|
|
13252
|
+
}
|
|
13253
|
+
const text = getMainRenderedText(this.panes.main) ?? document?.text ?? "";
|
|
12391
13254
|
if (text.length === 0)
|
|
12392
13255
|
return;
|
|
12393
13256
|
const normalizedText = text.toLowerCase();
|
|
12394
|
-
const normalizedQuery = query.toLowerCase();
|
|
12395
13257
|
const currentY = this.panes.main.text.scrollY;
|
|
12396
13258
|
const lines = text.split(`
|
|
12397
13259
|
`);
|
|
@@ -12415,6 +13277,7 @@ class RootView {
|
|
|
12415
13277
|
this.clearNonStickyMainRange();
|
|
12416
13278
|
const targetY = Math.max(0, nextLine - 2);
|
|
12417
13279
|
this.panes.main.text.scrollY = targetY;
|
|
13280
|
+
this.panes.main.syncScrollbar();
|
|
12418
13281
|
this.panes.main.box.bottomTitle = `Search: ${query} (${nextLine + 1}/${lines.length})`;
|
|
12419
13282
|
this.root.requestRender();
|
|
12420
13283
|
}
|
|
@@ -12435,7 +13298,7 @@ class RootView {
|
|
|
12435
13298
|
let prev = -1;
|
|
12436
13299
|
for (let i = current - 1;i >= 0; i--) {
|
|
12437
13300
|
const row = view.rows[i];
|
|
12438
|
-
const text = `${row.columns[0]?.text ?? ""} ${row.columns[
|
|
13301
|
+
const text = `${row.columns[0]?.text ?? ""} ${row.columns[2]?.text ?? ""}`.toLowerCase();
|
|
12439
13302
|
if (text.includes(normalizedQuery)) {
|
|
12440
13303
|
prev = i;
|
|
12441
13304
|
break;
|
|
@@ -12444,7 +13307,7 @@ class RootView {
|
|
|
12444
13307
|
if (prev === -1) {
|
|
12445
13308
|
for (let i = view.rows.length - 1;i >= current; i--) {
|
|
12446
13309
|
const row = view.rows[i];
|
|
12447
|
-
const text = `${row.columns[0]?.text ?? ""} ${row.columns[
|
|
13310
|
+
const text = `${row.columns[0]?.text ?? ""} ${row.columns[2]?.text ?? ""}`.toLowerCase();
|
|
12448
13311
|
if (text.includes(normalizedQuery)) {
|
|
12449
13312
|
prev = i;
|
|
12450
13313
|
break;
|
|
@@ -12470,13 +13333,45 @@ class RootView {
|
|
|
12470
13333
|
const query = this.getFilterForKey(this.filterKey("main"));
|
|
12471
13334
|
if (query.length === 0)
|
|
12472
13335
|
return;
|
|
12473
|
-
const
|
|
13336
|
+
const document = getMainDocument(this.panes.main);
|
|
13337
|
+
const virtual = virtualMainPaneFor(this.panes.main);
|
|
13338
|
+
const normalizedQuery = query.toLowerCase();
|
|
13339
|
+
if (document !== undefined && virtual?.isActive()) {
|
|
13340
|
+
const layout = virtual.layout();
|
|
13341
|
+
const preambleRows = layout?.preambleRows ?? 0;
|
|
13342
|
+
const totalRows = layout?.totalRows ?? preambleRows + document.lines.length;
|
|
13343
|
+
const currentLine = this.panes.main.text.scrollY - preambleRows;
|
|
13344
|
+
let previousLine = -1;
|
|
13345
|
+
for (let i = Math.min(document.lines.length - 1, currentLine - 1);i >= 0; i -= 1) {
|
|
13346
|
+
if (document.lines[i].raw.toLowerCase().includes(normalizedQuery)) {
|
|
13347
|
+
previousLine = i;
|
|
13348
|
+
break;
|
|
13349
|
+
}
|
|
13350
|
+
}
|
|
13351
|
+
if (previousLine === -1) {
|
|
13352
|
+
for (let i = document.lines.length - 1;i >= currentLine && i >= 0; i -= 1) {
|
|
13353
|
+
if (document.lines[i].raw.toLowerCase().includes(normalizedQuery)) {
|
|
13354
|
+
previousLine = i;
|
|
13355
|
+
break;
|
|
13356
|
+
}
|
|
13357
|
+
}
|
|
13358
|
+
}
|
|
13359
|
+
if (previousLine !== -1) {
|
|
13360
|
+
this.clearNonStickyMainRange();
|
|
13361
|
+
const targetRow = preambleRows + previousLine;
|
|
13362
|
+
this.panes.main.text.scrollY = Math.max(0, targetRow - 2);
|
|
13363
|
+
this.panes.main.syncScrollbar();
|
|
13364
|
+
this.panes.main.box.bottomTitle = `Search: ${query} (${targetRow + 1}/${totalRows})`;
|
|
13365
|
+
this.root.requestRender();
|
|
13366
|
+
}
|
|
13367
|
+
return;
|
|
13368
|
+
}
|
|
13369
|
+
const text = getMainRenderedText(this.panes.main) ?? document?.text ?? "";
|
|
12474
13370
|
if (text.length === 0)
|
|
12475
13371
|
return;
|
|
12476
13372
|
const lines = text.split(`
|
|
12477
13373
|
`);
|
|
12478
13374
|
const currentY = this.panes.main.text.scrollY;
|
|
12479
|
-
const normalizedQuery = query.toLowerCase();
|
|
12480
13375
|
let prevLine = -1;
|
|
12481
13376
|
for (let i = currentY - 1;i >= 0; i--) {
|
|
12482
13377
|
if (lines[i].toLowerCase().includes(normalizedQuery)) {
|
|
@@ -12496,6 +13391,7 @@ class RootView {
|
|
|
12496
13391
|
this.clearNonStickyMainRange();
|
|
12497
13392
|
const targetY = Math.max(0, prevLine - 2);
|
|
12498
13393
|
this.panes.main.text.scrollY = targetY;
|
|
13394
|
+
this.panes.main.syncScrollbar();
|
|
12499
13395
|
this.panes.main.box.bottomTitle = `Search: ${query} (${prevLine + 1}/${lines.length})`;
|
|
12500
13396
|
this.root.requestRender();
|
|
12501
13397
|
}
|
|
@@ -12530,6 +13426,13 @@ class RootView {
|
|
|
12530
13426
|
return [...paths];
|
|
12531
13427
|
}
|
|
12532
13428
|
mainActionTarget(document) {
|
|
13429
|
+
const pointer = getMainPointerSelection(this.panes.main);
|
|
13430
|
+
if (pointer?.fileIndex !== undefined && pointer.valid && pointer.endUtf16 > pointer.startUtf16) {
|
|
13431
|
+
return {
|
|
13432
|
+
fileIndex: pointer.fileIndex,
|
|
13433
|
+
...pointer.hunkIndex === undefined ? {} : { hunkIndex: pointer.hunkIndex }
|
|
13434
|
+
};
|
|
13435
|
+
}
|
|
12533
13436
|
const selected = getMainDiffLineSelection(this.panes.main);
|
|
12534
13437
|
const firstIndex = selected?.indexes[0];
|
|
12535
13438
|
const line = firstIndex === undefined ? undefined : document.lines[firstIndex];
|
|
@@ -12541,10 +13444,43 @@ class RootView {
|
|
|
12541
13444
|
}
|
|
12542
13445
|
return getMainCursorTarget(this.panes.main);
|
|
12543
13446
|
}
|
|
13447
|
+
mainPointerCoordinates(event) {
|
|
13448
|
+
const geometry = this.paneTextGeometry("main");
|
|
13449
|
+
if (geometry === undefined)
|
|
13450
|
+
return;
|
|
13451
|
+
const row = event.y - geometry.screenY;
|
|
13452
|
+
const column = event.x - geometry.screenX;
|
|
13453
|
+
if (!Number.isSafeInteger(row) || !Number.isSafeInteger(column) || row < 0 || row >= geometry.height || column < 0 || column >= geometry.width)
|
|
13454
|
+
return;
|
|
13455
|
+
return { row, column };
|
|
13456
|
+
}
|
|
13457
|
+
updateVirtualMainPointer(event) {
|
|
13458
|
+
const virtual = virtualMainPaneFor(this.panes.main);
|
|
13459
|
+
if (!virtual?.isActive())
|
|
13460
|
+
return;
|
|
13461
|
+
const anchor = this.mainPointerAnchor;
|
|
13462
|
+
if (anchor === undefined) {
|
|
13463
|
+
virtual.resetSelection();
|
|
13464
|
+
return;
|
|
13465
|
+
}
|
|
13466
|
+
const point = this.mainPointerCoordinates(event);
|
|
13467
|
+
if (point === undefined) {
|
|
13468
|
+
virtual.resetSelection();
|
|
13469
|
+
return;
|
|
13470
|
+
}
|
|
13471
|
+
virtual.setPointerSelection(anchor.row, anchor.column, point.row, point.column);
|
|
13472
|
+
}
|
|
12544
13473
|
mainChangeSelection() {
|
|
12545
13474
|
const document = getMainDocument(this.panes.main);
|
|
12546
13475
|
if (!document)
|
|
12547
13476
|
return;
|
|
13477
|
+
const pointerSelection = getMainPointerSelection(this.panes.main);
|
|
13478
|
+
if (pointerSelection?.valid && pointerSelection.endUtf16 > pointerSelection.startUtf16) {
|
|
13479
|
+
return {
|
|
13480
|
+
document,
|
|
13481
|
+
indexes: changeLineIndexes(document, pointerSelection.startUtf16, pointerSelection.endUtf16)
|
|
13482
|
+
};
|
|
13483
|
+
}
|
|
12548
13484
|
const keyboardSelection = getMainDiffLineSelection(this.panes.main);
|
|
12549
13485
|
if (keyboardSelection !== undefined) {
|
|
12550
13486
|
return {
|
|
@@ -12939,7 +13875,7 @@ class RootView {
|
|
|
12939
13875
|
let commitsState = setListRows(panel.views.commits, rows, displayRows);
|
|
12940
13876
|
if (commitsSearch.length > 0 && rows.length > 0) {
|
|
12941
13877
|
const normalized = commitsSearch.toLowerCase();
|
|
12942
|
-
const matchIndex = rows.findIndex((row) => (row.columns[
|
|
13878
|
+
const matchIndex = rows.findIndex((row) => (row.columns[2]?.text ?? "").toLowerCase().includes(normalized) || (row.columns[0]?.text ?? "").toLowerCase().includes(normalized));
|
|
12943
13879
|
if (matchIndex >= 0) {
|
|
12944
13880
|
const matchId = rows[matchIndex].id;
|
|
12945
13881
|
commitsState = selectListRow(commitsState, matchId);
|
|
@@ -12970,14 +13906,15 @@ class RootView {
|
|
|
12970
13906
|
}
|
|
12971
13907
|
const activeView = this.activeListView("commits");
|
|
12972
13908
|
if (activeView === undefined) {
|
|
13909
|
+
releaseListText(pane.text);
|
|
12973
13910
|
pane.update("");
|
|
12974
13911
|
return;
|
|
12975
13912
|
}
|
|
12976
13913
|
const { state } = activeView;
|
|
12977
13914
|
const width = sidePaneListWidth(this.geometry.windows.commits, state);
|
|
12978
13915
|
const focused = this.focusManager.active === "commits";
|
|
12979
|
-
const
|
|
12980
|
-
pane.
|
|
13916
|
+
const hoveredId = this.hoveredIdFor(activeView);
|
|
13917
|
+
installListText(pane.text, { state, width, focused, ...hoveredId === undefined ? {} : { hoveredId } });
|
|
12981
13918
|
pane.syncScrollbar(sidePaneViewportHeight(this.geometry.windows.commits));
|
|
12982
13919
|
}
|
|
12983
13920
|
installInitialMainContent(model) {
|
|
@@ -13209,16 +14146,19 @@ class RootView {
|
|
|
13209
14146
|
this.root.requestRender();
|
|
13210
14147
|
return;
|
|
13211
14148
|
}
|
|
14149
|
+
const rawPointerSelection = getMainPointerSelection(pane);
|
|
14150
|
+
const pointerSelection = rawPointerSelection !== undefined && rawPointerSelection.valid && rawPointerSelection.endUtf16 > rawPointerSelection.startUtf16 ? rawPointerSelection : undefined;
|
|
13212
14151
|
const keyboardSelection = getMainDiffLineSelection(pane);
|
|
13213
14152
|
const nativeRange = pane.text.getSelection();
|
|
13214
|
-
let selection = mode === "hunk" || mode === "file"
|
|
14153
|
+
let selection = mode === "hunk" || mode === "file" ? undefined : pointerSelection ?? (keyboardSelection === undefined ? undefined : {
|
|
13215
14154
|
valid: true,
|
|
13216
14155
|
startUtf16: keyboardSelection.startUtf16,
|
|
13217
14156
|
endUtf16: keyboardSelection.endUtf16,
|
|
13218
14157
|
active: true
|
|
13219
|
-
};
|
|
13220
|
-
if (selection === undefined && keyboardSelection === undefined && nativeRange)
|
|
14158
|
+
});
|
|
14159
|
+
if (selection === undefined && pointerSelection === undefined && keyboardSelection === undefined && nativeRange) {
|
|
13221
14160
|
selection = selectionFromRenderable(document, nativeRange, pane.text.getSelectedText());
|
|
14161
|
+
}
|
|
13222
14162
|
if (!selection && (mode === "hunk" || mode === "file")) {
|
|
13223
14163
|
const target = getMainCursorTarget(pane);
|
|
13224
14164
|
if (target) {
|
|
@@ -13538,6 +14478,9 @@ class RootView {
|
|
|
13538
14478
|
bar.onMouseDown = undefined;
|
|
13539
14479
|
bar.onMouseDrag = undefined;
|
|
13540
14480
|
bar.onMouseUp = undefined;
|
|
14481
|
+
bar.slider.onMouseDown = undefined;
|
|
14482
|
+
bar.slider.onMouseDrag = undefined;
|
|
14483
|
+
bar.slider.onMouseUp = undefined;
|
|
13541
14484
|
}
|
|
13542
14485
|
}
|
|
13543
14486
|
this.renderer.off("resize", this.handleResize);
|
|
@@ -13564,20 +14507,33 @@ class RootView {
|
|
|
13564
14507
|
const bar = paneScrollbar(typedPane.text);
|
|
13565
14508
|
if (!bar)
|
|
13566
14509
|
continue;
|
|
13567
|
-
|
|
14510
|
+
const beginScrollbarGesture = (event) => {
|
|
14511
|
+
this.updateHoveredListRow(event.x, event.y);
|
|
13568
14512
|
this.pendingClick = undefined;
|
|
13569
14513
|
this.lastSplitterPress = undefined;
|
|
13570
14514
|
this.gestureOwner = { kind: "scrollbar", paneId: typedPane.id };
|
|
14515
|
+
this.scrollPaneByScrollbarPosition(typedPane.id, event.y);
|
|
13571
14516
|
event.stopPropagation();
|
|
13572
14517
|
};
|
|
13573
|
-
|
|
13574
|
-
if (this.gestureOwner?.kind === "scrollbar" && this.gestureOwner.paneId === typedPane.id)
|
|
14518
|
+
const continueScrollbarGesture = (event) => {
|
|
14519
|
+
if (this.gestureOwner?.kind === "scrollbar" && this.gestureOwner.paneId === typedPane.id) {
|
|
14520
|
+
this.scrollPaneByScrollbarPosition(typedPane.id, event.y);
|
|
13575
14521
|
event.stopPropagation();
|
|
14522
|
+
}
|
|
13576
14523
|
};
|
|
13577
|
-
|
|
13578
|
-
if (this.gestureOwner?.kind === "scrollbar" && this.gestureOwner.paneId === typedPane.id)
|
|
14524
|
+
const endScrollbarGesture = (event) => {
|
|
14525
|
+
if (this.gestureOwner?.kind === "scrollbar" && this.gestureOwner.paneId === typedPane.id) {
|
|
14526
|
+
this.scrollPaneByScrollbarPosition(typedPane.id, event.y);
|
|
14527
|
+
this.gestureOwner = undefined;
|
|
13579
14528
|
event.stopPropagation();
|
|
14529
|
+
}
|
|
13580
14530
|
};
|
|
14531
|
+
bar.onMouseDown = beginScrollbarGesture;
|
|
14532
|
+
bar.onMouseDrag = continueScrollbarGesture;
|
|
14533
|
+
bar.onMouseUp = endScrollbarGesture;
|
|
14534
|
+
bar.slider.onMouseDown = beginScrollbarGesture;
|
|
14535
|
+
bar.slider.onMouseDrag = continueScrollbarGesture;
|
|
14536
|
+
bar.slider.onMouseUp = endScrollbarGesture;
|
|
13581
14537
|
}
|
|
13582
14538
|
this.root.onMouse = (event) => {
|
|
13583
14539
|
if (this.isBranchReviewActive?.())
|
|
@@ -13686,14 +14642,22 @@ class RootView {
|
|
|
13686
14642
|
return;
|
|
13687
14643
|
}
|
|
13688
14644
|
if (owner.kind === "main-selection") {
|
|
14645
|
+
const virtual = virtualMainPaneFor(this.panes.main);
|
|
13689
14646
|
if (event.type === "drag") {
|
|
13690
14647
|
this.pendingClick = undefined;
|
|
13691
14648
|
this.lastSplitterPress = undefined;
|
|
14649
|
+
if (virtual?.isActive())
|
|
14650
|
+
this.updateVirtualMainPointer(event);
|
|
14651
|
+
event.preventDefault();
|
|
13692
14652
|
event.stopPropagation();
|
|
13693
14653
|
return;
|
|
13694
14654
|
}
|
|
13695
|
-
if (event.type === "up") {
|
|
14655
|
+
if (event.type === "up" || event.type === "cancel") {
|
|
14656
|
+
if (virtual?.isActive() && event.type === "up")
|
|
14657
|
+
this.updateVirtualMainPointer(event);
|
|
13696
14658
|
this.gestureOwner = undefined;
|
|
14659
|
+
this.mainPointerAnchor = undefined;
|
|
14660
|
+
event.preventDefault();
|
|
13697
14661
|
event.stopPropagation();
|
|
13698
14662
|
return;
|
|
13699
14663
|
}
|
|
@@ -13824,10 +14788,22 @@ class RootView {
|
|
|
13824
14788
|
if (paneId === "main") {
|
|
13825
14789
|
this.pendingClick = undefined;
|
|
13826
14790
|
this.lastSplitterPress = undefined;
|
|
13827
|
-
this.gestureOwner = { kind: "main-selection" };
|
|
13828
14791
|
if (this.focusManager.active !== "main")
|
|
13829
14792
|
this.focusManager.focus("main");
|
|
14793
|
+
const virtual = virtualMainPaneFor(this.panes.main);
|
|
14794
|
+
const canSelect = event.button === 0 && !event.modifiers.ctrl;
|
|
14795
|
+
const point = virtual?.isActive() && canSelect ? this.mainPointerCoordinates(event) : undefined;
|
|
14796
|
+
this.mainPointerAnchor = point;
|
|
14797
|
+
if (virtual?.isActive()) {
|
|
14798
|
+
if (point === undefined)
|
|
14799
|
+
virtual.resetSelection();
|
|
14800
|
+
else
|
|
14801
|
+
virtual.setPointerSelection(point.row, point.column, point.row, point.column);
|
|
14802
|
+
}
|
|
14803
|
+
this.gestureOwner = { kind: "main-selection" };
|
|
13830
14804
|
this.clearTransientMenus();
|
|
14805
|
+
if (virtual?.isActive() && canSelect)
|
|
14806
|
+
event.preventDefault();
|
|
13831
14807
|
event.stopPropagation();
|
|
13832
14808
|
return;
|
|
13833
14809
|
}
|
|
@@ -14096,16 +15072,16 @@ class RootView {
|
|
|
14096
15072
|
this.syncPaneBorders();
|
|
14097
15073
|
const windows = this.geometry.windows;
|
|
14098
15074
|
const place = (renderable, name) => {
|
|
14099
|
-
const
|
|
14100
|
-
if (
|
|
15075
|
+
const dimensions2 = windows[name];
|
|
15076
|
+
if (dimensions2 === undefined) {
|
|
14101
15077
|
renderable.visible = false;
|
|
14102
15078
|
return;
|
|
14103
15079
|
}
|
|
14104
|
-
renderable.left =
|
|
14105
|
-
renderable.top =
|
|
14106
|
-
renderable.width = Math.max(1, widthOf(
|
|
14107
|
-
renderable.height = Math.max(1, heightOf(
|
|
14108
|
-
renderable.visible = widthOf(
|
|
15080
|
+
renderable.left = dimensions2.x0;
|
|
15081
|
+
renderable.top = dimensions2.y0;
|
|
15082
|
+
renderable.width = Math.max(1, widthOf(dimensions2));
|
|
15083
|
+
renderable.height = Math.max(1, heightOf(dimensions2));
|
|
15084
|
+
renderable.visible = widthOf(dimensions2) > 0 && heightOf(dimensions2) > 0;
|
|
14109
15085
|
};
|
|
14110
15086
|
for (const name of SIDE_WINDOWS)
|
|
14111
15087
|
place(this.panes[name].box, name);
|
|
@@ -14705,7 +15681,7 @@ function isWorkerAvailable() {
|
|
|
14705
15681
|
}
|
|
14706
15682
|
|
|
14707
15683
|
// src/ui/review-workspace/ReviewWorkspaceApp.tsx
|
|
14708
|
-
import { StyledText as StyledText8, parseColor as
|
|
15684
|
+
import { StyledText as StyledText8, parseColor as parseColor3 } from "@opentui/core";
|
|
14709
15685
|
import { useKeyboard, useTerminalDimensions } from "@opentui/react";
|
|
14710
15686
|
import { useCallback, useEffect as useEffect3, useLayoutEffect as useLayoutEffect2, useMemo as useMemo4, useRef as useRef2, useState as useState3, useSyncExternalStore } from "react";
|
|
14711
15687
|
|
|
@@ -15731,7 +16707,7 @@ function buildHunkStackRows(file, state, highlight, options) {
|
|
|
15731
16707
|
return rows;
|
|
15732
16708
|
}
|
|
15733
16709
|
// src/ui/review-workspace/components/ReviewDiffRow.tsx
|
|
15734
|
-
import { StyledText as StyledText7, parseColor } from "@opentui/core";
|
|
16710
|
+
import { StyledText as StyledText7, parseColor as parseColor2 } from "@opentui/core";
|
|
15735
16711
|
|
|
15736
16712
|
// src/ui/review-workspace/hunk-code-columns.ts
|
|
15737
16713
|
var HUNK_DIFF_RAIL_WIDTH = 1;
|
|
@@ -15804,7 +16780,7 @@ function color(value) {
|
|
|
15804
16780
|
const cached = colorCache2.get(value);
|
|
15805
16781
|
if (cached)
|
|
15806
16782
|
return cached;
|
|
15807
|
-
const parsed =
|
|
16783
|
+
const parsed = parseColor2(value);
|
|
15808
16784
|
colorCache2.set(value, parsed);
|
|
15809
16785
|
return parsed;
|
|
15810
16786
|
}
|
|
@@ -17916,7 +18892,7 @@ var colorCache3 = new Map;
|
|
|
17916
18892
|
function textChunk(text, style) {
|
|
17917
18893
|
let fg5 = colorCache3.get(COLORS2[style]);
|
|
17918
18894
|
if (!fg5) {
|
|
17919
|
-
fg5 =
|
|
18895
|
+
fg5 = parseColor3(COLORS2[style]);
|
|
17920
18896
|
colorCache3.set(COLORS2[style], fg5);
|
|
17921
18897
|
}
|
|
17922
18898
|
return { __isChunk: true, text, fg: fg5 };
|
|
@@ -18154,14 +19130,14 @@ function ReviewWorkspaceApp({ session }) {
|
|
|
18154
19130
|
const finishSummaryRef = useRef2(null);
|
|
18155
19131
|
const finishSubmitRef = useRef2(false);
|
|
18156
19132
|
const expandedSourceRef = useRef2(new Map);
|
|
18157
|
-
const
|
|
18158
|
-
const maxSidebarWidth = Math.max(REVIEW_SIDEBAR_MIN_WIDTH,
|
|
18159
|
-
const sidebarWidth =
|
|
18160
|
-
const diffWidth = Math.max(1,
|
|
19133
|
+
const dimensions2 = { width: Math.max(1, terminal.width), height: Math.max(1, terminal.height) };
|
|
19134
|
+
const maxSidebarWidth = Math.max(REVIEW_SIDEBAR_MIN_WIDTH, dimensions2.width - REVIEW_RESIZE_BAR_WIDTH - REVIEW_DIFF_BORDER_WIDTH - REVIEW_DIFF_MIN_CONTENT_WIDTH);
|
|
19135
|
+
const sidebarWidth = dimensions2.width >= REVIEW_SIDEBAR_VISIBILITY_WIDTH ? Math.min(Math.max(sidebarWidthPreference, REVIEW_SIDEBAR_MIN_WIDTH), maxSidebarWidth) : 0;
|
|
19136
|
+
const diffWidth = Math.max(1, dimensions2.width - sidebarWidth - (sidebarWidth > 0 ? REVIEW_RESIZE_BAR_WIDTH : 0) - REVIEW_DIFF_BORDER_WIDTH);
|
|
18161
19137
|
const layout = layoutMode === "auto" ? diffWidth >= 64 ? "split" : "stack" : layoutMode;
|
|
18162
19138
|
const composerHeight = state?.draft ? canShowReplacementDraft(state) ? 9 : 6 : 0;
|
|
18163
|
-
const diffHeight = Math.max(1,
|
|
18164
|
-
const resizeBarHeight = Math.max(1,
|
|
19139
|
+
const diffHeight = Math.max(1, dimensions2.height - 4 - composerHeight - 2);
|
|
19140
|
+
const resizeBarHeight = Math.max(1, dimensions2.height - 4 - composerHeight);
|
|
18165
19141
|
const sidebarFocused = focus === "sidebar" || focus === "filter";
|
|
18166
19142
|
const diffFocused = focus === "stream";
|
|
18167
19143
|
const files = useMemo4(() => state ? toHunkReviewFiles(visibleReviewFiles(state)) : [], [state?.document, state?.feedback, state?.filter, state?.viewed]);
|
|
@@ -18953,7 +19929,7 @@ function ReviewWorkspaceApp({ session }) {
|
|
|
18953
19929
|
id: "react-review-header",
|
|
18954
19930
|
style: { width: "100%", height: 3, flexShrink: 0 },
|
|
18955
19931
|
children: /* @__PURE__ */ jsx4("text", {
|
|
18956
|
-
content: headerText(state,
|
|
19932
|
+
content: headerText(state, dimensions2.width, controller.error),
|
|
18957
19933
|
wrapMode: "none",
|
|
18958
19934
|
truncate: true
|
|
18959
19935
|
})
|
|
@@ -19180,7 +20156,7 @@ function ReviewWorkspaceApp({ session }) {
|
|
|
19180
20156
|
}),
|
|
19181
20157
|
orphanedFeedback.length > 0 ? /* @__PURE__ */ jsx4("box", {
|
|
19182
20158
|
id: "review-orphaned-feedback",
|
|
19183
|
-
style: { position: "absolute", left: 1, bottom: 1, width: Math.max(20,
|
|
20159
|
+
style: { position: "absolute", left: 1, bottom: 1, width: Math.max(20, dimensions2.width - 2), height: Math.min(4, orphanedFeedback.length), zIndex: 50, border: true, flexDirection: "column", backgroundColor: "#202020" },
|
|
19184
20160
|
children: orphanedFeedback.slice(0, 4).map((feedback) => /* @__PURE__ */ jsxs4("box", {
|
|
19185
20161
|
style: { width: "100%", height: 1, flexDirection: "row" },
|
|
19186
20162
|
onMouseUp: () => {
|
|
@@ -19225,7 +20201,7 @@ function ReviewWorkspaceApp({ session }) {
|
|
|
19225
20201
|
}) : null,
|
|
19226
20202
|
feedbackMessage ? /* @__PURE__ */ jsx4("box", {
|
|
19227
20203
|
id: "review-feedback-message",
|
|
19228
|
-
style: { position: "absolute", left: 1, bottom: orphanedFeedback.length > 0 ? Math.min(5, orphanedFeedback.length + 1) : 1, width: Math.max(20,
|
|
20204
|
+
style: { position: "absolute", left: 1, bottom: orphanedFeedback.length > 0 ? Math.min(5, orphanedFeedback.length + 1) : 1, width: Math.max(20, dimensions2.width - 2), height: 1, zIndex: 55, backgroundColor: "#202020" },
|
|
19229
20205
|
children: /* @__PURE__ */ jsx4("text", {
|
|
19230
20206
|
content: feedbackMessage,
|
|
19231
20207
|
wrapMode: "none",
|
|
@@ -19445,7 +20421,7 @@ function ReviewWorkspaceApp({ session }) {
|
|
|
19445
20421
|
}) : null,
|
|
19446
20422
|
helpOpen ? /* @__PURE__ */ jsx4("box", {
|
|
19447
20423
|
id: "review-help-dialog",
|
|
19448
|
-
style: { position: "absolute", left: Math.max(1, Math.floor(
|
|
20424
|
+
style: { position: "absolute", left: Math.max(1, Math.floor(dimensions2.width / 10)), top: 2, width: Math.max(50, Math.floor(dimensions2.width * 4 / 5)), height: Math.min(26, Math.max(14, dimensions2.height - 4)), zIndex: 70, border: true, flexDirection: "column", backgroundColor: "#202020" },
|
|
19449
20425
|
children: /* @__PURE__ */ jsx4("text", {
|
|
19450
20426
|
content: `Review commands
|
|
19451
20427
|
${reviewHelp(focus, state)}
|
|
@@ -19456,7 +20432,7 @@ Esc close this help`,
|
|
|
19456
20432
|
}) : null,
|
|
19457
20433
|
finishDialog.isOpen() ? /* @__PURE__ */ jsxs4("box", {
|
|
19458
20434
|
id: "review-finish-dialog",
|
|
19459
|
-
style: { position: "absolute", left: Math.max(1, Math.floor(
|
|
20435
|
+
style: { position: "absolute", left: Math.max(1, Math.floor(dimensions2.width / 8)), top: 3, width: Math.max(40, Math.floor(dimensions2.width * 3 / 4)), height: 10, zIndex: 60, border: true, flexDirection: "column", backgroundColor: "#202020" },
|
|
19460
20436
|
children: [
|
|
19461
20437
|
/* @__PURE__ */ jsx4("text", {
|
|
19462
20438
|
content: `Finish review — ${finishDialog.getDecision()}`,
|