@lvce-editor/editor-worker 19.71.5 → 19.72.0
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/editorWorkerMain.js +480 -163
- package/dist/settings.json +10 -0
- package/package.json +1 -1
package/dist/editorWorkerMain.js
CHANGED
|
@@ -2023,13 +2023,6 @@ const getScrollBarSize = (size, contentSize, minimumSliderSize) => {
|
|
|
2023
2023
|
return Math.max(Math.round(size ** 2 / contentSize), minimumSliderSize);
|
|
2024
2024
|
};
|
|
2025
2025
|
|
|
2026
|
-
const getScrollBarWidth = (width, longestLineWidth) => {
|
|
2027
|
-
if (width > longestLineWidth) {
|
|
2028
|
-
return 0;
|
|
2029
|
-
}
|
|
2030
|
-
return width ** 2 / longestLineWidth;
|
|
2031
|
-
};
|
|
2032
|
-
|
|
2033
2026
|
const getNewDeltaPercent = (height, scrollBarHeight, relativeY) => {
|
|
2034
2027
|
const halfScrollBarHeight = scrollBarHeight / 2;
|
|
2035
2028
|
if (relativeY <= halfScrollBarHeight) {
|
|
@@ -2364,6 +2357,190 @@ const getDecorationClassName = type => {
|
|
|
2364
2357
|
}
|
|
2365
2358
|
};
|
|
2366
2359
|
|
|
2360
|
+
const getHorizontalScrollDimensions = ({
|
|
2361
|
+
gutterWidth = 0,
|
|
2362
|
+
width,
|
|
2363
|
+
x = 0
|
|
2364
|
+
}) => {
|
|
2365
|
+
return {
|
|
2366
|
+
width: Math.max(0, width - gutterWidth),
|
|
2367
|
+
x: x + gutterWidth
|
|
2368
|
+
};
|
|
2369
|
+
};
|
|
2370
|
+
|
|
2371
|
+
const defaultThreshold = 500;
|
|
2372
|
+
const getSegments = line => {
|
|
2373
|
+
if ('Segmenter' in Intl) {
|
|
2374
|
+
// @ts-ignore
|
|
2375
|
+
return [...new Intl.Segmenter(undefined, {
|
|
2376
|
+
granularity: 'grapheme'
|
|
2377
|
+
}).segment(line)];
|
|
2378
|
+
}
|
|
2379
|
+
const segments = [];
|
|
2380
|
+
let index = 0;
|
|
2381
|
+
for (const segment of line) {
|
|
2382
|
+
segments.push({
|
|
2383
|
+
index,
|
|
2384
|
+
segment
|
|
2385
|
+
});
|
|
2386
|
+
index += segment.length;
|
|
2387
|
+
}
|
|
2388
|
+
return segments;
|
|
2389
|
+
};
|
|
2390
|
+
const getCharacterWidth = (character, tabSize) => {
|
|
2391
|
+
if (character === '\t') {
|
|
2392
|
+
return tabSize;
|
|
2393
|
+
}
|
|
2394
|
+
// Grapheme clusters such as combining characters and ZWJ emoji are indivisible.
|
|
2395
|
+
// Treat each cluster as one display column; the extra cluster below is a safe overscan.
|
|
2396
|
+
return 1;
|
|
2397
|
+
};
|
|
2398
|
+
const getHorizontalDisplayColumn = (line, sourceColumn, tabSize) => {
|
|
2399
|
+
let displayColumn = 0;
|
|
2400
|
+
for (const {
|
|
2401
|
+
index,
|
|
2402
|
+
segment
|
|
2403
|
+
} of getSegments(line)) {
|
|
2404
|
+
if (index + segment.length > sourceColumn) {
|
|
2405
|
+
break;
|
|
2406
|
+
}
|
|
2407
|
+
displayColumn += segment === '\t' ? tabSize : segment.length;
|
|
2408
|
+
}
|
|
2409
|
+
return displayColumn;
|
|
2410
|
+
};
|
|
2411
|
+
const getHorizontalVisibleRange = (line, deltaX, width, averageCharWidth, tabSize, threshold = defaultThreshold) => {
|
|
2412
|
+
if (line.length <= threshold) {
|
|
2413
|
+
return {
|
|
2414
|
+
end: line.length,
|
|
2415
|
+
start: 0
|
|
2416
|
+
};
|
|
2417
|
+
}
|
|
2418
|
+
const charWidth = averageCharWidth > 0 ? averageCharWidth : 1;
|
|
2419
|
+
const scrollOffset = Math.max(0, Number.isFinite(deltaX) ? deltaX : 0);
|
|
2420
|
+
const viewportWidth = Number.isFinite(width) ? Math.max(0, width) : Infinity;
|
|
2421
|
+
const targetStart = scrollOffset / charWidth;
|
|
2422
|
+
const targetEnd = (scrollOffset + viewportWidth) / charWidth;
|
|
2423
|
+
let column = 0;
|
|
2424
|
+
let index = 0;
|
|
2425
|
+
let start = 0;
|
|
2426
|
+
let started = false;
|
|
2427
|
+
const segments = getSegments(line);
|
|
2428
|
+
for (const {
|
|
2429
|
+
index: segmentIndex,
|
|
2430
|
+
segment
|
|
2431
|
+
} of segments) {
|
|
2432
|
+
const nextColumn = column + getCharacterWidth(segment, tabSize);
|
|
2433
|
+
if (!started && nextColumn <= targetStart) {
|
|
2434
|
+
column = nextColumn;
|
|
2435
|
+
index = segmentIndex + segment.length;
|
|
2436
|
+
start = index;
|
|
2437
|
+
continue;
|
|
2438
|
+
}
|
|
2439
|
+
if (!started) {
|
|
2440
|
+
start = segmentIndex;
|
|
2441
|
+
started = true;
|
|
2442
|
+
}
|
|
2443
|
+
index = segmentIndex + segment.length;
|
|
2444
|
+
column = nextColumn;
|
|
2445
|
+
if (column >= targetEnd) {
|
|
2446
|
+
break;
|
|
2447
|
+
}
|
|
2448
|
+
}
|
|
2449
|
+
if (!started) {
|
|
2450
|
+
start = index;
|
|
2451
|
+
}
|
|
2452
|
+
// Keep one extra complete grapheme to cover fractional offsets and avoid a blank edge.
|
|
2453
|
+
if (index < line.length) {
|
|
2454
|
+
const nextSegment = segments.find(({
|
|
2455
|
+
index: segmentIndex
|
|
2456
|
+
}) => segmentIndex >= index);
|
|
2457
|
+
if (nextSegment) {
|
|
2458
|
+
index = nextSegment.index + nextSegment.segment.length;
|
|
2459
|
+
}
|
|
2460
|
+
}
|
|
2461
|
+
return {
|
|
2462
|
+
end: index,
|
|
2463
|
+
start
|
|
2464
|
+
};
|
|
2465
|
+
};
|
|
2466
|
+
const getHorizontalVisibleRangeMeasured = async (line, deltaX, width, averageCharWidth, tabSize, threshold, measureWidth) => {
|
|
2467
|
+
const fallback = () => {
|
|
2468
|
+
const range = getHorizontalVisibleRange(line, deltaX, width, averageCharWidth, tabSize, threshold);
|
|
2469
|
+
return {
|
|
2470
|
+
...range,
|
|
2471
|
+
difference: getHorizontalVisibleDifference(line, range.start, deltaX, averageCharWidth, tabSize)
|
|
2472
|
+
};
|
|
2473
|
+
};
|
|
2474
|
+
if (line.length <= threshold) {
|
|
2475
|
+
return fallback();
|
|
2476
|
+
}
|
|
2477
|
+
const scrollOffset = Math.max(0, Number.isFinite(deltaX) ? deltaX : 0);
|
|
2478
|
+
const viewportWidth = Number.isFinite(width) ? Math.max(0, width) : Infinity;
|
|
2479
|
+
const segments = getSegments(line);
|
|
2480
|
+
const boundaries = [0, ...segments.map(({
|
|
2481
|
+
index,
|
|
2482
|
+
segment
|
|
2483
|
+
}) => index + segment.length)];
|
|
2484
|
+
const measurements = new Map([[0, 0]]);
|
|
2485
|
+
const measureBoundary = async boundaryIndex => {
|
|
2486
|
+
const cached = measurements.get(boundaryIndex);
|
|
2487
|
+
if (cached !== undefined) {
|
|
2488
|
+
return cached;
|
|
2489
|
+
}
|
|
2490
|
+
const prefix = line.slice(0, boundaries[boundaryIndex]).replaceAll('\t', () => ' '.repeat(tabSize));
|
|
2491
|
+
const measured = await measureWidth(prefix);
|
|
2492
|
+
measurements.set(boundaryIndex, measured);
|
|
2493
|
+
return measured;
|
|
2494
|
+
};
|
|
2495
|
+
const findGreatestBoundaryAtMost = async target => {
|
|
2496
|
+
let low = 0;
|
|
2497
|
+
let high = boundaries.length;
|
|
2498
|
+
while (low < high) {
|
|
2499
|
+
const middle = Math.floor((low + high) / 2);
|
|
2500
|
+
if ((await measureBoundary(middle)) <= target) {
|
|
2501
|
+
low = middle + 1;
|
|
2502
|
+
} else {
|
|
2503
|
+
high = middle;
|
|
2504
|
+
}
|
|
2505
|
+
}
|
|
2506
|
+
return Math.max(0, low - 1);
|
|
2507
|
+
};
|
|
2508
|
+
const findFirstBoundaryAtLeast = async target => {
|
|
2509
|
+
let low = 0;
|
|
2510
|
+
let high = boundaries.length;
|
|
2511
|
+
while (low < high) {
|
|
2512
|
+
const middle = Math.floor((low + high) / 2);
|
|
2513
|
+
if ((await measureBoundary(middle)) < target) {
|
|
2514
|
+
low = middle + 1;
|
|
2515
|
+
} else {
|
|
2516
|
+
high = middle;
|
|
2517
|
+
}
|
|
2518
|
+
}
|
|
2519
|
+
return Math.min(boundaries.length - 1, low);
|
|
2520
|
+
};
|
|
2521
|
+
try {
|
|
2522
|
+
const startBoundary = await findGreatestBoundaryAtMost(scrollOffset);
|
|
2523
|
+
const endBoundary = await findFirstBoundaryAtLeast(scrollOffset + viewportWidth);
|
|
2524
|
+
const start = boundaries[startBoundary];
|
|
2525
|
+
let end = boundaries[endBoundary];
|
|
2526
|
+
if (end < line.length) {
|
|
2527
|
+
end = boundaries[Math.min(boundaries.length - 1, endBoundary + 1)];
|
|
2528
|
+
}
|
|
2529
|
+
return {
|
|
2530
|
+
difference: (await measureBoundary(startBoundary)) - scrollOffset,
|
|
2531
|
+
end,
|
|
2532
|
+
start
|
|
2533
|
+
};
|
|
2534
|
+
} catch {
|
|
2535
|
+
return fallback();
|
|
2536
|
+
}
|
|
2537
|
+
};
|
|
2538
|
+
const getHorizontalVisibleDifference = (line, start, deltaX, averageCharWidth, tabSize) => {
|
|
2539
|
+
const charWidth = averageCharWidth > 0 ? averageCharWidth : 1;
|
|
2540
|
+
const scrollOffset = Number.isFinite(deltaX) ? deltaX : 0;
|
|
2541
|
+
return getHorizontalDisplayColumn(line, start, tabSize) * charWidth - scrollOffset;
|
|
2542
|
+
};
|
|
2543
|
+
|
|
2367
2544
|
// Large files have no token cache. Only materialize the text inside the horizontal viewport.
|
|
2368
2545
|
const getLargeFileVisible = editor => {
|
|
2369
2546
|
const {
|
|
@@ -2762,6 +2939,31 @@ const loadTokenizers = async languageIds => {
|
|
|
2762
2939
|
}
|
|
2763
2940
|
};
|
|
2764
2941
|
|
|
2942
|
+
const RE_ASCII = /^\p{ASCII}*$/u;
|
|
2943
|
+
const isAscii = line => {
|
|
2944
|
+
return RE_ASCII.test(line);
|
|
2945
|
+
};
|
|
2946
|
+
|
|
2947
|
+
const measureTextWidthFast = async (text, charWidth) => {
|
|
2948
|
+
return text.length * charWidth;
|
|
2949
|
+
};
|
|
2950
|
+
|
|
2951
|
+
const measureTextWidthSlow = async (text, fontWeight, fontSize, fontFamily, letterSpacing, isMonoSpaceFont, charWidth) => {
|
|
2952
|
+
const width = await invoke$e('TextMeasurement.measureTextWidth', text, fontWeight, fontSize, fontFamily, letterSpacing, isMonoSpaceFont, charWidth);
|
|
2953
|
+
return width;
|
|
2954
|
+
};
|
|
2955
|
+
|
|
2956
|
+
const measureTextWidth = async (text, fontWeight, fontSize, fontFamily, letterSpacing, isMonoSpaceFont, charWidth) => {
|
|
2957
|
+
// TODO maybe have a property for the whole text document
|
|
2958
|
+
// whether the document is ASCII or not
|
|
2959
|
+
// so that it doesn't need to be checked on every cursor change
|
|
2960
|
+
// or scroll position change
|
|
2961
|
+
if (isMonoSpaceFont && isAscii(text)) {
|
|
2962
|
+
return await measureTextWidthFast(text, charWidth);
|
|
2963
|
+
}
|
|
2964
|
+
return await measureTextWidthSlow(text, fontWeight, fontSize, fontFamily, letterSpacing, isMonoSpaceFont, charWidth);
|
|
2965
|
+
};
|
|
2966
|
+
|
|
2765
2967
|
const Dot = '.';
|
|
2766
2968
|
const DoubleQuote$1 = '"';
|
|
2767
2969
|
const EmptyString = '';
|
|
@@ -2999,6 +3201,7 @@ const getStartDefaults = (tokens, minOffset) => {
|
|
|
2999
3201
|
let start = 0;
|
|
3000
3202
|
let end = 0;
|
|
3001
3203
|
let startIndex = 0;
|
|
3204
|
+
let found = false;
|
|
3002
3205
|
const tokensLength = tokens.length;
|
|
3003
3206
|
for (let i = 0; i < tokensLength; i += 2) {
|
|
3004
3207
|
const tokenLength = tokens[i + 1];
|
|
@@ -3008,11 +3211,17 @@ const getStartDefaults = (tokens, minOffset) => {
|
|
|
3008
3211
|
start -= tokenLength;
|
|
3009
3212
|
end -= tokenLength;
|
|
3010
3213
|
startIndex = i;
|
|
3214
|
+
found = true;
|
|
3011
3215
|
break;
|
|
3012
3216
|
}
|
|
3013
3217
|
}
|
|
3218
|
+
if (!found) {
|
|
3219
|
+
return {
|
|
3220
|
+
start: end,
|
|
3221
|
+
startIndex: tokensLength
|
|
3222
|
+
};
|
|
3223
|
+
}
|
|
3014
3224
|
return {
|
|
3015
|
-
end,
|
|
3016
3225
|
start,
|
|
3017
3226
|
startIndex
|
|
3018
3227
|
};
|
|
@@ -3063,20 +3272,24 @@ const getLineInfoEmbeddedFull = (embeddedResults, tokenResults, line, decoration
|
|
|
3063
3272
|
const embeddedTokenMap = embeddedResult.TokenMap;
|
|
3064
3273
|
const tokensLength = embeddedTokens.length;
|
|
3065
3274
|
let {
|
|
3066
|
-
end,
|
|
3067
3275
|
start,
|
|
3068
3276
|
startIndex
|
|
3069
3277
|
} = getStartDefaults(embeddedTokens, minOffset);
|
|
3070
|
-
const difference =
|
|
3278
|
+
const difference = getHorizontalVisibleDifference(line, Math.max(start, minOffset), deltaX, averageCharWidth, tabSize);
|
|
3071
3279
|
for (let i = startIndex; i < tokensLength; i += 2) {
|
|
3072
3280
|
const tokenType = embeddedTokens[i];
|
|
3073
3281
|
const tokenLength = embeddedTokens[i + 1];
|
|
3074
3282
|
const tokenEnd = start + tokenLength;
|
|
3075
|
-
const
|
|
3283
|
+
const tokenStart = Math.max(start, minOffset);
|
|
3284
|
+
const visibleTokenEnd = Math.min(tokenEnd, maxOffset);
|
|
3285
|
+
if (tokenStart >= visibleTokenEnd) {
|
|
3286
|
+
break;
|
|
3287
|
+
}
|
|
3288
|
+
const hasOverlap = hasDecorationOverlap(decorationMap, tokenStart, visibleTokenEnd);
|
|
3076
3289
|
if (hasOverlap) {
|
|
3077
3290
|
// Token has decoration overlap - split into parts
|
|
3078
|
-
let currentPos =
|
|
3079
|
-
while (currentPos <
|
|
3291
|
+
let currentPos = tokenStart;
|
|
3292
|
+
while (currentPos < visibleTokenEnd) {
|
|
3080
3293
|
// Find if current position is inside a decoration
|
|
3081
3294
|
const activeDecoration = getActiveDecoration(decorationMap, currentPos);
|
|
3082
3295
|
let partEnd;
|
|
@@ -3084,15 +3297,15 @@ const getLineInfoEmbeddedFull = (embeddedResults, tokenResults, line, decoration
|
|
|
3084
3297
|
let className;
|
|
3085
3298
|
if (activeDecoration) {
|
|
3086
3299
|
// Render decorated part
|
|
3087
|
-
partEnd = Math.min(
|
|
3300
|
+
partEnd = Math.min(visibleTokenEnd, activeDecoration.end);
|
|
3088
3301
|
text = line.slice(currentPos, partEnd);
|
|
3089
3302
|
const baseTokenClass = embeddedTokenMap[tokenType] || 'Unknown';
|
|
3090
3303
|
className = `Token ${baseTokenClass} ${activeDecoration.className}`;
|
|
3091
3304
|
} else {
|
|
3092
3305
|
// Find next decoration start or token end
|
|
3093
|
-
let nextDecorationStart =
|
|
3306
|
+
let nextDecorationStart = visibleTokenEnd;
|
|
3094
3307
|
for (const [decorationStart] of decorationMap) {
|
|
3095
|
-
if (decorationStart > currentPos && decorationStart <
|
|
3308
|
+
if (decorationStart > currentPos && decorationStart < visibleTokenEnd) {
|
|
3096
3309
|
nextDecorationStart = Math.min(nextDecorationStart, decorationStart);
|
|
3097
3310
|
}
|
|
3098
3311
|
}
|
|
@@ -3108,14 +3321,13 @@ const getLineInfoEmbeddedFull = (embeddedResults, tokenResults, line, decoration
|
|
|
3108
3321
|
}
|
|
3109
3322
|
} else {
|
|
3110
3323
|
// No decoration overlap - render token normally
|
|
3111
|
-
const text = line.slice(
|
|
3324
|
+
const text = line.slice(tokenStart, visibleTokenEnd);
|
|
3112
3325
|
const className = `Token ${embeddedTokenMap[tokenType] || 'Unknown'}`;
|
|
3113
3326
|
const normalizedText = normalizeText(text, normalize, tabSize);
|
|
3114
3327
|
lineInfo.push(normalizedText, className);
|
|
3115
3328
|
}
|
|
3116
3329
|
start = tokenEnd;
|
|
3117
|
-
|
|
3118
|
-
if (end >= maxOffset) {
|
|
3330
|
+
if (start >= maxOffset) {
|
|
3119
3331
|
break;
|
|
3120
3332
|
}
|
|
3121
3333
|
}
|
|
@@ -3124,17 +3336,6 @@ const getLineInfoEmbeddedFull = (embeddedResults, tokenResults, line, decoration
|
|
|
3124
3336
|
lineInfo
|
|
3125
3337
|
};
|
|
3126
3338
|
};
|
|
3127
|
-
const getOffsets = () => {
|
|
3128
|
-
return {
|
|
3129
|
-
maxOffset: Infinity,
|
|
3130
|
-
minOffset: 0
|
|
3131
|
-
};
|
|
3132
|
-
};
|
|
3133
|
-
const getDifference = (start, averageCharWidth, deltaX) => {
|
|
3134
|
-
const beforeWidth = start * averageCharWidth;
|
|
3135
|
-
const difference = beforeWidth - deltaX;
|
|
3136
|
-
return difference;
|
|
3137
|
-
};
|
|
3138
3339
|
const appendTokenRange = (resultTokens, resultTokenMap, tokens, tokenMap, rangeStart, rangeEnd) => {
|
|
3139
3340
|
let tokenStart = 0;
|
|
3140
3341
|
for (let i = 0; i < tokens.length; i += 2) {
|
|
@@ -3190,21 +3391,25 @@ const getLineInfoDefault = (line, tokenResults, embeddedResults, decorations, To
|
|
|
3190
3391
|
tokens
|
|
3191
3392
|
} = tokenResults;
|
|
3192
3393
|
let {
|
|
3193
|
-
end,
|
|
3194
3394
|
start,
|
|
3195
3395
|
startIndex
|
|
3196
3396
|
} = getStartDefaults(tokens, minOffset);
|
|
3197
|
-
const difference =
|
|
3397
|
+
const difference = getHorizontalVisibleDifference(line, Math.max(start, minOffset), deltaX, averageCharWidth, tabSize);
|
|
3198
3398
|
const tokensLength = tokens.length;
|
|
3199
3399
|
for (let i = startIndex; i < tokensLength; i += 2) {
|
|
3200
3400
|
const tokenType = tokens[i];
|
|
3201
3401
|
const tokenLength = tokens[i + 1];
|
|
3202
3402
|
const tokenEnd = start + tokenLength;
|
|
3203
|
-
const
|
|
3403
|
+
const tokenStart = Math.max(start, minOffset);
|
|
3404
|
+
const visibleTokenEnd = Math.min(tokenEnd, maxOffset);
|
|
3405
|
+
if (tokenStart >= visibleTokenEnd) {
|
|
3406
|
+
break;
|
|
3407
|
+
}
|
|
3408
|
+
const hasOverlap = hasDecorationOverlap(decorationMap, tokenStart, visibleTokenEnd);
|
|
3204
3409
|
if (hasOverlap) {
|
|
3205
3410
|
// Token has decoration overlap - split into parts
|
|
3206
|
-
let currentPos =
|
|
3207
|
-
while (currentPos <
|
|
3411
|
+
let currentPos = tokenStart;
|
|
3412
|
+
while (currentPos < visibleTokenEnd) {
|
|
3208
3413
|
// Find if current position is inside a decoration
|
|
3209
3414
|
const activeDecoration = getActiveDecoration(decorationMap, currentPos);
|
|
3210
3415
|
let partEnd;
|
|
@@ -3212,15 +3417,15 @@ const getLineInfoDefault = (line, tokenResults, embeddedResults, decorations, To
|
|
|
3212
3417
|
let className;
|
|
3213
3418
|
if (activeDecoration) {
|
|
3214
3419
|
// Render decorated part
|
|
3215
|
-
partEnd = Math.min(
|
|
3420
|
+
partEnd = Math.min(visibleTokenEnd, activeDecoration.end);
|
|
3216
3421
|
text = line.slice(currentPos, partEnd);
|
|
3217
3422
|
const baseTokenClass = TokenMap[tokenType] || 'Unknown';
|
|
3218
3423
|
className = `Token ${baseTokenClass} ${activeDecoration.className}`;
|
|
3219
3424
|
} else {
|
|
3220
3425
|
// Find next decoration start or token end
|
|
3221
|
-
let nextDecorationStart =
|
|
3426
|
+
let nextDecorationStart = visibleTokenEnd;
|
|
3222
3427
|
for (const [decorationStart] of decorationMap) {
|
|
3223
|
-
if (decorationStart > currentPos && decorationStart <
|
|
3428
|
+
if (decorationStart > currentPos && decorationStart < visibleTokenEnd) {
|
|
3224
3429
|
nextDecorationStart = Math.min(nextDecorationStart, decorationStart);
|
|
3225
3430
|
}
|
|
3226
3431
|
}
|
|
@@ -3236,14 +3441,13 @@ const getLineInfoDefault = (line, tokenResults, embeddedResults, decorations, To
|
|
|
3236
3441
|
}
|
|
3237
3442
|
} else {
|
|
3238
3443
|
// No decoration overlap - render token normally
|
|
3239
|
-
const text = line.slice(
|
|
3444
|
+
const text = line.slice(tokenStart, visibleTokenEnd);
|
|
3240
3445
|
const className = `Token ${TokenMap[tokenType] || 'Unknown'}`;
|
|
3241
3446
|
const normalizedText = normalizeText(text, normalize, tabSize);
|
|
3242
3447
|
lineInfo.push(normalizedText, className);
|
|
3243
3448
|
}
|
|
3244
3449
|
start = tokenEnd;
|
|
3245
|
-
|
|
3246
|
-
if (end >= maxOffset) {
|
|
3450
|
+
if (start >= maxOffset) {
|
|
3247
3451
|
break;
|
|
3248
3452
|
}
|
|
3249
3453
|
}
|
|
@@ -3252,11 +3456,11 @@ const getLineInfoDefault = (line, tokenResults, embeddedResults, decorations, To
|
|
|
3252
3456
|
lineInfo
|
|
3253
3457
|
};
|
|
3254
3458
|
};
|
|
3255
|
-
const getLineInfo$1 = (line, tokenResults, embeddedResults, decorations, TokenMap, lineOffset, normalize, tabSize, width, deltaX, averageCharWidth) => {
|
|
3459
|
+
const getLineInfo$1 = (line, tokenResults, embeddedResults, decorations, TokenMap, lineOffset, normalize, tabSize, width, deltaX, averageCharWidth, measuredRange) => {
|
|
3256
3460
|
const {
|
|
3257
|
-
maxOffset,
|
|
3258
|
-
minOffset
|
|
3259
|
-
} =
|
|
3461
|
+
end: maxOffset,
|
|
3462
|
+
start: minOffset
|
|
3463
|
+
} = measuredRange;
|
|
3260
3464
|
if (embeddedResults.length > 0 && tokenResults.embeddedResultIndex !== undefined) {
|
|
3261
3465
|
const embeddedResult = embeddedResults[tokenResults.embeddedResultIndex];
|
|
3262
3466
|
if (embeddedResult?.isFull) {
|
|
@@ -3271,9 +3475,10 @@ const getLineInfo$1 = (line, tokenResults, embeddedResults, decorations, TokenMa
|
|
|
3271
3475
|
};
|
|
3272
3476
|
|
|
3273
3477
|
// TODO need lots of tests for this
|
|
3274
|
-
const getLineInfosViewport = (editor, tokens, embeddedResults, minLineY, maxLineY, minLineOffset, width, deltaX, averageCharWidth) => {
|
|
3478
|
+
const getLineInfosViewport = async (editor, tokens, embeddedResults, minLineY, maxLineY, minLineOffset, width, deltaX, averageCharWidth, horizontalVirtualizationThreshold) => {
|
|
3275
3479
|
const result = [];
|
|
3276
3480
|
const differences = [];
|
|
3481
|
+
const horizontalVisibleRanges = [];
|
|
3277
3482
|
const {
|
|
3278
3483
|
decorations,
|
|
3279
3484
|
languageId,
|
|
@@ -3281,10 +3486,11 @@ const getLineInfosViewport = (editor, tokens, embeddedResults, minLineY, maxLine
|
|
|
3281
3486
|
} = editor;
|
|
3282
3487
|
const tokenMap = get$5(languageId);
|
|
3283
3488
|
let offset = minLineOffset;
|
|
3284
|
-
const tabSize = 2;
|
|
3489
|
+
const tabSize = editor.tabSize ?? 2;
|
|
3285
3490
|
for (let i = minLineY; i < maxLineY; i++) {
|
|
3286
3491
|
const line = lines[i];
|
|
3287
3492
|
const normalize = shouldNormalizeText(line);
|
|
3493
|
+
const measuredRange = await getHorizontalVisibleRangeMeasured(line, deltaX, width, averageCharWidth, tabSize, horizontalVirtualizationThreshold, text => measureTextWidth(text, editor.fontWeight, editor.fontSize, editor.fontFamily, editor.letterSpacing, editor.isMonospaceFont, editor.charWidth));
|
|
3288
3494
|
|
|
3289
3495
|
// Use decorations that were pre-computed (includes links and diagnostics)
|
|
3290
3496
|
// Filter decorations to only include those for this line
|
|
@@ -3301,15 +3507,20 @@ const getLineInfosViewport = (editor, tokens, embeddedResults, minLineY, maxLine
|
|
|
3301
3507
|
}
|
|
3302
3508
|
}
|
|
3303
3509
|
const {
|
|
3304
|
-
difference,
|
|
3305
3510
|
lineInfo
|
|
3306
|
-
} = getLineInfo$1(line, tokens[i - minLineY], embeddedResults, lineDecorations, tokenMap, offset, normalize, tabSize, width, deltaX, averageCharWidth);
|
|
3511
|
+
} = getLineInfo$1(line, tokens[i - minLineY], embeddedResults, lineDecorations, tokenMap, offset, normalize, tabSize, width, deltaX, averageCharWidth, measuredRange);
|
|
3307
3512
|
result.push(lineInfo);
|
|
3308
|
-
differences.push(difference);
|
|
3513
|
+
differences.push(measuredRange.difference);
|
|
3514
|
+
horizontalVisibleRanges.push({
|
|
3515
|
+
end: measuredRange.end,
|
|
3516
|
+
rowIndex: i,
|
|
3517
|
+
start: measuredRange.start
|
|
3518
|
+
});
|
|
3309
3519
|
offset += line.length + 1;
|
|
3310
3520
|
}
|
|
3311
3521
|
return {
|
|
3312
3522
|
differences,
|
|
3523
|
+
horizontalVisibleRanges,
|
|
3313
3524
|
result
|
|
3314
3525
|
};
|
|
3315
3526
|
};
|
|
@@ -3317,11 +3528,15 @@ const getVisible$1 = async (editor, syncIncremental) => {
|
|
|
3317
3528
|
if (editor.lifecycle?.disposed) {
|
|
3318
3529
|
return {
|
|
3319
3530
|
differences: [],
|
|
3531
|
+
horizontalVisibleRanges: [],
|
|
3320
3532
|
textInfos: []
|
|
3321
3533
|
};
|
|
3322
3534
|
}
|
|
3323
3535
|
if (editor.largeFile) {
|
|
3324
|
-
return
|
|
3536
|
+
return {
|
|
3537
|
+
...(await getLargeFileVisible(editor)),
|
|
3538
|
+
horizontalVisibleRanges: []
|
|
3539
|
+
};
|
|
3325
3540
|
}
|
|
3326
3541
|
// TODO should separate rendering from business logic somehow
|
|
3327
3542
|
// currently hard to test because need to mock editor height, top, left,
|
|
@@ -3331,15 +3546,19 @@ const getVisible$1 = async (editor, syncIncremental) => {
|
|
|
3331
3546
|
const {
|
|
3332
3547
|
charWidth,
|
|
3333
3548
|
deltaX,
|
|
3334
|
-
|
|
3335
|
-
|
|
3549
|
+
horizontalVirtualizationThreshold = 500,
|
|
3550
|
+
lines
|
|
3336
3551
|
} = editor;
|
|
3552
|
+
const {
|
|
3553
|
+
width
|
|
3554
|
+
} = getHorizontalScrollDimensions(editor);
|
|
3337
3555
|
const visibleLineIndices = (editor.visibleLineIndices ?? Array.from({
|
|
3338
3556
|
length: Math.max(0, Math.min(editor.maxLineY ?? editor.minLineY + editor.numberOfVisibleLines, lines.length) - editor.minLineY)
|
|
3339
3557
|
}, (_, index) => editor.minLineY + index)).filter(rowIndex => rowIndex >= 0 && rowIndex < lines.length);
|
|
3340
3558
|
if (visibleLineIndices.length === 0) {
|
|
3341
3559
|
return {
|
|
3342
3560
|
differences: [],
|
|
3561
|
+
horizontalVisibleRanges: [],
|
|
3343
3562
|
textInfos: []
|
|
3344
3563
|
};
|
|
3345
3564
|
}
|
|
@@ -3356,6 +3575,7 @@ const getVisible$1 = async (editor, syncIncremental) => {
|
|
|
3356
3575
|
if (editor.lifecycle?.disposed) {
|
|
3357
3576
|
return {
|
|
3358
3577
|
differences: [],
|
|
3578
|
+
horizontalVisibleRanges: [],
|
|
3359
3579
|
textInfos: []
|
|
3360
3580
|
};
|
|
3361
3581
|
}
|
|
@@ -3370,6 +3590,7 @@ const getVisible$1 = async (editor, syncIncremental) => {
|
|
|
3370
3590
|
if (editor.lifecycle?.disposed) {
|
|
3371
3591
|
return {
|
|
3372
3592
|
differences: [],
|
|
3593
|
+
horizontalVisibleRanges: [],
|
|
3373
3594
|
textInfos: []
|
|
3374
3595
|
};
|
|
3375
3596
|
}
|
|
@@ -3377,11 +3598,15 @@ const getVisible$1 = async (editor, syncIncremental) => {
|
|
|
3377
3598
|
const averageCharWidth = charWidth;
|
|
3378
3599
|
const {
|
|
3379
3600
|
differences: allDifferences,
|
|
3601
|
+
horizontalVisibleRanges: allHorizontalVisibleRanges,
|
|
3380
3602
|
result: allTextInfos
|
|
3381
|
-
} = getLineInfosViewport(editor, tokens, embeddedResults, minLineY, maxLineY, minLineOffset, width, deltaX, averageCharWidth);
|
|
3603
|
+
} = await getLineInfosViewport(editor, tokens, embeddedResults, minLineY, maxLineY, minLineOffset, width, deltaX, averageCharWidth, horizontalVirtualizationThreshold);
|
|
3382
3604
|
const relativeIndices = visibleLineIndices.map(rowIndex => rowIndex - minLineY);
|
|
3383
3605
|
return {
|
|
3384
3606
|
differences: relativeIndices.map(index => allDifferences[index]),
|
|
3607
|
+
horizontalVisibleRanges: allHorizontalVisibleRanges.filter(({
|
|
3608
|
+
rowIndex
|
|
3609
|
+
}) => visibleLineIndices.includes(rowIndex)),
|
|
3385
3610
|
textInfos: relativeIndices.map(index => allTextInfos[index])
|
|
3386
3611
|
};
|
|
3387
3612
|
};
|
|
@@ -3430,11 +3655,13 @@ const setDeltaY$1 = async (state, value) => {
|
|
|
3430
3655
|
const syncIncremental = getEnabled();
|
|
3431
3656
|
const {
|
|
3432
3657
|
differences,
|
|
3658
|
+
horizontalVisibleRanges,
|
|
3433
3659
|
textInfos
|
|
3434
3660
|
} = await getVisible$1(newEditor1, syncIncremental);
|
|
3435
3661
|
const newEditor2 = {
|
|
3436
3662
|
...newEditor1,
|
|
3437
3663
|
differences,
|
|
3664
|
+
horizontalVisibleRanges,
|
|
3438
3665
|
textInfos
|
|
3439
3666
|
};
|
|
3440
3667
|
return newEditor2;
|
|
@@ -3461,6 +3688,11 @@ const getIncrementalEdits = async (oldState, newState) => {
|
|
|
3461
3688
|
} = newState;
|
|
3462
3689
|
const oldLine = oldState.lines[rowIndex];
|
|
3463
3690
|
const newLine = lines[rowIndex];
|
|
3691
|
+
// Renderer edit offsets address full lines, so clipped rows need a fresh visible window.
|
|
3692
|
+
const threshold = newState.horizontalVirtualizationThreshold ?? 500;
|
|
3693
|
+
if (newState.deltaX !== 0 || oldLine.length > threshold || newLine.length > threshold) {
|
|
3694
|
+
return emptyIncrementalEdits;
|
|
3695
|
+
}
|
|
3464
3696
|
// @ts-ignore
|
|
3465
3697
|
const incrementalEdits = await invoke$b(
|
|
3466
3698
|
// @ts-ignore
|
|
@@ -3878,7 +4110,7 @@ const invoke$a = async (method, ...args) => {
|
|
|
3878
4110
|
const invoke$9 = async (applicationId, method, ...args) => {
|
|
3879
4111
|
return applicationId === undefined ? invoke$d(method, ...args) : invoke$d('Application.execute', applicationId, method, ...args);
|
|
3880
4112
|
};
|
|
3881
|
-
const readFile = async (applicationId, uri) => {
|
|
4113
|
+
const readFile$1 = async (applicationId, uri) => {
|
|
3882
4114
|
return applicationId === undefined ? invoke$a('FileSystem.readFile', uri) : invoke$a('ApplicationFileSystem.execute', applicationId, 'readFile', uri);
|
|
3883
4115
|
};
|
|
3884
4116
|
|
|
@@ -3911,31 +4143,6 @@ const getTabCount = string => {
|
|
|
3911
4143
|
return count;
|
|
3912
4144
|
};
|
|
3913
4145
|
|
|
3914
|
-
const RE_ASCII = /^\p{ASCII}*$/u;
|
|
3915
|
-
const isAscii = line => {
|
|
3916
|
-
return RE_ASCII.test(line);
|
|
3917
|
-
};
|
|
3918
|
-
|
|
3919
|
-
const measureTextWidthFast = async (text, charWidth) => {
|
|
3920
|
-
return text.length * charWidth;
|
|
3921
|
-
};
|
|
3922
|
-
|
|
3923
|
-
const measureTextWidthSlow = async (text, fontWeight, fontSize, fontFamily, letterSpacing, isMonoSpaceFont, charWidth) => {
|
|
3924
|
-
const width = await invoke$e('TextMeasurement.measureTextWidth', text, fontWeight, fontSize, fontFamily, letterSpacing, isMonoSpaceFont, charWidth);
|
|
3925
|
-
return width;
|
|
3926
|
-
};
|
|
3927
|
-
|
|
3928
|
-
const measureTextWidth = async (text, fontWeight, fontSize, fontFamily, letterSpacing, isMonoSpaceFont, charWidth) => {
|
|
3929
|
-
// TODO maybe have a property for the whole text document
|
|
3930
|
-
// whether the document is ASCII or not
|
|
3931
|
-
// so that it doesn't need to be checked on every cursor change
|
|
3932
|
-
// or scroll position change
|
|
3933
|
-
if (isMonoSpaceFont && isAscii(text)) {
|
|
3934
|
-
return await measureTextWidthFast(text, charWidth);
|
|
3935
|
-
}
|
|
3936
|
-
return await measureTextWidthSlow(text, fontWeight, fontSize, fontFamily, letterSpacing, isMonoSpaceFont, charWidth);
|
|
3937
|
-
};
|
|
3938
|
-
|
|
3939
4146
|
const getX = async (line, column, fontWeight, fontSize, fontFamily, isMonospaceFont, letterSpacing, tabSize, halfCursorWidth, width, averageCharWidth, difference = 0) => {
|
|
3940
4147
|
if (!line) {
|
|
3941
4148
|
return 0;
|
|
@@ -4409,11 +4616,13 @@ const scheduleDocumentAndCursorsSelections = async (editor, changes, selectionCh
|
|
|
4409
4616
|
const syncIncremental = getEnabled();
|
|
4410
4617
|
const {
|
|
4411
4618
|
differences,
|
|
4619
|
+
horizontalVisibleRanges,
|
|
4412
4620
|
textInfos
|
|
4413
4621
|
} = await getVisible$1(newEditor2, syncIncremental);
|
|
4414
4622
|
return {
|
|
4415
4623
|
...newEditor2,
|
|
4416
4624
|
differences,
|
|
4625
|
+
horizontalVisibleRanges,
|
|
4417
4626
|
textInfos
|
|
4418
4627
|
};
|
|
4419
4628
|
};
|
|
@@ -4448,11 +4657,13 @@ const scheduleDocumentAndCursorsSelectionIsUndo = async (editor, changes, select
|
|
|
4448
4657
|
const syncIncremental = getEnabled();
|
|
4449
4658
|
const {
|
|
4450
4659
|
differences,
|
|
4660
|
+
horizontalVisibleRanges,
|
|
4451
4661
|
textInfos
|
|
4452
4662
|
} = await getVisible$1(finalEditor, syncIncremental);
|
|
4453
4663
|
return {
|
|
4454
4664
|
...finalEditor,
|
|
4455
4665
|
differences,
|
|
4666
|
+
horizontalVisibleRanges,
|
|
4456
4667
|
textInfos
|
|
4457
4668
|
};
|
|
4458
4669
|
};
|
|
@@ -4492,11 +4703,13 @@ const scheduleDocument = async (editor, changes) => {
|
|
|
4492
4703
|
const syncIncremental = getEnabled();
|
|
4493
4704
|
const {
|
|
4494
4705
|
differences,
|
|
4706
|
+
horizontalVisibleRanges,
|
|
4495
4707
|
textInfos
|
|
4496
4708
|
} = await getVisible$1(finalEditor, syncIncremental);
|
|
4497
4709
|
return {
|
|
4498
4710
|
...finalEditor,
|
|
4499
4711
|
differences,
|
|
4712
|
+
horizontalVisibleRanges,
|
|
4500
4713
|
textInfos
|
|
4501
4714
|
};
|
|
4502
4715
|
// RendererProcess.send([
|
|
@@ -5140,6 +5353,69 @@ const getVisibleDiagnostics = async (editor, diagnostics) => {
|
|
|
5140
5353
|
return visibleDiagnostics;
|
|
5141
5354
|
};
|
|
5142
5355
|
|
|
5356
|
+
// Owned by the editor lifecycle, with only the current document's distinct lines retained.
|
|
5357
|
+
const caches = new WeakMap();
|
|
5358
|
+
const updateHorizontalLayout = async state => {
|
|
5359
|
+
const {
|
|
5360
|
+
breakPoints = [],
|
|
5361
|
+
deltaX,
|
|
5362
|
+
gutterDecorations = [],
|
|
5363
|
+
largeFile,
|
|
5364
|
+
lifecycle,
|
|
5365
|
+
lightBulbRowIndex = -1,
|
|
5366
|
+
lineNumbers
|
|
5367
|
+
} = state;
|
|
5368
|
+
if (largeFile || lifecycle?.disposed) {
|
|
5369
|
+
return state;
|
|
5370
|
+
}
|
|
5371
|
+
const {
|
|
5372
|
+
charWidth,
|
|
5373
|
+
fontFamily,
|
|
5374
|
+
fontSize,
|
|
5375
|
+
fontWeight,
|
|
5376
|
+
isMonospaceFont,
|
|
5377
|
+
letterSpacing,
|
|
5378
|
+
lines,
|
|
5379
|
+
tabSize,
|
|
5380
|
+
width
|
|
5381
|
+
} = state;
|
|
5382
|
+
const font = JSON.stringify([charWidth, fontFamily, fontSize, fontWeight, isMonospaceFont, letterSpacing, tabSize]);
|
|
5383
|
+
const owner = lifecycle || lines;
|
|
5384
|
+
const previous = caches.get(owner);
|
|
5385
|
+
const previousWidths = previous?.font === font ? previous.widths : undefined;
|
|
5386
|
+
const widths = new Map();
|
|
5387
|
+
let longestLineWidth = 0;
|
|
5388
|
+
for (const line of lines) {
|
|
5389
|
+
let measured = widths.get(line) ?? previousWidths?.get(line);
|
|
5390
|
+
if (measured === undefined) {
|
|
5391
|
+
measured = await measureTextWidth(line.replaceAll('\t', () => ' '.repeat(tabSize)), fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
|
|
5392
|
+
}
|
|
5393
|
+
widths.set(line, measured);
|
|
5394
|
+
longestLineWidth = Math.max(longestLineWidth, measured);
|
|
5395
|
+
}
|
|
5396
|
+
const showGutter = lineNumbers || breakPoints.length > 0 || lightBulbRowIndex >= 0 || gutterDecorations.length > 0;
|
|
5397
|
+
const gutterText = String(lines.length);
|
|
5398
|
+
let gutterWidth = 0;
|
|
5399
|
+
if (showGutter) {
|
|
5400
|
+
const measured = widths.get(gutterText) ?? previousWidths?.get(gutterText) ?? (await measureTextWidth(gutterText, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth));
|
|
5401
|
+
widths.set(gutterText, measured);
|
|
5402
|
+
gutterWidth = Math.max(30, measured + 1);
|
|
5403
|
+
}
|
|
5404
|
+
if (lifecycle?.disposed) {
|
|
5405
|
+
return state;
|
|
5406
|
+
}
|
|
5407
|
+
caches.set(owner, {
|
|
5408
|
+
font,
|
|
5409
|
+
widths
|
|
5410
|
+
});
|
|
5411
|
+
return {
|
|
5412
|
+
...state,
|
|
5413
|
+
deltaX: clamp(deltaX, 0, Math.max(0, longestLineWidth - Math.max(0, width - gutterWidth))),
|
|
5414
|
+
gutterWidth,
|
|
5415
|
+
longestLineWidth
|
|
5416
|
+
};
|
|
5417
|
+
};
|
|
5418
|
+
|
|
5143
5419
|
const shouldUpdateDiagnosticData = (oldState, newState) => {
|
|
5144
5420
|
return oldState.diagnostics !== newState.diagnostics || (newState.diagnostics?.length ?? 0) > 0 && (oldState.minLineY !== newState.minLineY || oldState.charWidth !== newState.charWidth || oldState.fontFamily !== newState.fontFamily || oldState.fontSize !== newState.fontSize || oldState.fontWeight !== newState.fontWeight || oldState.isMonospaceFont !== newState.isMonospaceFont || oldState.letterSpacing !== newState.letterSpacing || oldState.lines !== newState.lines || oldState.rowHeight !== newState.rowHeight || oldState.tabSize !== newState.tabSize || oldState.width !== newState.width);
|
|
5145
5421
|
};
|
|
@@ -5154,10 +5430,10 @@ const shouldUpdateBracketMatchData = (oldState, newState) => {
|
|
|
5154
5430
|
};
|
|
5155
5431
|
const shouldUpdateLightBulb = (oldState, newState) => oldState.diagnostics !== newState.diagnostics || oldState.languageId !== newState.languageId || oldState.selections !== newState.selections || oldState.uri !== newState.uri;
|
|
5156
5432
|
const shouldUpdateVisibleTextData = (oldState, newState) => {
|
|
5157
|
-
if (oldState.textInfos !== newState.textInfos || oldState.differences !== newState.differences) {
|
|
5433
|
+
if (oldState.deltaX === newState.deltaX && (oldState.textInfos !== newState.textInfos || oldState.differences !== newState.differences)) {
|
|
5158
5434
|
return false;
|
|
5159
5435
|
}
|
|
5160
|
-
return oldState.lines !== newState.lines || oldState.tokenizerId !== newState.tokenizerId || oldState.minLineY !== newState.minLineY || oldState.maxLineY !== newState.maxLineY || oldState.visibleLineIndices !== newState.visibleLineIndices || oldState.visibleViewLineIndices !== newState.visibleViewLineIndices || oldState.decorations !== newState.decorations || oldState.embeds !== newState.embeds || oldState.deltaX !== newState.deltaX || oldState.width !== newState.width || oldState.highlightedLine !== newState.highlightedLine || oldState.foldingRanges !== newState.foldingRanges || oldState.debugEnabled !== newState.debugEnabled;
|
|
5436
|
+
return oldState.lines !== newState.lines || oldState.tokenizerId !== newState.tokenizerId || oldState.minLineY !== newState.minLineY || oldState.maxLineY !== newState.maxLineY || oldState.visibleLineIndices !== newState.visibleLineIndices || oldState.visibleViewLineIndices !== newState.visibleViewLineIndices || oldState.decorations !== newState.decorations || oldState.embeds !== newState.embeds || oldState.deltaX !== newState.deltaX || oldState.width !== newState.width || oldState.charWidth !== newState.charWidth || oldState.tabSize !== newState.tabSize || oldState.horizontalVirtualizationThreshold !== newState.horizontalVirtualizationThreshold || oldState.fontFamily !== newState.fontFamily || oldState.fontSize !== newState.fontSize || oldState.fontWeight !== newState.fontWeight || oldState.letterSpacing !== newState.letterSpacing || oldState.isMonospaceFont !== newState.isMonospaceFont || oldState.highlightedLine !== newState.highlightedLine || oldState.foldingRanges !== newState.foldingRanges || oldState.debugEnabled !== newState.debugEnabled;
|
|
5161
5437
|
};
|
|
5162
5438
|
const shouldUpdateMinimapData = (oldState, newState) => {
|
|
5163
5439
|
return newState.minimapEnabled && (!oldState.minimapEnabled || oldState.lines !== newState.lines || oldState.tokenizerId !== newState.tokenizerId);
|
|
@@ -5174,7 +5450,8 @@ const mergeConflictsEqual$1 = (oldState, newState) => {
|
|
|
5174
5450
|
});
|
|
5175
5451
|
};
|
|
5176
5452
|
const updateDerivedState = async (oldState, newState) => {
|
|
5177
|
-
const
|
|
5453
|
+
const horizontalState = oldState.initial || oldState.lines !== newState.lines || oldState.width !== newState.width || oldState.charWidth !== newState.charWidth || oldState.fontFamily !== newState.fontFamily || oldState.fontSize !== newState.fontSize || oldState.fontWeight !== newState.fontWeight || oldState.isMonospaceFont !== newState.isMonospaceFont || oldState.letterSpacing !== newState.letterSpacing || oldState.tabSize !== newState.tabSize || oldState.lineNumbers !== newState.lineNumbers || oldState.breakPoints !== newState.breakPoints || oldState.gutterDecorations !== newState.gutterDecorations || oldState.lightBulbRowIndex !== newState.lightBulbRowIndex ? await updateHorizontalLayout(newState) : newState;
|
|
5454
|
+
const layoutState = oldState.lines !== newState.lines && 'foldingRanges' in newState ? updateLayout(horizontalState, []) : horizontalState;
|
|
5178
5455
|
const nextState = mergeConflictsEqual$1(oldState, layoutState) ? layoutState : {
|
|
5179
5456
|
...layoutState,
|
|
5180
5457
|
incrementalEdits: emptyIncrementalEdits
|
|
@@ -5186,15 +5463,17 @@ const updateDerivedState = async (oldState, newState) => {
|
|
|
5186
5463
|
documentSymbols: await getDocumentSymbols(nextState)
|
|
5187
5464
|
};
|
|
5188
5465
|
}
|
|
5189
|
-
if (shouldUpdateVisibleTextData(oldState, nextState)) {
|
|
5466
|
+
if (newState.deltaX !== nextState.deltaX || newState.gutterWidth !== nextState.gutterWidth || shouldUpdateVisibleTextData(oldState, nextState)) {
|
|
5190
5467
|
const syncIncremental = getEnabled();
|
|
5191
5468
|
const {
|
|
5192
5469
|
differences,
|
|
5470
|
+
horizontalVisibleRanges,
|
|
5193
5471
|
textInfos
|
|
5194
5472
|
} = await getVisible$1(nextState, syncIncremental);
|
|
5195
5473
|
finalState = {
|
|
5196
5474
|
...finalState,
|
|
5197
5475
|
differences,
|
|
5476
|
+
horizontalVisibleRanges,
|
|
5198
5477
|
textInfos
|
|
5199
5478
|
};
|
|
5200
5479
|
}
|
|
@@ -5907,7 +6186,7 @@ const isEqual$5 = (oldState, newState) => {
|
|
|
5907
6186
|
};
|
|
5908
6187
|
|
|
5909
6188
|
const isEqual$4 = (oldState, newState) => {
|
|
5910
|
-
return oldState.rowHeight === newState.rowHeight && oldState.deltaY === newState.deltaY && oldState.finalDeltaY === newState.finalDeltaY && oldState.height === newState.height && oldState.deltaX === newState.deltaX && oldState.longestLineWidth === newState.longestLineWidth && oldState.minimumSliderSize === newState.minimumSliderSize && oldState.width === newState.width && oldState.scrollBarHeight === newState.scrollBarHeight;
|
|
6189
|
+
return oldState.rowHeight === newState.rowHeight && oldState.deltaY === newState.deltaY && oldState.finalDeltaY === newState.finalDeltaY && oldState.height === newState.height && oldState.deltaX === newState.deltaX && oldState.gutterWidth === newState.gutterWidth && oldState.longestLineWidth === newState.longestLineWidth && oldState.minimumSliderSize === newState.minimumSliderSize && oldState.width === newState.width && oldState.scrollBarHeight === newState.scrollBarHeight;
|
|
5911
6190
|
};
|
|
5912
6191
|
|
|
5913
6192
|
const isEqual$3 = (oldState, newState) => {
|
|
@@ -5924,7 +6203,7 @@ const isEqual$3 = (oldState, newState) => {
|
|
|
5924
6203
|
};
|
|
5925
6204
|
|
|
5926
6205
|
const isEqual$2 = (oldState, newState) => {
|
|
5927
|
-
return oldState.breadcrumbFileIcon === newState.breadcrumbFileIcon && oldState.breadcrumbsEnabled === newState.breadcrumbsEnabled && oldState.breakPoints === newState.breakPoints && oldState.bracketMatchInfos === newState.bracketMatchInfos && oldState.cursorInfos === newState.cursorInfos && oldState.diagnostics === newState.diagnostics && oldState.documentSymbols === newState.documentSymbols && oldState.endOfLineDecorations === newState.endOfLineDecorations && oldState.focused === newState.focused && oldState.gutterDecorations === newState.gutterDecorations && oldState.highlightActiveLineNumber === newState.highlightActiveLineNumber && oldState.highlightedLine === newState.highlightedLine && oldState.problemsHighlightedRow === newState.problemsHighlightedRow && oldState.lineNumbers === newState.lineNumbers && oldState.loadError === newState.loadError && oldState.textInfos === newState.textInfos && oldState.visibleViewLineIndices === newState.visibleViewLineIndices && oldState.differences === newState.differences && oldState.initial === newState.initial && oldState.scrollBarHeight === newState.scrollBarHeight && oldState.width === newState.width && oldState.longestLineWidth === newState.longestLineWidth && oldState.minimumSliderSize === newState.minimumSliderSize && oldState.selectionInfos === newState.selectionInfos && oldState.selections === newState.selections && oldState.workspaceUri === newState.workspaceUri;
|
|
6206
|
+
return oldState.breadcrumbFileIcon === newState.breadcrumbFileIcon && oldState.breadcrumbsEnabled === newState.breadcrumbsEnabled && oldState.breakPoints === newState.breakPoints && oldState.bracketMatchInfos === newState.bracketMatchInfos && oldState.cursorInfos === newState.cursorInfos && oldState.diagnostics === newState.diagnostics && oldState.documentSymbols === newState.documentSymbols && oldState.endOfLineDecorations === newState.endOfLineDecorations && oldState.focused === newState.focused && oldState.gutterDecorations === newState.gutterDecorations && oldState.highlightActiveLineNumber === newState.highlightActiveLineNumber && oldState.highlightedLine === newState.highlightedLine && oldState.problemsHighlightedRow === newState.problemsHighlightedRow && oldState.lineNumbers === newState.lineNumbers && oldState.loadError === newState.loadError && oldState.textInfos === newState.textInfos && oldState.visibleViewLineIndices === newState.visibleViewLineIndices && oldState.differences === newState.differences && oldState.initial === newState.initial && oldState.scrollBarHeight === newState.scrollBarHeight && oldState.width === newState.width && oldState.gutterWidth === newState.gutterWidth && oldState.longestLineWidth === newState.longestLineWidth && oldState.minimumSliderSize === newState.minimumSliderSize && oldState.selectionInfos === newState.selectionInfos && oldState.selections === newState.selections && oldState.workspaceUri === newState.workspaceUri;
|
|
5928
6207
|
};
|
|
5929
6208
|
|
|
5930
6209
|
const isEqual$1 = (oldState, newState) => {
|
|
@@ -7356,7 +7635,7 @@ const at = async (editor, eventX, eventY) => {
|
|
|
7356
7635
|
};
|
|
7357
7636
|
}
|
|
7358
7637
|
const rowIndex = viewLineIndices ? getDocumentRowForVisualRow$1(visualRowIndex, viewLineIndices) : getDocumentRowForVisualRow(visualRowIndex, foldingRanges);
|
|
7359
|
-
const relativeX = eventX - x - gutterWidth + deltaX;
|
|
7638
|
+
const relativeX = Math.max(0, eventX - x - gutterWidth + deltaX);
|
|
7360
7639
|
const clampedRowIndex = clamp(rowIndex, 0, lines.length - 1);
|
|
7361
7640
|
const line = lines[clampedRowIndex];
|
|
7362
7641
|
const columnIndex = await getAccurateColumnIndex(line, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth, tabSize, relativeX);
|
|
@@ -7709,7 +7988,10 @@ const wrapCommand$1 = (fn, preservesTypingCoalescing = false, returnState = true
|
|
|
7709
7988
|
return returnState ? newEditor : undefined;
|
|
7710
7989
|
}
|
|
7711
7990
|
const newEditorWithDerivedState = await updateDerivedState(state, newEditor);
|
|
7712
|
-
|
|
7991
|
+
// Another command can commit before the renderer consumes this edit.
|
|
7992
|
+
// Keep its last rendered baseline, including renders completed while we awaited derived state.
|
|
7993
|
+
const renderedState = get$8(uid)?.oldState ?? oldInstance.oldState;
|
|
7994
|
+
set$a(uid, renderedState, newEditorWithDerivedState);
|
|
7713
7995
|
await dispose$3();
|
|
7714
7996
|
if (editorDiagnosticEffect.isActive(state, newEditorWithDerivedState)) {
|
|
7715
7997
|
void editorDiagnosticEffect.apply(newEditorWithDerivedState);
|
|
@@ -7853,7 +8135,7 @@ const applyWorkspaceEdit = async (editor, changes) => {
|
|
|
7853
8135
|
}
|
|
7854
8136
|
continue;
|
|
7855
8137
|
}
|
|
7856
|
-
const text = await readFile(editor.applicationId, uri);
|
|
8138
|
+
const text = await readFile$1(editor.applicationId, uri);
|
|
7857
8139
|
const newText = applyEditsToText(text, edits);
|
|
7858
8140
|
await invoke$9(editor.applicationId, 'FileSystem.writeFile', uri, newText);
|
|
7859
8141
|
}
|
|
@@ -11259,56 +11541,25 @@ const handlePointerUp = async editor => {
|
|
|
11259
11541
|
}
|
|
11260
11542
|
};
|
|
11261
11543
|
|
|
11262
|
-
// @ts-ignore
|
|
11263
|
-
|
|
11264
|
-
// @ts-ignore
|
|
11265
|
-
const getNewPercent$1 = (size, scrollBarSize, relativeX) => {
|
|
11266
|
-
if (relativeX <= 0) {
|
|
11267
|
-
return 0;
|
|
11268
|
-
}
|
|
11269
|
-
// if (relativeY <= editor.scrollBarHeight / 2) {
|
|
11270
|
-
// // clicked at top
|
|
11271
|
-
// return 0
|
|
11272
|
-
// }
|
|
11273
|
-
if (relativeX <= size - scrollBarSize / 2) {
|
|
11274
|
-
// clicked in middle
|
|
11275
|
-
return relativeX / (size - scrollBarSize);
|
|
11276
|
-
}
|
|
11277
|
-
// clicked at bottom
|
|
11278
|
-
return 1;
|
|
11279
|
-
};
|
|
11280
|
-
|
|
11281
|
-
// @ts-ignore
|
|
11282
11544
|
const handleScrollBarHorizontalMove = (state, eventX) => {
|
|
11283
11545
|
const {
|
|
11284
11546
|
handleOffsetX,
|
|
11285
11547
|
longestLineWidth,
|
|
11548
|
+
minimumSliderSize
|
|
11549
|
+
} = state;
|
|
11550
|
+
const {
|
|
11286
11551
|
width,
|
|
11287
11552
|
x
|
|
11288
|
-
} = state;
|
|
11289
|
-
|
|
11290
|
-
|
|
11291
|
-
|
|
11292
|
-
deltaX: 0,
|
|
11293
|
-
scrollBarWidth: 0
|
|
11294
|
-
};
|
|
11295
|
-
}
|
|
11296
|
-
const spaceRight = 20; // TODO make this configurable
|
|
11297
|
-
const normalizedEventX = clamp(eventX, x, x + width);
|
|
11298
|
-
const relativeX = normalizedEventX - x - handleOffsetX;
|
|
11299
|
-
const scrollBarWidth = getScrollBarWidth(width, longestLineWidth);
|
|
11300
|
-
const finalDeltaX = longestLineWidth - width + spaceRight;
|
|
11301
|
-
const newPercent = getNewPercent$1(width, scrollBarWidth, relativeX);
|
|
11302
|
-
const clampedPercent = clamp(newPercent, 0, 1);
|
|
11303
|
-
const newDeltaX = clampedPercent * finalDeltaX;
|
|
11553
|
+
} = getHorizontalScrollDimensions(state);
|
|
11554
|
+
const scrollBarWidth = getScrollBarSize(width, longestLineWidth, minimumSliderSize);
|
|
11555
|
+
const travel = width - scrollBarWidth;
|
|
11556
|
+
const percent = travel > 0 ? clamp((eventX - x - handleOffsetX) / travel, 0, 1) : 0;
|
|
11304
11557
|
return {
|
|
11305
11558
|
...state,
|
|
11306
|
-
deltaX:
|
|
11559
|
+
deltaX: percent * Math.max(0, longestLineWidth - width)
|
|
11307
11560
|
};
|
|
11308
11561
|
};
|
|
11309
11562
|
|
|
11310
|
-
// @ts-ignore
|
|
11311
|
-
|
|
11312
11563
|
// TODO duplicate code with vertical pointer down event listener
|
|
11313
11564
|
|
|
11314
11565
|
// @ts-ignore
|
|
@@ -11317,12 +11568,15 @@ const handleScrollBarHorizontalPointerDown = (state, eventX) => {
|
|
|
11317
11568
|
const {
|
|
11318
11569
|
deltaX,
|
|
11319
11570
|
longestLineWidth,
|
|
11571
|
+
minimumSliderSize
|
|
11572
|
+
} = state;
|
|
11573
|
+
const {
|
|
11320
11574
|
width,
|
|
11321
11575
|
x
|
|
11322
|
-
} = state;
|
|
11576
|
+
} = getHorizontalScrollDimensions(state);
|
|
11323
11577
|
const relativeX = eventX - x;
|
|
11324
|
-
const scrollBarWidth =
|
|
11325
|
-
const finalDeltaX =
|
|
11578
|
+
const scrollBarWidth = getScrollBarSize(width, longestLineWidth, minimumSliderSize);
|
|
11579
|
+
const finalDeltaX = Math.max(0, longestLineWidth - width);
|
|
11326
11580
|
const currentScrollBarX = getScrollBarOffset(deltaX, finalDeltaX, width, scrollBarWidth);
|
|
11327
11581
|
const diff = relativeX - currentScrollBarX;
|
|
11328
11582
|
if (diff >= 0 && diff < scrollBarWidth) {
|
|
@@ -11455,7 +11709,7 @@ const scrollByLines = (editor, lineCount) => {
|
|
|
11455
11709
|
};
|
|
11456
11710
|
|
|
11457
11711
|
// @ts-ignore
|
|
11458
|
-
const setDelta = (editor, deltaMode, eventDeltaX, eventDeltaY) => {
|
|
11712
|
+
const setDelta = async (editor, deltaMode, eventDeltaX, eventDeltaY) => {
|
|
11459
11713
|
number(deltaMode);
|
|
11460
11714
|
number(eventDeltaX);
|
|
11461
11715
|
number(eventDeltaY);
|
|
@@ -11463,12 +11717,15 @@ const setDelta = (editor, deltaMode, eventDeltaX, eventDeltaY) => {
|
|
|
11463
11717
|
const {
|
|
11464
11718
|
deltaX
|
|
11465
11719
|
} = editor;
|
|
11720
|
+
const {
|
|
11721
|
+
width
|
|
11722
|
+
} = getHorizontalScrollDimensions(editor);
|
|
11466
11723
|
if (eventDeltaX === 0) {
|
|
11467
11724
|
return setDeltaY(editor, eventDeltaY);
|
|
11468
11725
|
}
|
|
11469
|
-
const newDeltaX = clamp(deltaX + eventDeltaX, 0,
|
|
11726
|
+
const newDeltaX = clamp(deltaX + eventDeltaX, 0, Math.max(0, editor.longestLineWidth - width));
|
|
11470
11727
|
return {
|
|
11471
|
-
...setDeltaY(editor, eventDeltaY),
|
|
11728
|
+
...(await setDeltaY(editor, eventDeltaY)),
|
|
11472
11729
|
deltaX: newDeltaX
|
|
11473
11730
|
};
|
|
11474
11731
|
};
|
|
@@ -16028,6 +16285,7 @@ const DEFAULT_HOVER_DELAY = 200;
|
|
|
16028
16285
|
const DEFAULT_MESSAGE_DELAY = 3000;
|
|
16029
16286
|
const MAX_MESSAGE_DELAY = 10_000;
|
|
16030
16287
|
const DEFAULT_SELECTED_TEXT_OCCURRENCE_MATCHING = 'caseSensitive';
|
|
16288
|
+
const DEFAULT_HORIZONTAL_VIRTUALIZATION_THRESHOLD = 500;
|
|
16031
16289
|
const getSelectedTextOccurrenceMatching = value => {
|
|
16032
16290
|
return value === 'caseInsensitive' ? value : DEFAULT_SELECTED_TEXT_OCCURRENCE_MATCHING;
|
|
16033
16291
|
};
|
|
@@ -16045,8 +16303,15 @@ const getMessageDelay = value => {
|
|
|
16045
16303
|
}
|
|
16046
16304
|
return delay;
|
|
16047
16305
|
};
|
|
16306
|
+
const getHorizontalVirtualizationThreshold = value => {
|
|
16307
|
+
const threshold = typeof value === 'number' ? value : Number(value);
|
|
16308
|
+
if (!Number.isFinite(threshold) || threshold < 0 || threshold > 100_000) {
|
|
16309
|
+
return DEFAULT_HORIZONTAL_VIRTUALIZATION_THRESHOLD;
|
|
16310
|
+
}
|
|
16311
|
+
return Math.floor(threshold);
|
|
16312
|
+
};
|
|
16048
16313
|
const getEditorPreferences = async () => {
|
|
16049
|
-
const [diagnosticsEnabled, fontFamily, fontSize, fontWeight, formatOnSave, hoverEnabled, hoverDelay, messageDelay, isAutoClosingBracketsEnabled$1, isAutoClosingQuotesEnabled$1, isAutoClosingTagsEnabled$1, isQuickSuggestionsEnabled$1, lineNumbers, highlightActiveLineNumber, rowHeight, tabSize, letterSpacing, completionTriggerCharacters, minimapEnabled, mergeConflictActionsEnabled, breadcrumbsEnabled, insertSpaces, dragAndDropEnabled, roundedSelection, combineWhitespaceTokens, selectedTextOccurrenceMatching] = await Promise.all([get$3('editor.diagnostics'), getFontFamily(), getFontSize(), getFontWeight(), get$3('editor.formatOnSave'), get$3('editor.hover'), get$3('editor.hoverDelay'), get$3('editor.messageDelay'), isAutoClosingBracketsEnabled(), isAutoClosingQuotesEnabled(), isAutoClosingTagsEnabled(), isQuickSuggestionsEnabled(), getLineNumbers(), getHighlightActiveLineNumber(), getRowHeight(), getTabSize(), getLetterSpacing(), getCompletionTriggerCharacters(), getMinimapEnabled(), getMergeConflictActionsEnabled(), get$3('breadcrumbs.enabled'), get$3('editor.insertSpaces'), get$3('editor.dragAndDrop'), get$3('editor.roundedSelection'), get$3('editor.combineWhitespaceTokens'), get$3('editor.selectedTextOccurrenceMatching')]);
|
|
16314
|
+
const [diagnosticsEnabled, fontFamily, fontSize, fontWeight, formatOnSave, hoverEnabled, hoverDelay, horizontalVirtualizationThreshold, messageDelay, isAutoClosingBracketsEnabled$1, isAutoClosingQuotesEnabled$1, isAutoClosingTagsEnabled$1, isQuickSuggestionsEnabled$1, lineNumbers, highlightActiveLineNumber, rowHeight, tabSize, letterSpacing, completionTriggerCharacters, minimapEnabled, mergeConflictActionsEnabled, breadcrumbsEnabled, insertSpaces, dragAndDropEnabled, roundedSelection, combineWhitespaceTokens, selectedTextOccurrenceMatching] = await Promise.all([get$3('editor.diagnostics'), getFontFamily(), getFontSize(), getFontWeight(), get$3('editor.formatOnSave'), get$3('editor.hover'), get$3('editor.hoverDelay'), get$3('editor.horizontalVirtualizationThreshold'), get$3('editor.messageDelay'), isAutoClosingBracketsEnabled(), isAutoClosingQuotesEnabled(), isAutoClosingTagsEnabled(), isQuickSuggestionsEnabled(), getLineNumbers(), getHighlightActiveLineNumber(), getRowHeight(), getTabSize(), getLetterSpacing(), getCompletionTriggerCharacters(), getMinimapEnabled(), getMergeConflictActionsEnabled(), get$3('breadcrumbs.enabled'), get$3('editor.insertSpaces'), get$3('editor.dragAndDrop'), get$3('editor.roundedSelection'), get$3('editor.combineWhitespaceTokens'), get$3('editor.selectedTextOccurrenceMatching')]);
|
|
16050
16315
|
return {
|
|
16051
16316
|
breadcrumbsEnabled: breadcrumbsEnabled ?? false,
|
|
16052
16317
|
combineWhitespaceTokens: combineWhitespaceTokens ?? true,
|
|
@@ -16058,6 +16323,7 @@ const getEditorPreferences = async () => {
|
|
|
16058
16323
|
fontWeight,
|
|
16059
16324
|
formatOnSave: formatOnSave ?? false,
|
|
16060
16325
|
highlightActiveLineNumber,
|
|
16326
|
+
horizontalVirtualizationThreshold: getHorizontalVirtualizationThreshold(horizontalVirtualizationThreshold),
|
|
16061
16327
|
hoverDelay: getHoverDelay(hoverDelay),
|
|
16062
16328
|
hoverEnabled: hoverEnabled ?? false,
|
|
16063
16329
|
insertSpaces: insertSpaces ?? true,
|
|
@@ -16388,6 +16654,40 @@ const intialize = async (syntaxHighlightingEnabled, syncIncremental) => {
|
|
|
16388
16654
|
};
|
|
16389
16655
|
|
|
16390
16656
|
const largeFileContentLength = 10 * 1024 * 1024;
|
|
16657
|
+
const pendingFileReads = new Map();
|
|
16658
|
+
const readFile = (applicationId, uri, forceReload) => {
|
|
16659
|
+
if (forceReload) {
|
|
16660
|
+
return readFile$1(applicationId, uri);
|
|
16661
|
+
}
|
|
16662
|
+
let applicationReads = pendingFileReads.get(applicationId);
|
|
16663
|
+
if (!applicationReads) {
|
|
16664
|
+
applicationReads = new Map();
|
|
16665
|
+
pendingFileReads.set(applicationId, applicationReads);
|
|
16666
|
+
}
|
|
16667
|
+
const pendingRead = applicationReads.get(uri);
|
|
16668
|
+
if (pendingRead) {
|
|
16669
|
+
return pendingRead;
|
|
16670
|
+
}
|
|
16671
|
+
let fileRead;
|
|
16672
|
+
const removePendingRead = () => {
|
|
16673
|
+
if (applicationReads?.get(uri) !== fileRead) {
|
|
16674
|
+
return;
|
|
16675
|
+
}
|
|
16676
|
+
applicationReads.delete(uri);
|
|
16677
|
+
if (applicationReads.size === 0) {
|
|
16678
|
+
pendingFileReads.delete(applicationId);
|
|
16679
|
+
}
|
|
16680
|
+
};
|
|
16681
|
+
fileRead = (async () => {
|
|
16682
|
+
try {
|
|
16683
|
+
return await readFile$1(applicationId, uri);
|
|
16684
|
+
} finally {
|
|
16685
|
+
removePendingRead();
|
|
16686
|
+
}
|
|
16687
|
+
})();
|
|
16688
|
+
applicationReads.set(uri, fileRead);
|
|
16689
|
+
return fileRead;
|
|
16690
|
+
};
|
|
16391
16691
|
const getWorkspaceUri = async applicationId => {
|
|
16392
16692
|
try {
|
|
16393
16693
|
return await invoke$9(applicationId, 'Workspace.getPath');
|
|
@@ -16466,6 +16766,7 @@ const loadContent = async (state, savedState, largeFile = false, focus = true, f
|
|
|
16466
16766
|
fontWeight,
|
|
16467
16767
|
formatOnSave,
|
|
16468
16768
|
highlightActiveLineNumber,
|
|
16769
|
+
horizontalVirtualizationThreshold,
|
|
16469
16770
|
hoverDelay,
|
|
16470
16771
|
hoverEnabled,
|
|
16471
16772
|
insertSpaces,
|
|
@@ -16504,6 +16805,7 @@ const loadContent = async (state, savedState, largeFile = false, focus = true, f
|
|
|
16504
16805
|
fontWeight,
|
|
16505
16806
|
formatOnSave,
|
|
16506
16807
|
highlightActiveLineNumber,
|
|
16808
|
+
horizontalVirtualizationThreshold,
|
|
16507
16809
|
hoverDelay,
|
|
16508
16810
|
hoverEnabled,
|
|
16509
16811
|
insertSpaces,
|
|
@@ -16537,7 +16839,7 @@ const loadContent = async (state, savedState, largeFile = false, focus = true, f
|
|
|
16537
16839
|
let endOfLine = existingEditor?.endOfLine || 'lf';
|
|
16538
16840
|
try {
|
|
16539
16841
|
if (!existingEditor) {
|
|
16540
|
-
content = await readFile(state.applicationId, uri);
|
|
16842
|
+
content = await readFile(state.applicationId, uri, forceReload);
|
|
16541
16843
|
endOfLine = getEndOfLine(content);
|
|
16542
16844
|
content = normalizeLineEndings(content);
|
|
16543
16845
|
}
|
|
@@ -16579,7 +16881,7 @@ const loadContent = async (state, savedState, largeFile = false, focus = true, f
|
|
|
16579
16881
|
endOfLine
|
|
16580
16882
|
}, x, y, width, height, 9);
|
|
16581
16883
|
const newEditor2 = setText$1(newEditor1, content);
|
|
16582
|
-
|
|
16884
|
+
const newEditor3 = await updateHorizontalLayout(newEditor2);
|
|
16583
16885
|
|
|
16584
16886
|
// Detect links and initialize decorations
|
|
16585
16887
|
const linkDecorations = detectAllLinksAsDecorations(newEditor3);
|
|
@@ -16603,6 +16905,7 @@ const loadContent = async (state, savedState, largeFile = false, focus = true, f
|
|
|
16603
16905
|
const syncIncremental = getEnabled();
|
|
16604
16906
|
const {
|
|
16605
16907
|
differences,
|
|
16908
|
+
horizontalVisibleRanges,
|
|
16606
16909
|
textInfos
|
|
16607
16910
|
} = await getVisible$1(newEditor3WithBreadcrumbs, syncIncremental);
|
|
16608
16911
|
const newEditor4 = {
|
|
@@ -16610,6 +16913,7 @@ const loadContent = async (state, savedState, largeFile = false, focus = true, f
|
|
|
16610
16913
|
differences,
|
|
16611
16914
|
focus: FocusEditorText$1,
|
|
16612
16915
|
focused: focus,
|
|
16916
|
+
horizontalVisibleRanges,
|
|
16613
16917
|
textInfos
|
|
16614
16918
|
};
|
|
16615
16919
|
const completionsOnTypeRaw = await get$3('editor.completionsOnType');
|
|
@@ -16849,31 +17153,27 @@ ${editorSelector} .ScrollBarThumbHorizontal {
|
|
|
16849
17153
|
`;
|
|
16850
17154
|
};
|
|
16851
17155
|
|
|
16852
|
-
const getScrollBarLeft = (deltaX, longestLineWidth, width) => {
|
|
16853
|
-
const scrollBarLeft = deltaX / longestLineWidth * width;
|
|
16854
|
-
if (!Number.isFinite(scrollBarLeft)) {
|
|
16855
|
-
return 0;
|
|
16856
|
-
}
|
|
16857
|
-
return scrollBarLeft;
|
|
16858
|
-
};
|
|
16859
17156
|
const renderCss$1 = (oldState, newState) => {
|
|
16860
17157
|
const {
|
|
16861
17158
|
deltaX,
|
|
16862
17159
|
deltaY,
|
|
16863
17160
|
finalDeltaY,
|
|
17161
|
+
gutterWidth,
|
|
16864
17162
|
height,
|
|
16865
17163
|
longestLineWidth,
|
|
16866
17164
|
minimumSliderSize,
|
|
16867
17165
|
rowHeight,
|
|
16868
17166
|
scrollBarHeight,
|
|
16869
|
-
uid
|
|
16870
|
-
width
|
|
17167
|
+
uid
|
|
16871
17168
|
} = newState;
|
|
17169
|
+
const {
|
|
17170
|
+
width
|
|
17171
|
+
} = getHorizontalScrollDimensions(newState);
|
|
16872
17172
|
const scrollBarTop = getScrollBarY(deltaY, finalDeltaY, height, scrollBarHeight);
|
|
16873
17173
|
const scrollBarWidth = getScrollBarSize(width, longestLineWidth, minimumSliderSize);
|
|
16874
|
-
const scrollBarLeft =
|
|
17174
|
+
const scrollBarLeft = getScrollBarOffset(deltaX, Math.max(0, longestLineWidth - width), width, scrollBarWidth);
|
|
16875
17175
|
const css = getCss(uid, rowHeight, scrollBarHeight, scrollBarTop, scrollBarWidth, scrollBarLeft, deltaY);
|
|
16876
|
-
return [SetCss$1, uid, css];
|
|
17176
|
+
return [SetCss$1, uid, gutterWidth ? `${css}\n.Editor[data-uid="${uid}"] .Gutter { width: ${gutterWidth}px; }\n` : css];
|
|
16877
17177
|
};
|
|
16878
17178
|
|
|
16879
17179
|
const renderFocus$2 = (oldState, newState) => {
|
|
@@ -17160,13 +17460,18 @@ const mergeConflictActions = [{
|
|
|
17160
17460
|
action: 'both',
|
|
17161
17461
|
label: 'Accept Both Changes'
|
|
17162
17462
|
}];
|
|
17163
|
-
const getUnnecessaryRanges = (diagnostics, rowIndex, textLength) => {
|
|
17463
|
+
const getUnnecessaryRanges = (diagnostics, rowIndex, textLength, visibleStartColumn, line, hasLine, tabSize) => {
|
|
17464
|
+
const visibleStart = hasLine ? getHorizontalDisplayColumn(line, visibleStartColumn, tabSize) : visibleStartColumn;
|
|
17164
17465
|
return diagnostics.filter(diagnostic => diagnostic.tags?.includes(DiagnosticTag.Unnecessary)).flatMap(diagnostic => {
|
|
17165
17466
|
if (rowIndex < diagnostic.rowIndex || rowIndex > diagnostic.endRowIndex) {
|
|
17166
17467
|
return [];
|
|
17167
17468
|
}
|
|
17168
|
-
const
|
|
17169
|
-
const
|
|
17469
|
+
const diagnosticStart = rowIndex === diagnostic.rowIndex ? diagnostic.columnIndex : 0;
|
|
17470
|
+
const diagnosticEnd = rowIndex === diagnostic.endRowIndex ? diagnostic.endColumnIndex : line.length;
|
|
17471
|
+
const startColumn = hasLine ? getHorizontalDisplayColumn(line, diagnosticStart, tabSize) : diagnosticStart;
|
|
17472
|
+
const endColumn = hasLine ? getHorizontalDisplayColumn(line, diagnosticEnd, tabSize) : diagnosticEnd;
|
|
17473
|
+
const start = Math.max(0, startColumn - visibleStart);
|
|
17474
|
+
const end = Math.min(textLength, endColumn - visibleStart);
|
|
17170
17475
|
return start < end ? [{
|
|
17171
17476
|
end,
|
|
17172
17477
|
start
|
|
@@ -17227,7 +17532,7 @@ const addMergeConflictActions = (dom, rowIndex) => {
|
|
|
17227
17532
|
}, text(label));
|
|
17228
17533
|
}
|
|
17229
17534
|
};
|
|
17230
|
-
const getEditorRowsVirtualDom$1 = (textInfos, differences, lineNumbers = true, highlightedLine = -1, visibleLineIndices = [], endOfLineDecorations = [], visibleViewLineIndices = [], problemsHighlightedRow = -1, diagnostics = []) => {
|
|
17535
|
+
const getEditorRowsVirtualDom$1 = (textInfos, differences, lineNumbers = true, highlightedLine = -1, visibleLineIndices = [], endOfLineDecorations = [], visibleViewLineIndices = [], problemsHighlightedRow = -1, diagnostics = [], deltaX = 0, width = Infinity, charWidth = 1, tabSize = 2, lines = [], horizontalVirtualizationThreshold = 500, horizontalVisibleRanges = []) => {
|
|
17231
17536
|
const dom = [];
|
|
17232
17537
|
const actualViewRows = visibleViewLineIndices.length === 0 ? Array.from({
|
|
17233
17538
|
length: textInfos.length
|
|
@@ -17241,12 +17546,14 @@ const getEditorRowsVirtualDom$1 = (textInfos, differences, lineNumbers = true, h
|
|
|
17241
17546
|
const textInfo = textInfos[textInfoIndex];
|
|
17242
17547
|
const difference = differences[textInfoIndex];
|
|
17243
17548
|
const rowIndex = viewRow;
|
|
17244
|
-
const
|
|
17549
|
+
const line = lines[rowIndex] || '';
|
|
17550
|
+
const visibleRange = horizontalVisibleRanges.find(range => range.rowIndex === rowIndex) || getHorizontalVisibleRange(line, deltaX, width, charWidth, tabSize, horizontalVirtualizationThreshold);
|
|
17551
|
+
const rowDecorations = endOfLineDecorations.filter(decoration => decoration.rowIndex === rowIndex && (!lines[rowIndex] || visibleRange.end >= line.length));
|
|
17245
17552
|
let rowTextLength = 0;
|
|
17246
17553
|
for (let index = 0; index < textInfo.length; index += 2) {
|
|
17247
17554
|
rowTextLength += textInfo[index].length;
|
|
17248
17555
|
}
|
|
17249
|
-
const tokenParts = getTokenParts(textInfo, getUnnecessaryRanges(diagnostics, rowIndex, rowTextLength));
|
|
17556
|
+
const tokenParts = getTokenParts(textInfo, getUnnecessaryRanges(diagnostics, rowIndex, rowTextLength, visibleRange.start, line, lines[rowIndex] !== undefined, tabSize));
|
|
17250
17557
|
let className = EditorRow;
|
|
17251
17558
|
if (rowIndex === highlightedLine) {
|
|
17252
17559
|
className = mergeClassNames(className, EditorRowHighlighted);
|
|
@@ -17278,8 +17585,8 @@ const getEditorRowsVirtualDom$1 = (textInfos, differences, lineNumbers = true, h
|
|
|
17278
17585
|
return dom;
|
|
17279
17586
|
};
|
|
17280
17587
|
|
|
17281
|
-
const getEditorRowsVirtualDom = (textInfos, differences, lineNumbers = true, highlightedLine = -1, visibleLineIndices = [], endOfLineDecorations = [], visibleViewLineIndices = [], problemsHighlightedRow = -1, unnecessaryDiagnostics = []) => {
|
|
17282
|
-
const rowsDom = getEditorRowsVirtualDom$1(textInfos, differences, lineNumbers, highlightedLine, visibleLineIndices, endOfLineDecorations, visibleViewLineIndices, problemsHighlightedRow, unnecessaryDiagnostics);
|
|
17588
|
+
const getEditorRowsVirtualDom = (textInfos, differences, lineNumbers = true, highlightedLine = -1, visibleLineIndices = [], endOfLineDecorations = [], visibleViewLineIndices = [], problemsHighlightedRow = -1, unnecessaryDiagnostics = [], horizontalVisibleRanges = [], lines = [], tabSize = 2) => {
|
|
17589
|
+
const rowsDom = getEditorRowsVirtualDom$1(textInfos, differences, lineNumbers, highlightedLine, visibleLineIndices, endOfLineDecorations, visibleViewLineIndices, problemsHighlightedRow, unnecessaryDiagnostics, 0, Infinity, 1, tabSize, lines, 500, horizontalVisibleRanges);
|
|
17283
17590
|
return [{
|
|
17284
17591
|
childCount: visibleViewLineIndices.length || textInfos.length,
|
|
17285
17592
|
className: 'EditorRows',
|
|
@@ -17376,8 +17683,8 @@ const editorLayersNode = {
|
|
|
17376
17683
|
className: 'EditorLayers',
|
|
17377
17684
|
type: Div
|
|
17378
17685
|
};
|
|
17379
|
-
const getEditorLayersVirtualDom = (selectionInfos, textInfos, differences, lineNumbers = true, highlightedLine = -1, cursorInfos = [], diagnostics = [], visibleLineIndices = [], endOfLineDecorations = [], bracketMatchInfos = [], focused = true, visibleViewLineIndices = [], problemsHighlightedRow = -1, roundedSelection = false, unnecessaryDiagnostics = []) => {
|
|
17380
|
-
return [editorLayersNode, ...getEditorSelectionsVirtualDom(selectionInfos, focused, roundedSelection), ...getEditorRowsVirtualDom(textInfos, differences, lineNumbers, highlightedLine, visibleLineIndices, endOfLineDecorations, visibleViewLineIndices, problemsHighlightedRow, unnecessaryDiagnostics), ...getEditorCursorsVirtualDom(cursorInfos, focused), ...getEditorDiagnosticsVirtualDom(diagnostics, bracketMatchInfos)];
|
|
17686
|
+
const getEditorLayersVirtualDom = (selectionInfos, textInfos, differences, lineNumbers = true, highlightedLine = -1, cursorInfos = [], diagnostics = [], visibleLineIndices = [], endOfLineDecorations = [], bracketMatchInfos = [], focused = true, visibleViewLineIndices = [], problemsHighlightedRow = -1, roundedSelection = false, unnecessaryDiagnostics = [], horizontalVisibleRanges = [], lines = [], tabSize = 2) => {
|
|
17687
|
+
return [editorLayersNode, ...getEditorSelectionsVirtualDom(selectionInfos, focused, roundedSelection), ...getEditorRowsVirtualDom(textInfos, differences, lineNumbers, highlightedLine, visibleLineIndices, endOfLineDecorations, visibleViewLineIndices, problemsHighlightedRow, unnecessaryDiagnostics, horizontalVisibleRanges, lines, tabSize), ...getEditorCursorsVirtualDom(cursorInfos, focused), ...getEditorDiagnosticsVirtualDom(diagnostics, bracketMatchInfos)];
|
|
17381
17688
|
};
|
|
17382
17689
|
|
|
17383
17690
|
const getEditorScrollBarDiagnosticsVirtualDom = scrollBarDiagnostics => {
|
|
@@ -17450,13 +17757,16 @@ const getEditorContentVirtualDom = ({
|
|
|
17450
17757
|
endOfLineDecorations = [],
|
|
17451
17758
|
focused = true,
|
|
17452
17759
|
highlightedLine = -1,
|
|
17760
|
+
horizontalVisibleRanges = [],
|
|
17453
17761
|
lineNumbers = true,
|
|
17762
|
+
lines = [],
|
|
17454
17763
|
problemsHighlightedRow = -1,
|
|
17455
17764
|
roundedSelection = false,
|
|
17456
17765
|
scrollBarDiagnostics = [],
|
|
17457
17766
|
scrollBarHeight = 0,
|
|
17458
17767
|
scrollBarWidth = 0,
|
|
17459
17768
|
selectionInfos = [],
|
|
17769
|
+
tabSize = 2,
|
|
17460
17770
|
textInfos,
|
|
17461
17771
|
unnecessaryDiagnostics = [],
|
|
17462
17772
|
visibleLineIndices = [],
|
|
@@ -17465,7 +17775,7 @@ const getEditorContentVirtualDom = ({
|
|
|
17465
17775
|
return [{
|
|
17466
17776
|
...editorContentNode,
|
|
17467
17777
|
className: breadcrumbsEnabled ? 'EditorContent EditorBreadcrumbsOffset' : 'EditorContent'
|
|
17468
|
-
}, ...getEditorInputVirtualDom(), ...getEditorLayersVirtualDom(selectionInfos, textInfos, differences, lineNumbers, highlightedLine, cursorInfos, diagnostics, visibleLineIndices, endOfLineDecorations, bracketMatchInfos, focused, visibleViewLineIndices, problemsHighlightedRow, roundedSelection, unnecessaryDiagnostics), ...getEditorScrollBarDiagnosticsVirtualDom(scrollBarDiagnostics), ...getScrollBarVirtualDom(scrollBarHeight, scrollBarWidth)];
|
|
17778
|
+
}, ...getEditorInputVirtualDom(), ...getEditorLayersVirtualDom(selectionInfos, textInfos, differences, lineNumbers, highlightedLine, cursorInfos, diagnostics, visibleLineIndices, endOfLineDecorations, bracketMatchInfos, focused, visibleViewLineIndices, problemsHighlightedRow, roundedSelection, unnecessaryDiagnostics, horizontalVisibleRanges, lines, tabSize), ...getEditorScrollBarDiagnosticsVirtualDom(scrollBarDiagnostics), ...getScrollBarVirtualDom(scrollBarHeight, scrollBarWidth)];
|
|
17469
17779
|
};
|
|
17470
17780
|
|
|
17471
17781
|
const getGutterInfoVirtualDom = (gutterInfo, activeLineNumber) => {
|
|
@@ -17619,6 +17929,7 @@ const getEditorVirtualDom = ({
|
|
|
17619
17929
|
gutterInfos = [],
|
|
17620
17930
|
highlightActiveLineNumber = true,
|
|
17621
17931
|
highlightedLine = -1,
|
|
17932
|
+
horizontalVisibleRanges = [],
|
|
17622
17933
|
lightBulbRowIndex = -1,
|
|
17623
17934
|
lineNumbers = true,
|
|
17624
17935
|
lines = [],
|
|
@@ -17635,6 +17946,7 @@ const getEditorVirtualDom = ({
|
|
|
17635
17946
|
scrollBarWidth = 0,
|
|
17636
17947
|
selectionInfos = [],
|
|
17637
17948
|
selections = new Uint32Array(),
|
|
17949
|
+
tabSize = 2,
|
|
17638
17950
|
textInfos,
|
|
17639
17951
|
uid,
|
|
17640
17952
|
unnecessaryDiagnostics = [],
|
|
@@ -17687,13 +17999,16 @@ const getEditorVirtualDom = ({
|
|
|
17687
17999
|
endOfLineDecorations,
|
|
17688
18000
|
focused,
|
|
17689
18001
|
highlightedLine,
|
|
18002
|
+
horizontalVisibleRanges,
|
|
17690
18003
|
lineNumbers,
|
|
18004
|
+
lines,
|
|
17691
18005
|
problemsHighlightedRow,
|
|
17692
18006
|
roundedSelection,
|
|
17693
18007
|
scrollBarDiagnostics,
|
|
17694
18008
|
scrollBarHeight,
|
|
17695
18009
|
scrollBarWidth,
|
|
17696
18010
|
selectionInfos,
|
|
18011
|
+
tabSize,
|
|
17697
18012
|
textInfos: combineWhitespaceTokens$1 ? textInfos.map(combineWhitespaceTokens) : textInfos,
|
|
17698
18013
|
unnecessaryDiagnostics,
|
|
17699
18014
|
visibleLineIndices: visibleLineIndices || [],
|
|
@@ -17861,12 +18176,14 @@ const getDom = state => {
|
|
|
17861
18176
|
longestLineWidth,
|
|
17862
18177
|
minimumSliderSize,
|
|
17863
18178
|
textInfos,
|
|
17864
|
-
visualDecorations = []
|
|
17865
|
-
width
|
|
18179
|
+
visualDecorations = []
|
|
17866
18180
|
} = state;
|
|
17867
18181
|
if (initial && textInfos.length === 0) {
|
|
17868
18182
|
return [];
|
|
17869
18183
|
}
|
|
18184
|
+
const {
|
|
18185
|
+
width
|
|
18186
|
+
} = getHorizontalScrollDimensions(state);
|
|
17870
18187
|
return getEditorVirtualDom({
|
|
17871
18188
|
...state,
|
|
17872
18189
|
diagnostics: visualDecorations,
|
|
@@ -18048,10 +18365,10 @@ const renderLines = {
|
|
|
18048
18365
|
visibleLineIndices,
|
|
18049
18366
|
visibleViewLineIndices
|
|
18050
18367
|
} = newState;
|
|
18051
|
-
const dom = getEditorRowsVirtualDom$1(textInfos, differences, true, highlightedLine, visibleLineIndices, endOfLineDecorations, visibleViewLineIndices, newState.problemsHighlightedRow, diagnostics || []);
|
|
18368
|
+
const dom = getEditorRowsVirtualDom$1(textInfos, differences, true, highlightedLine, visibleLineIndices, endOfLineDecorations, visibleViewLineIndices, newState.problemsHighlightedRow, diagnostics || [], newState.deltaX, newState.width, newState.charWidth, newState.tabSize, newState.lines, newState.horizontalVirtualizationThreshold, newState.horizontalVisibleRanges);
|
|
18052
18369
|
return [/* method */'setText', dom];
|
|
18053
18370
|
},
|
|
18054
|
-
isEqual: (oldState, newState) => oldState.lines === newState.lines && oldState.foldingRanges === newState.foldingRanges && oldState.visibleViewLineIndices === newState.visibleViewLineIndices && oldState.tokenizerId === newState.tokenizerId && oldState.minLineY === newState.minLineY && oldState.decorations === newState.decorations && oldState.embeds === newState.embeds && oldState.endOfLineDecorations === newState.endOfLineDecorations && oldState.diagnostics === newState.diagnostics && oldState.deltaX === newState.deltaX && oldState.width === newState.width && oldState.highlightedLine === newState.highlightedLine && oldState.problemsHighlightedRow === newState.problemsHighlightedRow && oldState.debugEnabled === newState.debugEnabled
|
|
18371
|
+
isEqual: (oldState, newState) => oldState.lines === newState.lines && oldState.foldingRanges === newState.foldingRanges && oldState.visibleViewLineIndices === newState.visibleViewLineIndices && oldState.tokenizerId === newState.tokenizerId && oldState.minLineY === newState.minLineY && oldState.decorations === newState.decorations && oldState.embeds === newState.embeds && oldState.endOfLineDecorations === newState.endOfLineDecorations && oldState.diagnostics === newState.diagnostics && oldState.deltaX === newState.deltaX && oldState.charWidth === newState.charWidth && oldState.tabSize === newState.tabSize && oldState.gutterWidth === newState.gutterWidth && oldState.horizontalVirtualizationThreshold === newState.horizontalVirtualizationThreshold && oldState.fontFamily === newState.fontFamily && oldState.fontSize === newState.fontSize && oldState.fontWeight === newState.fontWeight && oldState.letterSpacing === newState.letterSpacing && oldState.isMonospaceFont === newState.isMonospaceFont && oldState.width === newState.width && oldState.highlightedLine === newState.highlightedLine && oldState.problemsHighlightedRow === newState.problemsHighlightedRow && oldState.debugEnabled === newState.debugEnabled
|
|
18055
18372
|
};
|
|
18056
18373
|
const renderSelections = {
|
|
18057
18374
|
apply: (oldState, newState) => {
|
package/dist/settings.json
CHANGED
|
@@ -791,6 +791,16 @@
|
|
|
791
791
|
"minimum": 0,
|
|
792
792
|
"maximum": 10000
|
|
793
793
|
},
|
|
794
|
+
{
|
|
795
|
+
"category": "text-editor",
|
|
796
|
+
"description": "Controls the minimum line length in characters before horizontal virtualization is enabled",
|
|
797
|
+
"heading": "Horizontal Virtualization Threshold",
|
|
798
|
+
"id": "editor.horizontalVirtualizationThreshold",
|
|
799
|
+
"type": "number",
|
|
800
|
+
"value": 500,
|
|
801
|
+
"minimum": 0,
|
|
802
|
+
"maximum": 100000
|
|
803
|
+
},
|
|
794
804
|
{
|
|
795
805
|
"category": "text-editor",
|
|
796
806
|
"description": "Controls how long editor messages remain visible, in milliseconds",
|