@opentui/core 0.0.0-20251112-a24ada2d → 0.0.0-20251128-0889a764
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/3d/WGPURenderer.d.ts +2 -0
- package/3d/canvas.d.ts +2 -0
- package/3d.js +33 -2
- package/3d.js.map +4 -4
- package/README.md +5 -3
- package/buffer.d.ts +18 -0
- package/console.d.ts +2 -0
- package/edit-buffer.d.ts +1 -0
- package/editor-view.d.ts +5 -0
- package/{index-kj9k00yt.js → index-rhx7c7kj.js} +1825 -341
- package/{index-kj9k00yt.js.map → index-rhx7c7kj.js.map} +15 -15
- package/index.js +2157 -278
- package/index.js.map +25 -13
- package/lib/KeyHandler.d.ts +0 -3
- package/lib/ascii.font.d.ts +212 -5
- package/lib/extmarks.d.ts +1 -1
- package/package.json +9 -8
- package/parser.worker.js +4 -3
- package/parser.worker.js.map +3 -3
- package/renderables/ASCIIFont.d.ts +28 -19
- package/renderables/Diff.d.ts +62 -0
- package/renderables/EditBufferRenderable.d.ts +7 -2
- package/renderables/LineNumberRenderable.d.ts +71 -0
- package/renderables/ScrollBox.d.ts +3 -0
- package/renderables/TextBufferRenderable.d.ts +5 -5
- package/renderables/Textarea.d.ts +7 -4
- package/renderables/index.d.ts +2 -0
- package/renderer.d.ts +4 -1
- package/testing.js +6 -3
- package/testing.js.map +4 -4
- package/text-buffer-view.d.ts +4 -0
- package/text-buffer.d.ts +1 -0
- package/types.d.ts +12 -0
- package/zig-structs.d.ts +11 -0
- package/zig.d.ts +23 -6
package/index.js
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
LinearScrollAccel,
|
|
20
20
|
LogLevel,
|
|
21
21
|
MacOSScrollAccel,
|
|
22
|
+
MeasureMode,
|
|
22
23
|
MouseButton,
|
|
23
24
|
MouseEvent,
|
|
24
25
|
MouseParser,
|
|
@@ -136,7 +137,7 @@ import {
|
|
|
136
137
|
white,
|
|
137
138
|
wrapWithDelegates,
|
|
138
139
|
yellow
|
|
139
|
-
} from "./index-
|
|
140
|
+
} from "./index-rhx7c7kj.js";
|
|
140
141
|
// src/text-buffer-view.ts
|
|
141
142
|
class TextBufferView {
|
|
142
143
|
lib;
|
|
@@ -234,6 +235,10 @@ class TextBufferView {
|
|
|
234
235
|
this.guard();
|
|
235
236
|
this.lib.textBufferViewSetTabIndicatorColor(this.viewPtr, color);
|
|
236
237
|
}
|
|
238
|
+
measureForDimensions(width, height) {
|
|
239
|
+
this.guard();
|
|
240
|
+
return this.lib.textBufferViewMeasureForDimensions(this.viewPtr, width, height);
|
|
241
|
+
}
|
|
237
242
|
destroy() {
|
|
238
243
|
if (this._destroyed)
|
|
239
244
|
return;
|
|
@@ -319,6 +324,10 @@ class EditBuffer extends EventEmitter {
|
|
|
319
324
|
const textBytes = this.lib.encoder.encode(text);
|
|
320
325
|
this.lib.editBufferSetText(this.bufferPtr, textBytes, history);
|
|
321
326
|
}
|
|
327
|
+
getLineCount() {
|
|
328
|
+
this.guard();
|
|
329
|
+
return this.lib.textBufferGetLineCount(this.textBufferPtr);
|
|
330
|
+
}
|
|
322
331
|
getText() {
|
|
323
332
|
this.guard();
|
|
324
333
|
const maxSize = 1024 * 1024;
|
|
@@ -551,6 +560,7 @@ class EditorView {
|
|
|
551
560
|
editBuffer;
|
|
552
561
|
_destroyed = false;
|
|
553
562
|
_extmarksController;
|
|
563
|
+
_textBufferViewPtr;
|
|
554
564
|
constructor(lib, ptr, editBuffer) {
|
|
555
565
|
this.lib = lib;
|
|
556
566
|
this.viewPtr = ptr;
|
|
@@ -696,6 +706,13 @@ class EditorView {
|
|
|
696
706
|
this.guard();
|
|
697
707
|
this.lib.editorViewSetTabIndicatorColor(this.viewPtr, color);
|
|
698
708
|
}
|
|
709
|
+
measureForDimensions(width, height) {
|
|
710
|
+
this.guard();
|
|
711
|
+
if (!this._textBufferViewPtr) {
|
|
712
|
+
this._textBufferViewPtr = this.lib.editorViewGetTextBufferView(this.viewPtr);
|
|
713
|
+
}
|
|
714
|
+
return this.lib.textBufferViewMeasureForDimensions(this._textBufferViewPtr, width, height);
|
|
715
|
+
}
|
|
699
716
|
destroy() {
|
|
700
717
|
if (this._destroyed)
|
|
701
718
|
return;
|
|
@@ -2022,17 +2039,27 @@ class FrameBufferRenderable extends Renderable {
|
|
|
2022
2039
|
// src/renderables/ASCIIFont.ts
|
|
2023
2040
|
class ASCIIFontRenderable extends FrameBufferRenderable {
|
|
2024
2041
|
selectable = true;
|
|
2042
|
+
static _defaultOptions = {
|
|
2043
|
+
text: "",
|
|
2044
|
+
font: "tiny",
|
|
2045
|
+
color: "#FFFFFF",
|
|
2046
|
+
backgroundColor: "transparent",
|
|
2047
|
+
selectionBg: undefined,
|
|
2048
|
+
selectionFg: undefined,
|
|
2049
|
+
selectable: true
|
|
2050
|
+
};
|
|
2025
2051
|
_text;
|
|
2026
2052
|
_font;
|
|
2027
|
-
|
|
2028
|
-
|
|
2053
|
+
_color;
|
|
2054
|
+
_backgroundColor;
|
|
2029
2055
|
_selectionBg;
|
|
2030
2056
|
_selectionFg;
|
|
2031
2057
|
lastLocalSelection = null;
|
|
2032
2058
|
selectionHelper;
|
|
2033
2059
|
constructor(ctx, options) {
|
|
2034
|
-
const
|
|
2035
|
-
const
|
|
2060
|
+
const defaultOptions = ASCIIFontRenderable._defaultOptions;
|
|
2061
|
+
const font = options.font || defaultOptions.font;
|
|
2062
|
+
const text = options.text || defaultOptions.text;
|
|
2036
2063
|
const measurements = measureText({ text, font });
|
|
2037
2064
|
super(ctx, {
|
|
2038
2065
|
flexShrink: 0,
|
|
@@ -2043,8 +2070,8 @@ class ASCIIFontRenderable extends FrameBufferRenderable {
|
|
|
2043
2070
|
});
|
|
2044
2071
|
this._text = text;
|
|
2045
2072
|
this._font = font;
|
|
2046
|
-
this.
|
|
2047
|
-
this.
|
|
2073
|
+
this._color = options.color || defaultOptions.color;
|
|
2074
|
+
this._backgroundColor = options.backgroundColor || defaultOptions.backgroundColor;
|
|
2048
2075
|
this._selectionBg = options.selectionBg ? parseColor(options.selectionBg) : undefined;
|
|
2049
2076
|
this._selectionFg = options.selectionFg ? parseColor(options.selectionFg) : undefined;
|
|
2050
2077
|
this.selectable = options.selectable ?? true;
|
|
@@ -2075,23 +2102,19 @@ class ASCIIFontRenderable extends FrameBufferRenderable {
|
|
|
2075
2102
|
this.renderFontToBuffer();
|
|
2076
2103
|
this.requestRender();
|
|
2077
2104
|
}
|
|
2078
|
-
get
|
|
2079
|
-
return this.
|
|
2105
|
+
get color() {
|
|
2106
|
+
return this._color;
|
|
2080
2107
|
}
|
|
2081
|
-
set
|
|
2082
|
-
|
|
2083
|
-
this._fg = value.map((color) => typeof color === "string" ? parseColor(color) : color);
|
|
2084
|
-
} else {
|
|
2085
|
-
this._fg = [typeof value === "string" ? parseColor(value) : value];
|
|
2086
|
-
}
|
|
2108
|
+
set color(value) {
|
|
2109
|
+
this._color = value;
|
|
2087
2110
|
this.renderFontToBuffer();
|
|
2088
2111
|
this.requestRender();
|
|
2089
2112
|
}
|
|
2090
|
-
get
|
|
2091
|
-
return this.
|
|
2113
|
+
get backgroundColor() {
|
|
2114
|
+
return this._backgroundColor;
|
|
2092
2115
|
}
|
|
2093
|
-
set
|
|
2094
|
-
this.
|
|
2116
|
+
set backgroundColor(value) {
|
|
2117
|
+
this._backgroundColor = value;
|
|
2095
2118
|
this.renderFontToBuffer();
|
|
2096
2119
|
this.requestRender();
|
|
2097
2120
|
}
|
|
@@ -2131,13 +2154,13 @@ class ASCIIFontRenderable extends FrameBufferRenderable {
|
|
|
2131
2154
|
renderFontToBuffer() {
|
|
2132
2155
|
if (this.isDestroyed)
|
|
2133
2156
|
return;
|
|
2134
|
-
this.frameBuffer.clear(this.
|
|
2157
|
+
this.frameBuffer.clear(parseColor(this._backgroundColor));
|
|
2135
2158
|
renderFontToFrameBuffer(this.frameBuffer, {
|
|
2136
2159
|
text: this._text,
|
|
2137
2160
|
x: 0,
|
|
2138
2161
|
y: 0,
|
|
2139
|
-
|
|
2140
|
-
|
|
2162
|
+
color: this.color,
|
|
2163
|
+
backgroundColor: this._backgroundColor,
|
|
2141
2164
|
font: this._font
|
|
2142
2165
|
});
|
|
2143
2166
|
const selection = this.selectionHelper.getSelection();
|
|
@@ -2155,15 +2178,15 @@ class ASCIIFontRenderable extends FrameBufferRenderable {
|
|
|
2155
2178
|
const startX = positions[selection.start] || 0;
|
|
2156
2179
|
const endX = selection.end < positions.length ? positions[selection.end] : measureText({ text: this._text, font: this._font }).width;
|
|
2157
2180
|
if (this._selectionBg) {
|
|
2158
|
-
this.frameBuffer.fillRect(startX, 0, endX - startX, this.height, this._selectionBg);
|
|
2181
|
+
this.frameBuffer.fillRect(startX, 0, endX - startX, this.height, parseColor(this._selectionBg));
|
|
2159
2182
|
}
|
|
2160
2183
|
if (this._selectionFg || this._selectionBg) {
|
|
2161
2184
|
renderFontToFrameBuffer(this.frameBuffer, {
|
|
2162
2185
|
text: selectedText,
|
|
2163
2186
|
x: startX,
|
|
2164
2187
|
y: 0,
|
|
2165
|
-
|
|
2166
|
-
|
|
2188
|
+
color: this._selectionFg ? this._selectionFg : this._color,
|
|
2189
|
+
backgroundColor: this._selectionBg ? this._selectionBg : this._backgroundColor,
|
|
2167
2190
|
font: this._font
|
|
2168
2191
|
});
|
|
2169
2192
|
}
|
|
@@ -2399,7 +2422,6 @@ class TextBufferRenderable extends Renderable {
|
|
|
2399
2422
|
_tabIndicatorColor;
|
|
2400
2423
|
textBuffer;
|
|
2401
2424
|
textBufferView;
|
|
2402
|
-
_lineInfo = { lineStarts: [], lineWidths: [], maxLineWidth: 0 };
|
|
2403
2425
|
_defaultOptions = {
|
|
2404
2426
|
fg: RGBA.fromValues(1, 1, 1, 1),
|
|
2405
2427
|
bg: RGBA.fromValues(0, 0, 0, 0),
|
|
@@ -2438,10 +2460,19 @@ class TextBufferRenderable extends Renderable {
|
|
|
2438
2460
|
this.textBufferView.setTabIndicatorColor(this._tabIndicatorColor);
|
|
2439
2461
|
}
|
|
2440
2462
|
if (this._wrapMode !== "none" && this.width > 0) {
|
|
2441
|
-
this.
|
|
2463
|
+
this.textBufferView.setWrapWidth(this.width);
|
|
2442
2464
|
}
|
|
2443
2465
|
this.updateTextInfo();
|
|
2444
2466
|
}
|
|
2467
|
+
get lineInfo() {
|
|
2468
|
+
return this.textBufferView.logicalLineInfo;
|
|
2469
|
+
}
|
|
2470
|
+
get lineCount() {
|
|
2471
|
+
return this.textBuffer.getLineCount();
|
|
2472
|
+
}
|
|
2473
|
+
get scrollY() {
|
|
2474
|
+
return 0;
|
|
2475
|
+
}
|
|
2445
2476
|
get plainText() {
|
|
2446
2477
|
return this.textBuffer.getPlainText();
|
|
2447
2478
|
}
|
|
@@ -2517,7 +2548,7 @@ class TextBufferRenderable extends Renderable {
|
|
|
2517
2548
|
this._wrapMode = value;
|
|
2518
2549
|
this.textBufferView.setWrapMode(this._wrapMode);
|
|
2519
2550
|
if (value !== "none" && this.width > 0) {
|
|
2520
|
-
this.
|
|
2551
|
+
this.textBufferView.setWrapWidth(this.width);
|
|
2521
2552
|
}
|
|
2522
2553
|
this.yogaNode.markDirty();
|
|
2523
2554
|
this.requestRender();
|
|
@@ -2576,30 +2607,29 @@ class TextBufferRenderable extends Renderable {
|
|
|
2576
2607
|
}
|
|
2577
2608
|
this.yogaNode.markDirty();
|
|
2578
2609
|
this.requestRender();
|
|
2579
|
-
|
|
2580
|
-
updateLineInfo() {
|
|
2581
|
-
const lineInfo = this.textBufferView.logicalLineInfo;
|
|
2582
|
-
this._lineInfo.lineStarts = lineInfo.lineStarts;
|
|
2583
|
-
this._lineInfo.lineWidths = lineInfo.lineWidths;
|
|
2584
|
-
this._lineInfo.maxLineWidth = lineInfo.maxLineWidth;
|
|
2585
|
-
}
|
|
2586
|
-
updateWrapWidth(width) {
|
|
2587
|
-
this.textBufferView.setWrapWidth(width);
|
|
2588
|
-
this.updateLineInfo();
|
|
2610
|
+
this.emit("line-info-change");
|
|
2589
2611
|
}
|
|
2590
2612
|
setupMeasureFunc() {
|
|
2591
2613
|
const measureFunc = (width, widthMode, height, heightMode) => {
|
|
2592
|
-
|
|
2593
|
-
if (
|
|
2594
|
-
|
|
2614
|
+
let effectiveWidth;
|
|
2615
|
+
if (widthMode === MeasureMode.Undefined || isNaN(width)) {
|
|
2616
|
+
effectiveWidth = 0;
|
|
2595
2617
|
} else {
|
|
2596
|
-
|
|
2618
|
+
effectiveWidth = width;
|
|
2619
|
+
}
|
|
2620
|
+
const effectiveHeight = isNaN(height) ? 1 : height;
|
|
2621
|
+
const measureResult = this.textBufferView.measureForDimensions(Math.floor(effectiveWidth), Math.floor(effectiveHeight));
|
|
2622
|
+
const measuredWidth = measureResult ? Math.max(1, measureResult.maxWidth) : 1;
|
|
2623
|
+
const measuredHeight = measureResult ? Math.max(1, measureResult.lineCount) : 1;
|
|
2624
|
+
if (widthMode === MeasureMode.AtMost && this._positionType !== "absolute") {
|
|
2625
|
+
return {
|
|
2626
|
+
width: Math.min(effectiveWidth, measuredWidth),
|
|
2627
|
+
height: Math.min(effectiveHeight, measuredHeight)
|
|
2628
|
+
};
|
|
2597
2629
|
}
|
|
2598
|
-
const measuredWidth = this._lineInfo.maxLineWidth;
|
|
2599
|
-
const measuredHeight = this._lineInfo.lineStarts.length;
|
|
2600
2630
|
return {
|
|
2601
|
-
width:
|
|
2602
|
-
height:
|
|
2631
|
+
width: measuredWidth,
|
|
2632
|
+
height: measuredHeight
|
|
2603
2633
|
};
|
|
2604
2634
|
};
|
|
2605
2635
|
this.yogaNode.setMeasureFunc(measureFunc);
|
|
@@ -2684,6 +2714,10 @@ class CodeRenderable extends TextBufferRenderable {
|
|
|
2684
2714
|
this._conceal = options.conceal ?? this._contentDefaultOptions.conceal;
|
|
2685
2715
|
this._drawUnstyledText = options.drawUnstyledText ?? this._contentDefaultOptions.drawUnstyledText;
|
|
2686
2716
|
this._streaming = options.streaming ?? this._contentDefaultOptions.streaming;
|
|
2717
|
+
if (this._content.length > 0 && (this._drawUnstyledText || !this._filetype)) {
|
|
2718
|
+
this.textBuffer.setText(this._content);
|
|
2719
|
+
this.updateTextInfo();
|
|
2720
|
+
}
|
|
2687
2721
|
this._highlightsDirty = this._content.length > 0;
|
|
2688
2722
|
}
|
|
2689
2723
|
get content() {
|
|
@@ -2693,6 +2727,10 @@ class CodeRenderable extends TextBufferRenderable {
|
|
|
2693
2727
|
if (this._content !== value) {
|
|
2694
2728
|
this._content = value;
|
|
2695
2729
|
this._highlightsDirty = true;
|
|
2730
|
+
if (this._drawUnstyledText || !this._filetype) {
|
|
2731
|
+
this.textBuffer.setText(value);
|
|
2732
|
+
this.updateTextInfo();
|
|
2733
|
+
}
|
|
2696
2734
|
}
|
|
2697
2735
|
}
|
|
2698
2736
|
get filetype() {
|
|
@@ -2981,196 +3019,1952 @@ class TextNodeRenderable extends BaseRenderable {
|
|
|
2981
3019
|
this._children.splice(anchorIndex, 0, ...textNodes);
|
|
2982
3020
|
textNodes.forEach((node) => node.parent = this);
|
|
2983
3021
|
} else {
|
|
2984
|
-
throw new Error("Child must be a string, TextNodeRenderable, or StyledText instance");
|
|
3022
|
+
throw new Error("Child must be a string, TextNodeRenderable, or StyledText instance");
|
|
3023
|
+
}
|
|
3024
|
+
this.requestRender();
|
|
3025
|
+
return this;
|
|
3026
|
+
}
|
|
3027
|
+
remove(id) {
|
|
3028
|
+
const childIndex = this.getRenderableIndex(id);
|
|
3029
|
+
if (childIndex === -1) {
|
|
3030
|
+
throw new Error("Child not found in children");
|
|
3031
|
+
}
|
|
3032
|
+
const child = this._children[childIndex];
|
|
3033
|
+
this._children.splice(childIndex, 1);
|
|
3034
|
+
child.parent = null;
|
|
3035
|
+
this.requestRender();
|
|
3036
|
+
return this;
|
|
3037
|
+
}
|
|
3038
|
+
clear() {
|
|
3039
|
+
this._children = [];
|
|
3040
|
+
this.requestRender();
|
|
3041
|
+
}
|
|
3042
|
+
mergeStyles(parentStyle) {
|
|
3043
|
+
return {
|
|
3044
|
+
fg: this._fg ?? parentStyle.fg,
|
|
3045
|
+
bg: this._bg ?? parentStyle.bg,
|
|
3046
|
+
attributes: this._attributes | parentStyle.attributes
|
|
3047
|
+
};
|
|
3048
|
+
}
|
|
3049
|
+
gatherWithInheritedStyle(parentStyle = { fg: undefined, bg: undefined, attributes: 0 }) {
|
|
3050
|
+
const currentStyle = this.mergeStyles(parentStyle);
|
|
3051
|
+
const chunks = [];
|
|
3052
|
+
for (const child of this._children) {
|
|
3053
|
+
if (typeof child === "string") {
|
|
3054
|
+
chunks.push({
|
|
3055
|
+
__isChunk: true,
|
|
3056
|
+
text: child,
|
|
3057
|
+
fg: currentStyle.fg,
|
|
3058
|
+
bg: currentStyle.bg,
|
|
3059
|
+
attributes: currentStyle.attributes
|
|
3060
|
+
});
|
|
3061
|
+
} else {
|
|
3062
|
+
const childChunks = child.gatherWithInheritedStyle(currentStyle);
|
|
3063
|
+
chunks.push(...childChunks);
|
|
3064
|
+
}
|
|
3065
|
+
}
|
|
3066
|
+
this.markClean();
|
|
3067
|
+
return chunks;
|
|
3068
|
+
}
|
|
3069
|
+
static fromString(text, options = {}) {
|
|
3070
|
+
const node = new TextNodeRenderable(options);
|
|
3071
|
+
node.add(text);
|
|
3072
|
+
return node;
|
|
3073
|
+
}
|
|
3074
|
+
static fromNodes(nodes, options = {}) {
|
|
3075
|
+
const node = new TextNodeRenderable(options);
|
|
3076
|
+
for (const childNode of nodes) {
|
|
3077
|
+
node.add(childNode);
|
|
3078
|
+
}
|
|
3079
|
+
return node;
|
|
3080
|
+
}
|
|
3081
|
+
toChunks(parentStyle = { fg: undefined, bg: undefined, attributes: 0 }) {
|
|
3082
|
+
return this.gatherWithInheritedStyle(parentStyle);
|
|
3083
|
+
}
|
|
3084
|
+
getChildren() {
|
|
3085
|
+
return this._children.filter((child) => typeof child !== "string");
|
|
3086
|
+
}
|
|
3087
|
+
getChildrenCount() {
|
|
3088
|
+
return this._children.length;
|
|
3089
|
+
}
|
|
3090
|
+
getRenderable(id) {
|
|
3091
|
+
return this._children.find((child) => typeof child !== "string" && child.id === id);
|
|
3092
|
+
}
|
|
3093
|
+
getRenderableIndex(id) {
|
|
3094
|
+
return this._children.findIndex((child) => isTextNodeRenderable(child) && child.id === id);
|
|
3095
|
+
}
|
|
3096
|
+
get fg() {
|
|
3097
|
+
return this._fg;
|
|
3098
|
+
}
|
|
3099
|
+
set fg(fg2) {
|
|
3100
|
+
if (!fg2) {
|
|
3101
|
+
this._fg = undefined;
|
|
3102
|
+
this.requestRender();
|
|
3103
|
+
return;
|
|
3104
|
+
}
|
|
3105
|
+
this._fg = parseColor(fg2);
|
|
3106
|
+
this.requestRender();
|
|
3107
|
+
}
|
|
3108
|
+
set bg(bg2) {
|
|
3109
|
+
if (!bg2) {
|
|
3110
|
+
this._bg = undefined;
|
|
3111
|
+
this.requestRender();
|
|
3112
|
+
return;
|
|
3113
|
+
}
|
|
3114
|
+
this._bg = parseColor(bg2);
|
|
3115
|
+
this.requestRender();
|
|
3116
|
+
}
|
|
3117
|
+
get bg() {
|
|
3118
|
+
return this._bg;
|
|
3119
|
+
}
|
|
3120
|
+
set attributes(attributes) {
|
|
3121
|
+
this._attributes = attributes;
|
|
3122
|
+
this.requestRender();
|
|
3123
|
+
}
|
|
3124
|
+
get attributes() {
|
|
3125
|
+
return this._attributes;
|
|
3126
|
+
}
|
|
3127
|
+
findDescendantById(id) {
|
|
3128
|
+
return;
|
|
3129
|
+
}
|
|
3130
|
+
}
|
|
3131
|
+
|
|
3132
|
+
class RootTextNodeRenderable extends TextNodeRenderable {
|
|
3133
|
+
ctx;
|
|
3134
|
+
textParent;
|
|
3135
|
+
constructor(ctx, options, textParent) {
|
|
3136
|
+
super(options);
|
|
3137
|
+
this.ctx = ctx;
|
|
3138
|
+
this.textParent = textParent;
|
|
3139
|
+
}
|
|
3140
|
+
requestRender() {
|
|
3141
|
+
this.markDirty();
|
|
3142
|
+
this.ctx.requestRender();
|
|
3143
|
+
}
|
|
3144
|
+
}
|
|
3145
|
+
|
|
3146
|
+
// src/renderables/composition/constructs.ts
|
|
3147
|
+
function Generic(props, ...children) {
|
|
3148
|
+
return h(VRenderable, props || {}, ...children);
|
|
3149
|
+
}
|
|
3150
|
+
function Box(props, ...children) {
|
|
3151
|
+
return h(BoxRenderable, props || {}, ...children);
|
|
3152
|
+
}
|
|
3153
|
+
function Text(props, ...children) {
|
|
3154
|
+
return h(TextRenderable, props || {}, ...children);
|
|
3155
|
+
}
|
|
3156
|
+
function ASCIIFont(props, ...children) {
|
|
3157
|
+
return h(ASCIIFontRenderable, props || {}, ...children);
|
|
3158
|
+
}
|
|
3159
|
+
function Input(props, ...children) {
|
|
3160
|
+
return h(InputRenderable, props || {}, ...children);
|
|
3161
|
+
}
|
|
3162
|
+
function Select(props, ...children) {
|
|
3163
|
+
return h(SelectRenderable, props || {}, ...children);
|
|
3164
|
+
}
|
|
3165
|
+
function TabSelect(props, ...children) {
|
|
3166
|
+
return h(TabSelectRenderable, props || {}, ...children);
|
|
3167
|
+
}
|
|
3168
|
+
function FrameBuffer(props, ...children) {
|
|
3169
|
+
return h(FrameBufferRenderable, props, ...children);
|
|
3170
|
+
}
|
|
3171
|
+
function StyledText2(props, ...children) {
|
|
3172
|
+
const styledProps = props;
|
|
3173
|
+
const textNodeOptions = {
|
|
3174
|
+
...styledProps,
|
|
3175
|
+
attributes: styledProps?.attributes ?? 0
|
|
3176
|
+
};
|
|
3177
|
+
const textNode = new TextNodeRenderable(textNodeOptions);
|
|
3178
|
+
for (const child of children) {
|
|
3179
|
+
textNode.add(child);
|
|
3180
|
+
}
|
|
3181
|
+
return textNode;
|
|
3182
|
+
}
|
|
3183
|
+
var vstyles = {
|
|
3184
|
+
bold: (...children) => StyledText2({ attributes: TextAttributes.BOLD }, ...children),
|
|
3185
|
+
italic: (...children) => StyledText2({ attributes: TextAttributes.ITALIC }, ...children),
|
|
3186
|
+
underline: (...children) => StyledText2({ attributes: TextAttributes.UNDERLINE }, ...children),
|
|
3187
|
+
dim: (...children) => StyledText2({ attributes: TextAttributes.DIM }, ...children),
|
|
3188
|
+
blink: (...children) => StyledText2({ attributes: TextAttributes.BLINK }, ...children),
|
|
3189
|
+
inverse: (...children) => StyledText2({ attributes: TextAttributes.INVERSE }, ...children),
|
|
3190
|
+
hidden: (...children) => StyledText2({ attributes: TextAttributes.HIDDEN }, ...children),
|
|
3191
|
+
strikethrough: (...children) => StyledText2({ attributes: TextAttributes.STRIKETHROUGH }, ...children),
|
|
3192
|
+
boldItalic: (...children) => StyledText2({ attributes: TextAttributes.BOLD | TextAttributes.ITALIC }, ...children),
|
|
3193
|
+
boldUnderline: (...children) => StyledText2({ attributes: TextAttributes.BOLD | TextAttributes.UNDERLINE }, ...children),
|
|
3194
|
+
italicUnderline: (...children) => StyledText2({ attributes: TextAttributes.ITALIC | TextAttributes.UNDERLINE }, ...children),
|
|
3195
|
+
boldItalicUnderline: (...children) => StyledText2({ attributes: TextAttributes.BOLD | TextAttributes.ITALIC | TextAttributes.UNDERLINE }, ...children),
|
|
3196
|
+
color: (color, ...children) => StyledText2({ fg: color }, ...children),
|
|
3197
|
+
bgColor: (bgColor, ...children) => StyledText2({ bg: bgColor }, ...children),
|
|
3198
|
+
fg: (color, ...children) => StyledText2({ fg: color }, ...children),
|
|
3199
|
+
bg: (bgColor, ...children) => StyledText2({ bg: bgColor }, ...children),
|
|
3200
|
+
styled: (attributes = 0, ...children) => StyledText2({ attributes }, ...children)
|
|
3201
|
+
};
|
|
3202
|
+
// src/renderables/composition/VRenderable.ts
|
|
3203
|
+
class VRenderable extends Renderable {
|
|
3204
|
+
options;
|
|
3205
|
+
constructor(ctx, options) {
|
|
3206
|
+
super(ctx, options);
|
|
3207
|
+
this.options = options;
|
|
3208
|
+
}
|
|
3209
|
+
renderSelf(buffer, deltaTime) {
|
|
3210
|
+
if (this.options.render) {
|
|
3211
|
+
this.options.render.call(this.options, buffer, deltaTime, this);
|
|
3212
|
+
}
|
|
3213
|
+
}
|
|
3214
|
+
}
|
|
3215
|
+
// src/renderables/LineNumberRenderable.ts
|
|
3216
|
+
class GutterRenderable extends Renderable {
|
|
3217
|
+
target;
|
|
3218
|
+
_fg;
|
|
3219
|
+
_bg;
|
|
3220
|
+
_minWidth;
|
|
3221
|
+
_paddingRight;
|
|
3222
|
+
_lineColorsGutter;
|
|
3223
|
+
_lineColorsContent;
|
|
3224
|
+
_lineSigns;
|
|
3225
|
+
_lineNumberOffset;
|
|
3226
|
+
_hideLineNumbers;
|
|
3227
|
+
_lineNumbers;
|
|
3228
|
+
_maxBeforeWidth = 0;
|
|
3229
|
+
_maxAfterWidth = 0;
|
|
3230
|
+
_lastKnownLineCount = 0;
|
|
3231
|
+
_lastKnownScrollY = 0;
|
|
3232
|
+
constructor(ctx, target, options) {
|
|
3233
|
+
super(ctx, {
|
|
3234
|
+
id: options.id,
|
|
3235
|
+
width: "auto",
|
|
3236
|
+
height: "auto",
|
|
3237
|
+
flexGrow: 0,
|
|
3238
|
+
flexShrink: 0,
|
|
3239
|
+
buffered: options.buffered
|
|
3240
|
+
});
|
|
3241
|
+
this.target = target;
|
|
3242
|
+
this._fg = options.fg;
|
|
3243
|
+
this._bg = options.bg;
|
|
3244
|
+
this._minWidth = options.minWidth;
|
|
3245
|
+
this._paddingRight = options.paddingRight;
|
|
3246
|
+
this._lineColorsGutter = options.lineColorsGutter;
|
|
3247
|
+
this._lineColorsContent = options.lineColorsContent;
|
|
3248
|
+
this._lineSigns = options.lineSigns;
|
|
3249
|
+
this._lineNumberOffset = options.lineNumberOffset;
|
|
3250
|
+
this._hideLineNumbers = options.hideLineNumbers;
|
|
3251
|
+
this._lineNumbers = options.lineNumbers ?? new Map;
|
|
3252
|
+
this._lastKnownLineCount = this.target.lineCount;
|
|
3253
|
+
this._lastKnownScrollY = this.target.scrollY;
|
|
3254
|
+
this.calculateSignWidths();
|
|
3255
|
+
this.setupMeasureFunc();
|
|
3256
|
+
this.onLifecyclePass = () => {
|
|
3257
|
+
const currentLineCount = this.target.lineCount;
|
|
3258
|
+
if (currentLineCount !== this._lastKnownLineCount) {
|
|
3259
|
+
this._lastKnownLineCount = currentLineCount;
|
|
3260
|
+
this.yogaNode.markDirty();
|
|
3261
|
+
this.requestRender();
|
|
3262
|
+
}
|
|
3263
|
+
};
|
|
3264
|
+
}
|
|
3265
|
+
setupMeasureFunc() {
|
|
3266
|
+
const measureFunc = (width, widthMode, height, heightMode) => {
|
|
3267
|
+
const gutterWidth = this.calculateWidth();
|
|
3268
|
+
const gutterHeight = this.target.lineCount;
|
|
3269
|
+
return {
|
|
3270
|
+
width: gutterWidth,
|
|
3271
|
+
height: gutterHeight
|
|
3272
|
+
};
|
|
3273
|
+
};
|
|
3274
|
+
this.yogaNode.setMeasureFunc(measureFunc);
|
|
3275
|
+
}
|
|
3276
|
+
remeasure() {
|
|
3277
|
+
this.yogaNode.markDirty();
|
|
3278
|
+
}
|
|
3279
|
+
calculateSignWidths() {
|
|
3280
|
+
this._maxBeforeWidth = 0;
|
|
3281
|
+
this._maxAfterWidth = 0;
|
|
3282
|
+
for (const sign of this._lineSigns.values()) {
|
|
3283
|
+
if (sign.before) {
|
|
3284
|
+
const width = Bun.stringWidth(sign.before);
|
|
3285
|
+
this._maxBeforeWidth = Math.max(this._maxBeforeWidth, width);
|
|
3286
|
+
}
|
|
3287
|
+
if (sign.after) {
|
|
3288
|
+
const width = Bun.stringWidth(sign.after);
|
|
3289
|
+
this._maxAfterWidth = Math.max(this._maxAfterWidth, width);
|
|
3290
|
+
}
|
|
3291
|
+
}
|
|
3292
|
+
}
|
|
3293
|
+
calculateWidth() {
|
|
3294
|
+
const totalLines = this.target.lineCount;
|
|
3295
|
+
let maxLineNumber = totalLines + this._lineNumberOffset;
|
|
3296
|
+
if (this._lineNumbers.size > 0) {
|
|
3297
|
+
for (const customLineNum of this._lineNumbers.values()) {
|
|
3298
|
+
maxLineNumber = Math.max(maxLineNumber, customLineNum);
|
|
3299
|
+
}
|
|
3300
|
+
}
|
|
3301
|
+
const digits = maxLineNumber > 0 ? Math.floor(Math.log10(maxLineNumber)) + 1 : 1;
|
|
3302
|
+
const baseWidth = Math.max(this._minWidth, digits + this._paddingRight + 1);
|
|
3303
|
+
return baseWidth + this._maxBeforeWidth + this._maxAfterWidth;
|
|
3304
|
+
}
|
|
3305
|
+
setLineColors(lineColorsGutter, lineColorsContent) {
|
|
3306
|
+
this._lineColorsGutter = lineColorsGutter;
|
|
3307
|
+
this._lineColorsContent = lineColorsContent;
|
|
3308
|
+
this.requestRender();
|
|
3309
|
+
}
|
|
3310
|
+
getLineColors() {
|
|
3311
|
+
return {
|
|
3312
|
+
gutter: this._lineColorsGutter,
|
|
3313
|
+
content: this._lineColorsContent
|
|
3314
|
+
};
|
|
3315
|
+
}
|
|
3316
|
+
setLineSigns(lineSigns) {
|
|
3317
|
+
const oldMaxBefore = this._maxBeforeWidth;
|
|
3318
|
+
const oldMaxAfter = this._maxAfterWidth;
|
|
3319
|
+
this._lineSigns = lineSigns;
|
|
3320
|
+
this.calculateSignWidths();
|
|
3321
|
+
if (this._maxBeforeWidth !== oldMaxBefore || this._maxAfterWidth !== oldMaxAfter) {
|
|
3322
|
+
this.yogaNode.markDirty();
|
|
3323
|
+
}
|
|
3324
|
+
this.requestRender();
|
|
3325
|
+
}
|
|
3326
|
+
getLineSigns() {
|
|
3327
|
+
return this._lineSigns;
|
|
3328
|
+
}
|
|
3329
|
+
renderSelf(buffer) {
|
|
3330
|
+
const currentScrollY = this.target.scrollY;
|
|
3331
|
+
const scrollChanged = currentScrollY !== this._lastKnownScrollY;
|
|
3332
|
+
if (this.buffered && !this.isDirty && !scrollChanged) {
|
|
3333
|
+
return;
|
|
3334
|
+
}
|
|
3335
|
+
this._lastKnownScrollY = currentScrollY;
|
|
3336
|
+
this.refreshFrameBuffer(buffer);
|
|
3337
|
+
}
|
|
3338
|
+
refreshFrameBuffer(buffer) {
|
|
3339
|
+
const startX = this.buffered ? 0 : this.x;
|
|
3340
|
+
const startY = this.buffered ? 0 : this.y;
|
|
3341
|
+
if (this.buffered) {
|
|
3342
|
+
buffer.clear(this._bg);
|
|
3343
|
+
} else if (this._bg.a > 0) {
|
|
3344
|
+
buffer.fillRect(startX, startY, this.width, this.height, this._bg);
|
|
3345
|
+
}
|
|
3346
|
+
const lineInfo = this.target.lineInfo;
|
|
3347
|
+
if (!lineInfo || !lineInfo.lineSources)
|
|
3348
|
+
return;
|
|
3349
|
+
const sources = lineInfo.lineSources;
|
|
3350
|
+
let lastSource = -1;
|
|
3351
|
+
const startLine = this.target.scrollY;
|
|
3352
|
+
if (startLine >= sources.length)
|
|
3353
|
+
return;
|
|
3354
|
+
lastSource = startLine > 0 ? sources[startLine - 1] : -1;
|
|
3355
|
+
for (let i = 0;i < this.height; i++) {
|
|
3356
|
+
const visualLineIndex = startLine + i;
|
|
3357
|
+
if (visualLineIndex >= sources.length)
|
|
3358
|
+
break;
|
|
3359
|
+
const logicalLine = sources[visualLineIndex];
|
|
3360
|
+
const lineBg = this._lineColorsGutter.get(logicalLine) ?? this._bg;
|
|
3361
|
+
if (lineBg !== this._bg) {
|
|
3362
|
+
buffer.fillRect(startX, startY + i, this.width, 1, lineBg);
|
|
3363
|
+
}
|
|
3364
|
+
if (logicalLine === lastSource) {} else {
|
|
3365
|
+
let currentX = startX;
|
|
3366
|
+
const sign = this._lineSigns.get(logicalLine);
|
|
3367
|
+
if (sign?.before) {
|
|
3368
|
+
const beforeWidth = Bun.stringWidth(sign.before);
|
|
3369
|
+
const padding = this._maxBeforeWidth - beforeWidth;
|
|
3370
|
+
currentX += padding;
|
|
3371
|
+
const beforeColor = sign.beforeColor ? parseColor(sign.beforeColor) : this._fg;
|
|
3372
|
+
buffer.drawText(sign.before, currentX, startY + i, beforeColor, lineBg);
|
|
3373
|
+
currentX += beforeWidth;
|
|
3374
|
+
} else if (this._maxBeforeWidth > 0) {
|
|
3375
|
+
currentX += this._maxBeforeWidth;
|
|
3376
|
+
}
|
|
3377
|
+
if (!this._hideLineNumbers.has(logicalLine)) {
|
|
3378
|
+
const customLineNum = this._lineNumbers.get(logicalLine);
|
|
3379
|
+
const lineNum = customLineNum !== undefined ? customLineNum : logicalLine + 1 + this._lineNumberOffset;
|
|
3380
|
+
const lineNumStr = lineNum.toString();
|
|
3381
|
+
const lineNumWidth = lineNumStr.length;
|
|
3382
|
+
const availableSpace = this.width - this._maxBeforeWidth - this._maxAfterWidth - this._paddingRight;
|
|
3383
|
+
const lineNumX = startX + this._maxBeforeWidth + 1 + availableSpace - lineNumWidth - 1;
|
|
3384
|
+
if (lineNumX >= startX + this._maxBeforeWidth + 1) {
|
|
3385
|
+
buffer.drawText(lineNumStr, lineNumX, startY + i, this._fg, lineBg);
|
|
3386
|
+
}
|
|
3387
|
+
}
|
|
3388
|
+
if (sign?.after) {
|
|
3389
|
+
const afterX = startX + this.width - this._paddingRight - this._maxAfterWidth;
|
|
3390
|
+
const afterColor = sign.afterColor ? parseColor(sign.afterColor) : this._fg;
|
|
3391
|
+
buffer.drawText(sign.after, afterX, startY + i, afterColor, lineBg);
|
|
3392
|
+
}
|
|
3393
|
+
}
|
|
3394
|
+
lastSource = logicalLine;
|
|
3395
|
+
}
|
|
3396
|
+
}
|
|
3397
|
+
}
|
|
3398
|
+
function darkenColor(color) {
|
|
3399
|
+
return RGBA.fromValues(color.r * 0.8, color.g * 0.8, color.b * 0.8, color.a);
|
|
3400
|
+
}
|
|
3401
|
+
|
|
3402
|
+
class LineNumberRenderable extends Renderable {
|
|
3403
|
+
gutter = null;
|
|
3404
|
+
target = null;
|
|
3405
|
+
_lineColorsGutter;
|
|
3406
|
+
_lineColorsContent;
|
|
3407
|
+
_lineSigns;
|
|
3408
|
+
_fg;
|
|
3409
|
+
_bg;
|
|
3410
|
+
_minWidth;
|
|
3411
|
+
_paddingRight;
|
|
3412
|
+
_lineNumberOffset;
|
|
3413
|
+
_hideLineNumbers;
|
|
3414
|
+
_lineNumbers;
|
|
3415
|
+
_isDestroying = false;
|
|
3416
|
+
handleLineInfoChange = () => {
|
|
3417
|
+
this.gutter?.remeasure();
|
|
3418
|
+
this.requestRender();
|
|
3419
|
+
};
|
|
3420
|
+
parseLineColor(line, color) {
|
|
3421
|
+
if (typeof color === "object" && "gutter" in color) {
|
|
3422
|
+
const config = color;
|
|
3423
|
+
if (config.gutter) {
|
|
3424
|
+
this._lineColorsGutter.set(line, parseColor(config.gutter));
|
|
3425
|
+
}
|
|
3426
|
+
if (config.content) {
|
|
3427
|
+
this._lineColorsContent.set(line, parseColor(config.content));
|
|
3428
|
+
} else if (config.gutter) {
|
|
3429
|
+
this._lineColorsContent.set(line, darkenColor(parseColor(config.gutter)));
|
|
3430
|
+
}
|
|
3431
|
+
} else {
|
|
3432
|
+
const parsedColor = parseColor(color);
|
|
3433
|
+
this._lineColorsGutter.set(line, parsedColor);
|
|
3434
|
+
this._lineColorsContent.set(line, darkenColor(parsedColor));
|
|
3435
|
+
}
|
|
3436
|
+
}
|
|
3437
|
+
constructor(ctx, options) {
|
|
3438
|
+
super(ctx, {
|
|
3439
|
+
...options,
|
|
3440
|
+
flexDirection: "row",
|
|
3441
|
+
height: "auto"
|
|
3442
|
+
});
|
|
3443
|
+
this._fg = parseColor(options.fg ?? "#888888");
|
|
3444
|
+
this._bg = parseColor(options.bg ?? "transparent");
|
|
3445
|
+
this._minWidth = options.minWidth ?? 3;
|
|
3446
|
+
this._paddingRight = options.paddingRight ?? 1;
|
|
3447
|
+
this._lineNumberOffset = options.lineNumberOffset ?? 0;
|
|
3448
|
+
this._hideLineNumbers = options.hideLineNumbers ?? new Set;
|
|
3449
|
+
this._lineNumbers = options.lineNumbers ?? new Map;
|
|
3450
|
+
this._lineColorsGutter = new Map;
|
|
3451
|
+
this._lineColorsContent = new Map;
|
|
3452
|
+
if (options.lineColors) {
|
|
3453
|
+
for (const [line, color] of options.lineColors) {
|
|
3454
|
+
this.parseLineColor(line, color);
|
|
3455
|
+
}
|
|
3456
|
+
}
|
|
3457
|
+
this._lineSigns = new Map;
|
|
3458
|
+
if (options.lineSigns) {
|
|
3459
|
+
for (const [line, sign] of options.lineSigns) {
|
|
3460
|
+
this._lineSigns.set(line, sign);
|
|
3461
|
+
}
|
|
3462
|
+
}
|
|
3463
|
+
if (options.target) {
|
|
3464
|
+
this.setTarget(options.target);
|
|
3465
|
+
}
|
|
3466
|
+
}
|
|
3467
|
+
setTarget(target) {
|
|
3468
|
+
if (this.target === target)
|
|
3469
|
+
return;
|
|
3470
|
+
if (this.target) {
|
|
3471
|
+
this.target.off("line-info-change", this.handleLineInfoChange);
|
|
3472
|
+
super.remove(this.target.id);
|
|
3473
|
+
}
|
|
3474
|
+
if (this.gutter) {
|
|
3475
|
+
super.remove(this.gutter.id);
|
|
3476
|
+
this.gutter = null;
|
|
3477
|
+
}
|
|
3478
|
+
this.target = target;
|
|
3479
|
+
this.target.on("line-info-change", this.handleLineInfoChange);
|
|
3480
|
+
this.gutter = new GutterRenderable(this.ctx, this.target, {
|
|
3481
|
+
fg: this._fg,
|
|
3482
|
+
bg: this._bg,
|
|
3483
|
+
minWidth: this._minWidth,
|
|
3484
|
+
paddingRight: this._paddingRight,
|
|
3485
|
+
lineColorsGutter: this._lineColorsGutter,
|
|
3486
|
+
lineColorsContent: this._lineColorsContent,
|
|
3487
|
+
lineSigns: this._lineSigns,
|
|
3488
|
+
lineNumberOffset: this._lineNumberOffset,
|
|
3489
|
+
hideLineNumbers: this._hideLineNumbers,
|
|
3490
|
+
lineNumbers: this._lineNumbers,
|
|
3491
|
+
id: this.id ? `${this.id}-gutter` : undefined,
|
|
3492
|
+
buffered: true
|
|
3493
|
+
});
|
|
3494
|
+
super.add(this.gutter);
|
|
3495
|
+
super.add(this.target);
|
|
3496
|
+
}
|
|
3497
|
+
add(child) {
|
|
3498
|
+
if (!this.target && "lineInfo" in child && "lineCount" in child && "scrollY" in child) {
|
|
3499
|
+
this.setTarget(child);
|
|
3500
|
+
return this.getChildrenCount() - 1;
|
|
3501
|
+
}
|
|
3502
|
+
return -1;
|
|
3503
|
+
}
|
|
3504
|
+
remove(id) {
|
|
3505
|
+
if (this._isDestroying) {
|
|
3506
|
+
super.remove(id);
|
|
3507
|
+
return;
|
|
3508
|
+
}
|
|
3509
|
+
if (this.gutter && id === this.gutter.id) {
|
|
3510
|
+
throw new Error("LineNumberRenderable: Cannot remove gutter directly.");
|
|
3511
|
+
}
|
|
3512
|
+
if (this.target && id === this.target.id) {
|
|
3513
|
+
throw new Error("LineNumberRenderable: Cannot remove target directly. Use clearTarget() instead.");
|
|
3514
|
+
}
|
|
3515
|
+
super.remove(id);
|
|
3516
|
+
}
|
|
3517
|
+
destroyRecursively() {
|
|
3518
|
+
this._isDestroying = true;
|
|
3519
|
+
if (this.target) {
|
|
3520
|
+
this.target.off("line-info-change", this.handleLineInfoChange);
|
|
3521
|
+
}
|
|
3522
|
+
super.destroyRecursively();
|
|
3523
|
+
this.gutter = null;
|
|
3524
|
+
this.target = null;
|
|
3525
|
+
}
|
|
3526
|
+
clearTarget() {
|
|
3527
|
+
if (this.target) {
|
|
3528
|
+
this.target.off("line-info-change", this.handleLineInfoChange);
|
|
3529
|
+
super.remove(this.target.id);
|
|
3530
|
+
this.target = null;
|
|
3531
|
+
}
|
|
3532
|
+
if (this.gutter) {
|
|
3533
|
+
super.remove(this.gutter.id);
|
|
3534
|
+
this.gutter = null;
|
|
3535
|
+
}
|
|
3536
|
+
}
|
|
3537
|
+
renderSelf(buffer) {
|
|
3538
|
+
if (!this.target || !this.gutter)
|
|
3539
|
+
return;
|
|
3540
|
+
const lineInfo = this.target.lineInfo;
|
|
3541
|
+
if (!lineInfo || !lineInfo.lineSources)
|
|
3542
|
+
return;
|
|
3543
|
+
const sources = lineInfo.lineSources;
|
|
3544
|
+
const startLine = this.target.scrollY;
|
|
3545
|
+
if (startLine >= sources.length)
|
|
3546
|
+
return;
|
|
3547
|
+
const gutterWidth = this.gutter.visible ? this.gutter.width : 0;
|
|
3548
|
+
const contentWidth = this.width - gutterWidth;
|
|
3549
|
+
for (let i = 0;i < this.height; i++) {
|
|
3550
|
+
const visualLineIndex = startLine + i;
|
|
3551
|
+
if (visualLineIndex >= sources.length)
|
|
3552
|
+
break;
|
|
3553
|
+
const logicalLine = sources[visualLineIndex];
|
|
3554
|
+
const lineBg = this._lineColorsContent.get(logicalLine);
|
|
3555
|
+
if (lineBg) {
|
|
3556
|
+
buffer.fillRect(this.x + gutterWidth, this.y + i, contentWidth, 1, lineBg);
|
|
3557
|
+
}
|
|
3558
|
+
}
|
|
3559
|
+
}
|
|
3560
|
+
set showLineNumbers(value) {
|
|
3561
|
+
if (this.gutter) {
|
|
3562
|
+
this.gutter.visible = value;
|
|
3563
|
+
}
|
|
3564
|
+
}
|
|
3565
|
+
get showLineNumbers() {
|
|
3566
|
+
return this.gutter?.visible ?? false;
|
|
3567
|
+
}
|
|
3568
|
+
setLineColor(line, color) {
|
|
3569
|
+
this.parseLineColor(line, color);
|
|
3570
|
+
if (this.gutter) {
|
|
3571
|
+
this.gutter.setLineColors(this._lineColorsGutter, this._lineColorsContent);
|
|
3572
|
+
}
|
|
3573
|
+
}
|
|
3574
|
+
clearLineColor(line) {
|
|
3575
|
+
this._lineColorsGutter.delete(line);
|
|
3576
|
+
this._lineColorsContent.delete(line);
|
|
3577
|
+
if (this.gutter) {
|
|
3578
|
+
this.gutter.setLineColors(this._lineColorsGutter, this._lineColorsContent);
|
|
3579
|
+
}
|
|
3580
|
+
}
|
|
3581
|
+
clearAllLineColors() {
|
|
3582
|
+
this._lineColorsGutter.clear();
|
|
3583
|
+
this._lineColorsContent.clear();
|
|
3584
|
+
if (this.gutter) {
|
|
3585
|
+
this.gutter.setLineColors(this._lineColorsGutter, this._lineColorsContent);
|
|
3586
|
+
}
|
|
3587
|
+
}
|
|
3588
|
+
setLineColors(lineColors) {
|
|
3589
|
+
this._lineColorsGutter.clear();
|
|
3590
|
+
this._lineColorsContent.clear();
|
|
3591
|
+
for (const [line, color] of lineColors) {
|
|
3592
|
+
this.parseLineColor(line, color);
|
|
3593
|
+
}
|
|
3594
|
+
if (this.gutter) {
|
|
3595
|
+
this.gutter.setLineColors(this._lineColorsGutter, this._lineColorsContent);
|
|
3596
|
+
}
|
|
3597
|
+
}
|
|
3598
|
+
getLineColors() {
|
|
3599
|
+
return {
|
|
3600
|
+
gutter: this._lineColorsGutter,
|
|
3601
|
+
content: this._lineColorsContent
|
|
3602
|
+
};
|
|
3603
|
+
}
|
|
3604
|
+
setLineSign(line, sign) {
|
|
3605
|
+
this._lineSigns.set(line, sign);
|
|
3606
|
+
if (this.gutter) {
|
|
3607
|
+
this.gutter.setLineSigns(this._lineSigns);
|
|
3608
|
+
}
|
|
3609
|
+
}
|
|
3610
|
+
clearLineSign(line) {
|
|
3611
|
+
this._lineSigns.delete(line);
|
|
3612
|
+
if (this.gutter) {
|
|
3613
|
+
this.gutter.setLineSigns(this._lineSigns);
|
|
3614
|
+
}
|
|
3615
|
+
}
|
|
3616
|
+
clearAllLineSigns() {
|
|
3617
|
+
this._lineSigns.clear();
|
|
3618
|
+
if (this.gutter) {
|
|
3619
|
+
this.gutter.setLineSigns(this._lineSigns);
|
|
3620
|
+
}
|
|
3621
|
+
}
|
|
3622
|
+
setLineSigns(lineSigns) {
|
|
3623
|
+
this._lineSigns.clear();
|
|
3624
|
+
for (const [line, sign] of lineSigns) {
|
|
3625
|
+
this._lineSigns.set(line, sign);
|
|
3626
|
+
}
|
|
3627
|
+
if (this.gutter) {
|
|
3628
|
+
this.gutter.setLineSigns(this._lineSigns);
|
|
3629
|
+
}
|
|
3630
|
+
}
|
|
3631
|
+
getLineSigns() {
|
|
3632
|
+
return this._lineSigns;
|
|
3633
|
+
}
|
|
3634
|
+
set lineNumberOffset(value) {
|
|
3635
|
+
if (this._lineNumberOffset !== value) {
|
|
3636
|
+
this._lineNumberOffset = value;
|
|
3637
|
+
if (this.gutter && this.target) {
|
|
3638
|
+
const target = this.target;
|
|
3639
|
+
super.remove(this.gutter.id);
|
|
3640
|
+
super.remove(this.target.id);
|
|
3641
|
+
this.gutter = null;
|
|
3642
|
+
this.target = null;
|
|
3643
|
+
this.setTarget(target);
|
|
3644
|
+
}
|
|
3645
|
+
}
|
|
3646
|
+
}
|
|
3647
|
+
get lineNumberOffset() {
|
|
3648
|
+
return this._lineNumberOffset;
|
|
3649
|
+
}
|
|
3650
|
+
setHideLineNumbers(hideLineNumbers) {
|
|
3651
|
+
this._hideLineNumbers = hideLineNumbers;
|
|
3652
|
+
if (this.gutter && this.target) {
|
|
3653
|
+
const target = this.target;
|
|
3654
|
+
super.remove(this.gutter.id);
|
|
3655
|
+
super.remove(this.target.id);
|
|
3656
|
+
this.gutter = null;
|
|
3657
|
+
this.target = null;
|
|
3658
|
+
this.setTarget(target);
|
|
3659
|
+
}
|
|
3660
|
+
}
|
|
3661
|
+
getHideLineNumbers() {
|
|
3662
|
+
return this._hideLineNumbers;
|
|
3663
|
+
}
|
|
3664
|
+
setLineNumbers(lineNumbers) {
|
|
3665
|
+
this._lineNumbers = lineNumbers;
|
|
3666
|
+
if (this.gutter && this.target) {
|
|
3667
|
+
const target = this.target;
|
|
3668
|
+
super.remove(this.gutter.id);
|
|
3669
|
+
super.remove(this.target.id);
|
|
3670
|
+
this.gutter = null;
|
|
3671
|
+
this.target = null;
|
|
3672
|
+
this.setTarget(target);
|
|
3673
|
+
}
|
|
3674
|
+
}
|
|
3675
|
+
getLineNumbers() {
|
|
3676
|
+
return this._lineNumbers;
|
|
3677
|
+
}
|
|
3678
|
+
}
|
|
3679
|
+
|
|
3680
|
+
// ../../node_modules/diff/libesm/diff/base.js
|
|
3681
|
+
class Diff {
|
|
3682
|
+
diff(oldStr, newStr, options = {}) {
|
|
3683
|
+
let callback;
|
|
3684
|
+
if (typeof options === "function") {
|
|
3685
|
+
callback = options;
|
|
3686
|
+
options = {};
|
|
3687
|
+
} else if ("callback" in options) {
|
|
3688
|
+
callback = options.callback;
|
|
3689
|
+
}
|
|
3690
|
+
const oldString = this.castInput(oldStr, options);
|
|
3691
|
+
const newString = this.castInput(newStr, options);
|
|
3692
|
+
const oldTokens = this.removeEmpty(this.tokenize(oldString, options));
|
|
3693
|
+
const newTokens = this.removeEmpty(this.tokenize(newString, options));
|
|
3694
|
+
return this.diffWithOptionsObj(oldTokens, newTokens, options, callback);
|
|
3695
|
+
}
|
|
3696
|
+
diffWithOptionsObj(oldTokens, newTokens, options, callback) {
|
|
3697
|
+
var _a;
|
|
3698
|
+
const done = (value) => {
|
|
3699
|
+
value = this.postProcess(value, options);
|
|
3700
|
+
if (callback) {
|
|
3701
|
+
setTimeout(function() {
|
|
3702
|
+
callback(value);
|
|
3703
|
+
}, 0);
|
|
3704
|
+
return;
|
|
3705
|
+
} else {
|
|
3706
|
+
return value;
|
|
3707
|
+
}
|
|
3708
|
+
};
|
|
3709
|
+
const newLen = newTokens.length, oldLen = oldTokens.length;
|
|
3710
|
+
let editLength = 1;
|
|
3711
|
+
let maxEditLength = newLen + oldLen;
|
|
3712
|
+
if (options.maxEditLength != null) {
|
|
3713
|
+
maxEditLength = Math.min(maxEditLength, options.maxEditLength);
|
|
3714
|
+
}
|
|
3715
|
+
const maxExecutionTime = (_a = options.timeout) !== null && _a !== undefined ? _a : Infinity;
|
|
3716
|
+
const abortAfterTimestamp = Date.now() + maxExecutionTime;
|
|
3717
|
+
const bestPath = [{ oldPos: -1, lastComponent: undefined }];
|
|
3718
|
+
let newPos = this.extractCommon(bestPath[0], newTokens, oldTokens, 0, options);
|
|
3719
|
+
if (bestPath[0].oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
|
|
3720
|
+
return done(this.buildValues(bestPath[0].lastComponent, newTokens, oldTokens));
|
|
3721
|
+
}
|
|
3722
|
+
let minDiagonalToConsider = -Infinity, maxDiagonalToConsider = Infinity;
|
|
3723
|
+
const execEditLength = () => {
|
|
3724
|
+
for (let diagonalPath = Math.max(minDiagonalToConsider, -editLength);diagonalPath <= Math.min(maxDiagonalToConsider, editLength); diagonalPath += 2) {
|
|
3725
|
+
let basePath;
|
|
3726
|
+
const removePath = bestPath[diagonalPath - 1], addPath = bestPath[diagonalPath + 1];
|
|
3727
|
+
if (removePath) {
|
|
3728
|
+
bestPath[diagonalPath - 1] = undefined;
|
|
3729
|
+
}
|
|
3730
|
+
let canAdd = false;
|
|
3731
|
+
if (addPath) {
|
|
3732
|
+
const addPathNewPos = addPath.oldPos - diagonalPath;
|
|
3733
|
+
canAdd = addPath && 0 <= addPathNewPos && addPathNewPos < newLen;
|
|
3734
|
+
}
|
|
3735
|
+
const canRemove = removePath && removePath.oldPos + 1 < oldLen;
|
|
3736
|
+
if (!canAdd && !canRemove) {
|
|
3737
|
+
bestPath[diagonalPath] = undefined;
|
|
3738
|
+
continue;
|
|
3739
|
+
}
|
|
3740
|
+
if (!canRemove || canAdd && removePath.oldPos < addPath.oldPos) {
|
|
3741
|
+
basePath = this.addToPath(addPath, true, false, 0, options);
|
|
3742
|
+
} else {
|
|
3743
|
+
basePath = this.addToPath(removePath, false, true, 1, options);
|
|
3744
|
+
}
|
|
3745
|
+
newPos = this.extractCommon(basePath, newTokens, oldTokens, diagonalPath, options);
|
|
3746
|
+
if (basePath.oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
|
|
3747
|
+
return done(this.buildValues(basePath.lastComponent, newTokens, oldTokens)) || true;
|
|
3748
|
+
} else {
|
|
3749
|
+
bestPath[diagonalPath] = basePath;
|
|
3750
|
+
if (basePath.oldPos + 1 >= oldLen) {
|
|
3751
|
+
maxDiagonalToConsider = Math.min(maxDiagonalToConsider, diagonalPath - 1);
|
|
3752
|
+
}
|
|
3753
|
+
if (newPos + 1 >= newLen) {
|
|
3754
|
+
minDiagonalToConsider = Math.max(minDiagonalToConsider, diagonalPath + 1);
|
|
3755
|
+
}
|
|
3756
|
+
}
|
|
3757
|
+
}
|
|
3758
|
+
editLength++;
|
|
3759
|
+
};
|
|
3760
|
+
if (callback) {
|
|
3761
|
+
(function exec() {
|
|
3762
|
+
setTimeout(function() {
|
|
3763
|
+
if (editLength > maxEditLength || Date.now() > abortAfterTimestamp) {
|
|
3764
|
+
return callback(undefined);
|
|
3765
|
+
}
|
|
3766
|
+
if (!execEditLength()) {
|
|
3767
|
+
exec();
|
|
3768
|
+
}
|
|
3769
|
+
}, 0);
|
|
3770
|
+
})();
|
|
3771
|
+
} else {
|
|
3772
|
+
while (editLength <= maxEditLength && Date.now() <= abortAfterTimestamp) {
|
|
3773
|
+
const ret = execEditLength();
|
|
3774
|
+
if (ret) {
|
|
3775
|
+
return ret;
|
|
3776
|
+
}
|
|
3777
|
+
}
|
|
3778
|
+
}
|
|
3779
|
+
}
|
|
3780
|
+
addToPath(path, added, removed, oldPosInc, options) {
|
|
3781
|
+
const last = path.lastComponent;
|
|
3782
|
+
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
3783
|
+
return {
|
|
3784
|
+
oldPos: path.oldPos + oldPosInc,
|
|
3785
|
+
lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
|
|
3786
|
+
};
|
|
3787
|
+
} else {
|
|
3788
|
+
return {
|
|
3789
|
+
oldPos: path.oldPos + oldPosInc,
|
|
3790
|
+
lastComponent: { count: 1, added, removed, previousComponent: last }
|
|
3791
|
+
};
|
|
3792
|
+
}
|
|
3793
|
+
}
|
|
3794
|
+
extractCommon(basePath, newTokens, oldTokens, diagonalPath, options) {
|
|
3795
|
+
const newLen = newTokens.length, oldLen = oldTokens.length;
|
|
3796
|
+
let oldPos = basePath.oldPos, newPos = oldPos - diagonalPath, commonCount = 0;
|
|
3797
|
+
while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(oldTokens[oldPos + 1], newTokens[newPos + 1], options)) {
|
|
3798
|
+
newPos++;
|
|
3799
|
+
oldPos++;
|
|
3800
|
+
commonCount++;
|
|
3801
|
+
if (options.oneChangePerToken) {
|
|
3802
|
+
basePath.lastComponent = { count: 1, previousComponent: basePath.lastComponent, added: false, removed: false };
|
|
3803
|
+
}
|
|
3804
|
+
}
|
|
3805
|
+
if (commonCount && !options.oneChangePerToken) {
|
|
3806
|
+
basePath.lastComponent = { count: commonCount, previousComponent: basePath.lastComponent, added: false, removed: false };
|
|
3807
|
+
}
|
|
3808
|
+
basePath.oldPos = oldPos;
|
|
3809
|
+
return newPos;
|
|
3810
|
+
}
|
|
3811
|
+
equals(left, right, options) {
|
|
3812
|
+
if (options.comparator) {
|
|
3813
|
+
return options.comparator(left, right);
|
|
3814
|
+
} else {
|
|
3815
|
+
return left === right || !!options.ignoreCase && left.toLowerCase() === right.toLowerCase();
|
|
3816
|
+
}
|
|
3817
|
+
}
|
|
3818
|
+
removeEmpty(array) {
|
|
3819
|
+
const ret = [];
|
|
3820
|
+
for (let i = 0;i < array.length; i++) {
|
|
3821
|
+
if (array[i]) {
|
|
3822
|
+
ret.push(array[i]);
|
|
3823
|
+
}
|
|
3824
|
+
}
|
|
3825
|
+
return ret;
|
|
3826
|
+
}
|
|
3827
|
+
castInput(value, options) {
|
|
3828
|
+
return value;
|
|
3829
|
+
}
|
|
3830
|
+
tokenize(value, options) {
|
|
3831
|
+
return Array.from(value);
|
|
3832
|
+
}
|
|
3833
|
+
join(chars) {
|
|
3834
|
+
return chars.join("");
|
|
3835
|
+
}
|
|
3836
|
+
postProcess(changeObjects, options) {
|
|
3837
|
+
return changeObjects;
|
|
3838
|
+
}
|
|
3839
|
+
get useLongestToken() {
|
|
3840
|
+
return false;
|
|
3841
|
+
}
|
|
3842
|
+
buildValues(lastComponent, newTokens, oldTokens) {
|
|
3843
|
+
const components = [];
|
|
3844
|
+
let nextComponent;
|
|
3845
|
+
while (lastComponent) {
|
|
3846
|
+
components.push(lastComponent);
|
|
3847
|
+
nextComponent = lastComponent.previousComponent;
|
|
3848
|
+
delete lastComponent.previousComponent;
|
|
3849
|
+
lastComponent = nextComponent;
|
|
3850
|
+
}
|
|
3851
|
+
components.reverse();
|
|
3852
|
+
const componentLen = components.length;
|
|
3853
|
+
let componentPos = 0, newPos = 0, oldPos = 0;
|
|
3854
|
+
for (;componentPos < componentLen; componentPos++) {
|
|
3855
|
+
const component = components[componentPos];
|
|
3856
|
+
if (!component.removed) {
|
|
3857
|
+
if (!component.added && this.useLongestToken) {
|
|
3858
|
+
let value = newTokens.slice(newPos, newPos + component.count);
|
|
3859
|
+
value = value.map(function(value2, i) {
|
|
3860
|
+
const oldValue = oldTokens[oldPos + i];
|
|
3861
|
+
return oldValue.length > value2.length ? oldValue : value2;
|
|
3862
|
+
});
|
|
3863
|
+
component.value = this.join(value);
|
|
3864
|
+
} else {
|
|
3865
|
+
component.value = this.join(newTokens.slice(newPos, newPos + component.count));
|
|
3866
|
+
}
|
|
3867
|
+
newPos += component.count;
|
|
3868
|
+
if (!component.added) {
|
|
3869
|
+
oldPos += component.count;
|
|
3870
|
+
}
|
|
3871
|
+
} else {
|
|
3872
|
+
component.value = this.join(oldTokens.slice(oldPos, oldPos + component.count));
|
|
3873
|
+
oldPos += component.count;
|
|
3874
|
+
}
|
|
3875
|
+
}
|
|
3876
|
+
return components;
|
|
3877
|
+
}
|
|
3878
|
+
}
|
|
3879
|
+
|
|
3880
|
+
// ../../node_modules/diff/libesm/diff/character.js
|
|
3881
|
+
class CharacterDiff extends Diff {
|
|
3882
|
+
}
|
|
3883
|
+
var characterDiff = new CharacterDiff;
|
|
3884
|
+
|
|
3885
|
+
// ../../node_modules/diff/libesm/util/string.js
|
|
3886
|
+
function longestCommonPrefix(str1, str2) {
|
|
3887
|
+
let i;
|
|
3888
|
+
for (i = 0;i < str1.length && i < str2.length; i++) {
|
|
3889
|
+
if (str1[i] != str2[i]) {
|
|
3890
|
+
return str1.slice(0, i);
|
|
3891
|
+
}
|
|
3892
|
+
}
|
|
3893
|
+
return str1.slice(0, i);
|
|
3894
|
+
}
|
|
3895
|
+
function longestCommonSuffix(str1, str2) {
|
|
3896
|
+
let i;
|
|
3897
|
+
if (!str1 || !str2 || str1[str1.length - 1] != str2[str2.length - 1]) {
|
|
3898
|
+
return "";
|
|
3899
|
+
}
|
|
3900
|
+
for (i = 0;i < str1.length && i < str2.length; i++) {
|
|
3901
|
+
if (str1[str1.length - (i + 1)] != str2[str2.length - (i + 1)]) {
|
|
3902
|
+
return str1.slice(-i);
|
|
3903
|
+
}
|
|
3904
|
+
}
|
|
3905
|
+
return str1.slice(-i);
|
|
3906
|
+
}
|
|
3907
|
+
function replacePrefix(string, oldPrefix, newPrefix) {
|
|
3908
|
+
if (string.slice(0, oldPrefix.length) != oldPrefix) {
|
|
3909
|
+
throw Error(`string ${JSON.stringify(string)} doesn't start with prefix ${JSON.stringify(oldPrefix)}; this is a bug`);
|
|
3910
|
+
}
|
|
3911
|
+
return newPrefix + string.slice(oldPrefix.length);
|
|
3912
|
+
}
|
|
3913
|
+
function replaceSuffix(string, oldSuffix, newSuffix) {
|
|
3914
|
+
if (!oldSuffix) {
|
|
3915
|
+
return string + newSuffix;
|
|
3916
|
+
}
|
|
3917
|
+
if (string.slice(-oldSuffix.length) != oldSuffix) {
|
|
3918
|
+
throw Error(`string ${JSON.stringify(string)} doesn't end with suffix ${JSON.stringify(oldSuffix)}; this is a bug`);
|
|
3919
|
+
}
|
|
3920
|
+
return string.slice(0, -oldSuffix.length) + newSuffix;
|
|
3921
|
+
}
|
|
3922
|
+
function removePrefix(string, oldPrefix) {
|
|
3923
|
+
return replacePrefix(string, oldPrefix, "");
|
|
3924
|
+
}
|
|
3925
|
+
function removeSuffix(string, oldSuffix) {
|
|
3926
|
+
return replaceSuffix(string, oldSuffix, "");
|
|
3927
|
+
}
|
|
3928
|
+
function maximumOverlap(string1, string2) {
|
|
3929
|
+
return string2.slice(0, overlapCount(string1, string2));
|
|
3930
|
+
}
|
|
3931
|
+
function overlapCount(a, b) {
|
|
3932
|
+
let startA = 0;
|
|
3933
|
+
if (a.length > b.length) {
|
|
3934
|
+
startA = a.length - b.length;
|
|
3935
|
+
}
|
|
3936
|
+
let endB = b.length;
|
|
3937
|
+
if (a.length < b.length) {
|
|
3938
|
+
endB = a.length;
|
|
3939
|
+
}
|
|
3940
|
+
const map = Array(endB);
|
|
3941
|
+
let k = 0;
|
|
3942
|
+
map[0] = 0;
|
|
3943
|
+
for (let j = 1;j < endB; j++) {
|
|
3944
|
+
if (b[j] == b[k]) {
|
|
3945
|
+
map[j] = map[k];
|
|
3946
|
+
} else {
|
|
3947
|
+
map[j] = k;
|
|
3948
|
+
}
|
|
3949
|
+
while (k > 0 && b[j] != b[k]) {
|
|
3950
|
+
k = map[k];
|
|
3951
|
+
}
|
|
3952
|
+
if (b[j] == b[k]) {
|
|
3953
|
+
k++;
|
|
3954
|
+
}
|
|
3955
|
+
}
|
|
3956
|
+
k = 0;
|
|
3957
|
+
for (let i = startA;i < a.length; i++) {
|
|
3958
|
+
while (k > 0 && a[i] != b[k]) {
|
|
3959
|
+
k = map[k];
|
|
3960
|
+
}
|
|
3961
|
+
if (a[i] == b[k]) {
|
|
3962
|
+
k++;
|
|
3963
|
+
}
|
|
3964
|
+
}
|
|
3965
|
+
return k;
|
|
3966
|
+
}
|
|
3967
|
+
function trailingWs(string) {
|
|
3968
|
+
let i;
|
|
3969
|
+
for (i = string.length - 1;i >= 0; i--) {
|
|
3970
|
+
if (!string[i].match(/\s/)) {
|
|
3971
|
+
break;
|
|
3972
|
+
}
|
|
3973
|
+
}
|
|
3974
|
+
return string.substring(i + 1);
|
|
3975
|
+
}
|
|
3976
|
+
function leadingWs(string) {
|
|
3977
|
+
const match = string.match(/^\s*/);
|
|
3978
|
+
return match ? match[0] : "";
|
|
3979
|
+
}
|
|
3980
|
+
|
|
3981
|
+
// ../../node_modules/diff/libesm/diff/word.js
|
|
3982
|
+
var extendedWordChars = "a-zA-Z0-9_\\u{C0}-\\u{FF}\\u{D8}-\\u{F6}\\u{F8}-\\u{2C6}\\u{2C8}-\\u{2D7}\\u{2DE}-\\u{2FF}\\u{1E00}-\\u{1EFF}";
|
|
3983
|
+
var tokenizeIncludingWhitespace = new RegExp(`[${extendedWordChars}]+|\\s+|[^${extendedWordChars}]`, "ug");
|
|
3984
|
+
|
|
3985
|
+
class WordDiff extends Diff {
|
|
3986
|
+
equals(left, right, options) {
|
|
3987
|
+
if (options.ignoreCase) {
|
|
3988
|
+
left = left.toLowerCase();
|
|
3989
|
+
right = right.toLowerCase();
|
|
3990
|
+
}
|
|
3991
|
+
return left.trim() === right.trim();
|
|
3992
|
+
}
|
|
3993
|
+
tokenize(value, options = {}) {
|
|
3994
|
+
let parts;
|
|
3995
|
+
if (options.intlSegmenter) {
|
|
3996
|
+
const segmenter = options.intlSegmenter;
|
|
3997
|
+
if (segmenter.resolvedOptions().granularity != "word") {
|
|
3998
|
+
throw new Error('The segmenter passed must have a granularity of "word"');
|
|
3999
|
+
}
|
|
4000
|
+
parts = Array.from(segmenter.segment(value), (segment) => segment.segment);
|
|
4001
|
+
} else {
|
|
4002
|
+
parts = value.match(tokenizeIncludingWhitespace) || [];
|
|
4003
|
+
}
|
|
4004
|
+
const tokens = [];
|
|
4005
|
+
let prevPart = null;
|
|
4006
|
+
parts.forEach((part) => {
|
|
4007
|
+
if (/\s/.test(part)) {
|
|
4008
|
+
if (prevPart == null) {
|
|
4009
|
+
tokens.push(part);
|
|
4010
|
+
} else {
|
|
4011
|
+
tokens.push(tokens.pop() + part);
|
|
4012
|
+
}
|
|
4013
|
+
} else if (prevPart != null && /\s/.test(prevPart)) {
|
|
4014
|
+
if (tokens[tokens.length - 1] == prevPart) {
|
|
4015
|
+
tokens.push(tokens.pop() + part);
|
|
4016
|
+
} else {
|
|
4017
|
+
tokens.push(prevPart + part);
|
|
4018
|
+
}
|
|
4019
|
+
} else {
|
|
4020
|
+
tokens.push(part);
|
|
4021
|
+
}
|
|
4022
|
+
prevPart = part;
|
|
4023
|
+
});
|
|
4024
|
+
return tokens;
|
|
4025
|
+
}
|
|
4026
|
+
join(tokens) {
|
|
4027
|
+
return tokens.map((token, i) => {
|
|
4028
|
+
if (i == 0) {
|
|
4029
|
+
return token;
|
|
4030
|
+
} else {
|
|
4031
|
+
return token.replace(/^\s+/, "");
|
|
4032
|
+
}
|
|
4033
|
+
}).join("");
|
|
4034
|
+
}
|
|
4035
|
+
postProcess(changes, options) {
|
|
4036
|
+
if (!changes || options.oneChangePerToken) {
|
|
4037
|
+
return changes;
|
|
4038
|
+
}
|
|
4039
|
+
let lastKeep = null;
|
|
4040
|
+
let insertion = null;
|
|
4041
|
+
let deletion = null;
|
|
4042
|
+
changes.forEach((change) => {
|
|
4043
|
+
if (change.added) {
|
|
4044
|
+
insertion = change;
|
|
4045
|
+
} else if (change.removed) {
|
|
4046
|
+
deletion = change;
|
|
4047
|
+
} else {
|
|
4048
|
+
if (insertion || deletion) {
|
|
4049
|
+
dedupeWhitespaceInChangeObjects(lastKeep, deletion, insertion, change);
|
|
4050
|
+
}
|
|
4051
|
+
lastKeep = change;
|
|
4052
|
+
insertion = null;
|
|
4053
|
+
deletion = null;
|
|
4054
|
+
}
|
|
4055
|
+
});
|
|
4056
|
+
if (insertion || deletion) {
|
|
4057
|
+
dedupeWhitespaceInChangeObjects(lastKeep, deletion, insertion, null);
|
|
4058
|
+
}
|
|
4059
|
+
return changes;
|
|
4060
|
+
}
|
|
4061
|
+
}
|
|
4062
|
+
var wordDiff = new WordDiff;
|
|
4063
|
+
function dedupeWhitespaceInChangeObjects(startKeep, deletion, insertion, endKeep) {
|
|
4064
|
+
if (deletion && insertion) {
|
|
4065
|
+
const oldWsPrefix = leadingWs(deletion.value);
|
|
4066
|
+
const oldWsSuffix = trailingWs(deletion.value);
|
|
4067
|
+
const newWsPrefix = leadingWs(insertion.value);
|
|
4068
|
+
const newWsSuffix = trailingWs(insertion.value);
|
|
4069
|
+
if (startKeep) {
|
|
4070
|
+
const commonWsPrefix = longestCommonPrefix(oldWsPrefix, newWsPrefix);
|
|
4071
|
+
startKeep.value = replaceSuffix(startKeep.value, newWsPrefix, commonWsPrefix);
|
|
4072
|
+
deletion.value = removePrefix(deletion.value, commonWsPrefix);
|
|
4073
|
+
insertion.value = removePrefix(insertion.value, commonWsPrefix);
|
|
4074
|
+
}
|
|
4075
|
+
if (endKeep) {
|
|
4076
|
+
const commonWsSuffix = longestCommonSuffix(oldWsSuffix, newWsSuffix);
|
|
4077
|
+
endKeep.value = replacePrefix(endKeep.value, newWsSuffix, commonWsSuffix);
|
|
4078
|
+
deletion.value = removeSuffix(deletion.value, commonWsSuffix);
|
|
4079
|
+
insertion.value = removeSuffix(insertion.value, commonWsSuffix);
|
|
4080
|
+
}
|
|
4081
|
+
} else if (insertion) {
|
|
4082
|
+
if (startKeep) {
|
|
4083
|
+
const ws = leadingWs(insertion.value);
|
|
4084
|
+
insertion.value = insertion.value.substring(ws.length);
|
|
4085
|
+
}
|
|
4086
|
+
if (endKeep) {
|
|
4087
|
+
const ws = leadingWs(endKeep.value);
|
|
4088
|
+
endKeep.value = endKeep.value.substring(ws.length);
|
|
4089
|
+
}
|
|
4090
|
+
} else if (startKeep && endKeep) {
|
|
4091
|
+
const newWsFull = leadingWs(endKeep.value), delWsStart = leadingWs(deletion.value), delWsEnd = trailingWs(deletion.value);
|
|
4092
|
+
const newWsStart = longestCommonPrefix(newWsFull, delWsStart);
|
|
4093
|
+
deletion.value = removePrefix(deletion.value, newWsStart);
|
|
4094
|
+
const newWsEnd = longestCommonSuffix(removePrefix(newWsFull, newWsStart), delWsEnd);
|
|
4095
|
+
deletion.value = removeSuffix(deletion.value, newWsEnd);
|
|
4096
|
+
endKeep.value = replacePrefix(endKeep.value, newWsFull, newWsEnd);
|
|
4097
|
+
startKeep.value = replaceSuffix(startKeep.value, newWsFull, newWsFull.slice(0, newWsFull.length - newWsEnd.length));
|
|
4098
|
+
} else if (endKeep) {
|
|
4099
|
+
const endKeepWsPrefix = leadingWs(endKeep.value);
|
|
4100
|
+
const deletionWsSuffix = trailingWs(deletion.value);
|
|
4101
|
+
const overlap = maximumOverlap(deletionWsSuffix, endKeepWsPrefix);
|
|
4102
|
+
deletion.value = removeSuffix(deletion.value, overlap);
|
|
4103
|
+
} else if (startKeep) {
|
|
4104
|
+
const startKeepWsSuffix = trailingWs(startKeep.value);
|
|
4105
|
+
const deletionWsPrefix = leadingWs(deletion.value);
|
|
4106
|
+
const overlap = maximumOverlap(startKeepWsSuffix, deletionWsPrefix);
|
|
4107
|
+
deletion.value = removePrefix(deletion.value, overlap);
|
|
4108
|
+
}
|
|
4109
|
+
}
|
|
4110
|
+
|
|
4111
|
+
class WordsWithSpaceDiff extends Diff {
|
|
4112
|
+
tokenize(value) {
|
|
4113
|
+
const regex = new RegExp(`(\\r?\\n)|[${extendedWordChars}]+|[^\\S\\n\\r]+|[^${extendedWordChars}]`, "ug");
|
|
4114
|
+
return value.match(regex) || [];
|
|
4115
|
+
}
|
|
4116
|
+
}
|
|
4117
|
+
var wordsWithSpaceDiff = new WordsWithSpaceDiff;
|
|
4118
|
+
|
|
4119
|
+
// ../../node_modules/diff/libesm/diff/line.js
|
|
4120
|
+
class LineDiff extends Diff {
|
|
4121
|
+
constructor() {
|
|
4122
|
+
super(...arguments);
|
|
4123
|
+
this.tokenize = tokenize;
|
|
4124
|
+
}
|
|
4125
|
+
equals(left, right, options) {
|
|
4126
|
+
if (options.ignoreWhitespace) {
|
|
4127
|
+
if (!options.newlineIsToken || !left.includes(`
|
|
4128
|
+
`)) {
|
|
4129
|
+
left = left.trim();
|
|
4130
|
+
}
|
|
4131
|
+
if (!options.newlineIsToken || !right.includes(`
|
|
4132
|
+
`)) {
|
|
4133
|
+
right = right.trim();
|
|
4134
|
+
}
|
|
4135
|
+
} else if (options.ignoreNewlineAtEof && !options.newlineIsToken) {
|
|
4136
|
+
if (left.endsWith(`
|
|
4137
|
+
`)) {
|
|
4138
|
+
left = left.slice(0, -1);
|
|
4139
|
+
}
|
|
4140
|
+
if (right.endsWith(`
|
|
4141
|
+
`)) {
|
|
4142
|
+
right = right.slice(0, -1);
|
|
4143
|
+
}
|
|
4144
|
+
}
|
|
4145
|
+
return super.equals(left, right, options);
|
|
4146
|
+
}
|
|
4147
|
+
}
|
|
4148
|
+
var lineDiff = new LineDiff;
|
|
4149
|
+
function tokenize(value, options) {
|
|
4150
|
+
if (options.stripTrailingCr) {
|
|
4151
|
+
value = value.replace(/\r\n/g, `
|
|
4152
|
+
`);
|
|
4153
|
+
}
|
|
4154
|
+
const retLines = [], linesAndNewlines = value.split(/(\n|\r\n)/);
|
|
4155
|
+
if (!linesAndNewlines[linesAndNewlines.length - 1]) {
|
|
4156
|
+
linesAndNewlines.pop();
|
|
4157
|
+
}
|
|
4158
|
+
for (let i = 0;i < linesAndNewlines.length; i++) {
|
|
4159
|
+
const line = linesAndNewlines[i];
|
|
4160
|
+
if (i % 2 && !options.newlineIsToken) {
|
|
4161
|
+
retLines[retLines.length - 1] += line;
|
|
4162
|
+
} else {
|
|
4163
|
+
retLines.push(line);
|
|
4164
|
+
}
|
|
4165
|
+
}
|
|
4166
|
+
return retLines;
|
|
4167
|
+
}
|
|
4168
|
+
|
|
4169
|
+
// ../../node_modules/diff/libesm/diff/sentence.js
|
|
4170
|
+
function isSentenceEndPunct(char) {
|
|
4171
|
+
return char == "." || char == "!" || char == "?";
|
|
4172
|
+
}
|
|
4173
|
+
|
|
4174
|
+
class SentenceDiff extends Diff {
|
|
4175
|
+
tokenize(value) {
|
|
4176
|
+
var _a;
|
|
4177
|
+
const result = [];
|
|
4178
|
+
let tokenStartI = 0;
|
|
4179
|
+
for (let i = 0;i < value.length; i++) {
|
|
4180
|
+
if (i == value.length - 1) {
|
|
4181
|
+
result.push(value.slice(tokenStartI));
|
|
4182
|
+
break;
|
|
4183
|
+
}
|
|
4184
|
+
if (isSentenceEndPunct(value[i]) && value[i + 1].match(/\s/)) {
|
|
4185
|
+
result.push(value.slice(tokenStartI, i + 1));
|
|
4186
|
+
i = tokenStartI = i + 1;
|
|
4187
|
+
while ((_a = value[i + 1]) === null || _a === undefined ? undefined : _a.match(/\s/)) {
|
|
4188
|
+
i++;
|
|
4189
|
+
}
|
|
4190
|
+
result.push(value.slice(tokenStartI, i + 1));
|
|
4191
|
+
tokenStartI = i + 1;
|
|
4192
|
+
}
|
|
4193
|
+
}
|
|
4194
|
+
return result;
|
|
4195
|
+
}
|
|
4196
|
+
}
|
|
4197
|
+
var sentenceDiff = new SentenceDiff;
|
|
4198
|
+
|
|
4199
|
+
// ../../node_modules/diff/libesm/diff/css.js
|
|
4200
|
+
class CssDiff extends Diff {
|
|
4201
|
+
tokenize(value) {
|
|
4202
|
+
return value.split(/([{}:;,]|\s+)/);
|
|
4203
|
+
}
|
|
4204
|
+
}
|
|
4205
|
+
var cssDiff = new CssDiff;
|
|
4206
|
+
|
|
4207
|
+
// ../../node_modules/diff/libesm/diff/json.js
|
|
4208
|
+
class JsonDiff extends Diff {
|
|
4209
|
+
constructor() {
|
|
4210
|
+
super(...arguments);
|
|
4211
|
+
this.tokenize = tokenize;
|
|
4212
|
+
}
|
|
4213
|
+
get useLongestToken() {
|
|
4214
|
+
return true;
|
|
4215
|
+
}
|
|
4216
|
+
castInput(value, options) {
|
|
4217
|
+
const { undefinedReplacement, stringifyReplacer = (k, v) => typeof v === "undefined" ? undefinedReplacement : v } = options;
|
|
4218
|
+
return typeof value === "string" ? value : JSON.stringify(canonicalize(value, null, null, stringifyReplacer), null, " ");
|
|
4219
|
+
}
|
|
4220
|
+
equals(left, right, options) {
|
|
4221
|
+
return super.equals(left.replace(/,([\r\n])/g, "$1"), right.replace(/,([\r\n])/g, "$1"), options);
|
|
4222
|
+
}
|
|
4223
|
+
}
|
|
4224
|
+
var jsonDiff = new JsonDiff;
|
|
4225
|
+
function canonicalize(obj, stack, replacementStack, replacer, key) {
|
|
4226
|
+
stack = stack || [];
|
|
4227
|
+
replacementStack = replacementStack || [];
|
|
4228
|
+
if (replacer) {
|
|
4229
|
+
obj = replacer(key === undefined ? "" : key, obj);
|
|
4230
|
+
}
|
|
4231
|
+
let i;
|
|
4232
|
+
for (i = 0;i < stack.length; i += 1) {
|
|
4233
|
+
if (stack[i] === obj) {
|
|
4234
|
+
return replacementStack[i];
|
|
4235
|
+
}
|
|
4236
|
+
}
|
|
4237
|
+
let canonicalizedObj;
|
|
4238
|
+
if (Object.prototype.toString.call(obj) === "[object Array]") {
|
|
4239
|
+
stack.push(obj);
|
|
4240
|
+
canonicalizedObj = new Array(obj.length);
|
|
4241
|
+
replacementStack.push(canonicalizedObj);
|
|
4242
|
+
for (i = 0;i < obj.length; i += 1) {
|
|
4243
|
+
canonicalizedObj[i] = canonicalize(obj[i], stack, replacementStack, replacer, String(i));
|
|
4244
|
+
}
|
|
4245
|
+
stack.pop();
|
|
4246
|
+
replacementStack.pop();
|
|
4247
|
+
return canonicalizedObj;
|
|
4248
|
+
}
|
|
4249
|
+
if (obj && obj.toJSON) {
|
|
4250
|
+
obj = obj.toJSON();
|
|
4251
|
+
}
|
|
4252
|
+
if (typeof obj === "object" && obj !== null) {
|
|
4253
|
+
stack.push(obj);
|
|
4254
|
+
canonicalizedObj = {};
|
|
4255
|
+
replacementStack.push(canonicalizedObj);
|
|
4256
|
+
const sortedKeys = [];
|
|
4257
|
+
let key2;
|
|
4258
|
+
for (key2 in obj) {
|
|
4259
|
+
if (Object.prototype.hasOwnProperty.call(obj, key2)) {
|
|
4260
|
+
sortedKeys.push(key2);
|
|
4261
|
+
}
|
|
4262
|
+
}
|
|
4263
|
+
sortedKeys.sort();
|
|
4264
|
+
for (i = 0;i < sortedKeys.length; i += 1) {
|
|
4265
|
+
key2 = sortedKeys[i];
|
|
4266
|
+
canonicalizedObj[key2] = canonicalize(obj[key2], stack, replacementStack, replacer, key2);
|
|
4267
|
+
}
|
|
4268
|
+
stack.pop();
|
|
4269
|
+
replacementStack.pop();
|
|
4270
|
+
} else {
|
|
4271
|
+
canonicalizedObj = obj;
|
|
4272
|
+
}
|
|
4273
|
+
return canonicalizedObj;
|
|
4274
|
+
}
|
|
4275
|
+
|
|
4276
|
+
// ../../node_modules/diff/libesm/diff/array.js
|
|
4277
|
+
class ArrayDiff extends Diff {
|
|
4278
|
+
tokenize(value) {
|
|
4279
|
+
return value.slice();
|
|
4280
|
+
}
|
|
4281
|
+
join(value) {
|
|
4282
|
+
return value;
|
|
4283
|
+
}
|
|
4284
|
+
removeEmpty(value) {
|
|
4285
|
+
return value;
|
|
4286
|
+
}
|
|
4287
|
+
}
|
|
4288
|
+
var arrayDiff = new ArrayDiff;
|
|
4289
|
+
|
|
4290
|
+
// ../../node_modules/diff/libesm/patch/parse.js
|
|
4291
|
+
function parsePatch(uniDiff) {
|
|
4292
|
+
const diffstr = uniDiff.split(/\n/), list = [];
|
|
4293
|
+
let i = 0;
|
|
4294
|
+
function parseIndex() {
|
|
4295
|
+
const index = {};
|
|
4296
|
+
list.push(index);
|
|
4297
|
+
while (i < diffstr.length) {
|
|
4298
|
+
const line = diffstr[i];
|
|
4299
|
+
if (/^(---|\+\+\+|@@)\s/.test(line)) {
|
|
4300
|
+
break;
|
|
4301
|
+
}
|
|
4302
|
+
const header = /^(?:Index:|diff(?: -r \w+)+)\s+(.+?)\s*$/.exec(line);
|
|
4303
|
+
if (header) {
|
|
4304
|
+
index.index = header[1];
|
|
4305
|
+
}
|
|
4306
|
+
i++;
|
|
4307
|
+
}
|
|
4308
|
+
parseFileHeader(index);
|
|
4309
|
+
parseFileHeader(index);
|
|
4310
|
+
index.hunks = [];
|
|
4311
|
+
while (i < diffstr.length) {
|
|
4312
|
+
const line = diffstr[i];
|
|
4313
|
+
if (/^(Index:\s|diff\s|---\s|\+\+\+\s|===================================================================)/.test(line)) {
|
|
4314
|
+
break;
|
|
4315
|
+
} else if (/^@@/.test(line)) {
|
|
4316
|
+
index.hunks.push(parseHunk());
|
|
4317
|
+
} else if (line) {
|
|
4318
|
+
throw new Error("Unknown line " + (i + 1) + " " + JSON.stringify(line));
|
|
4319
|
+
} else {
|
|
4320
|
+
i++;
|
|
4321
|
+
}
|
|
4322
|
+
}
|
|
4323
|
+
}
|
|
4324
|
+
function parseFileHeader(index) {
|
|
4325
|
+
const fileHeader = /^(---|\+\+\+)\s+(.*)\r?$/.exec(diffstr[i]);
|
|
4326
|
+
if (fileHeader) {
|
|
4327
|
+
const data = fileHeader[2].split("\t", 2), header = (data[1] || "").trim();
|
|
4328
|
+
let fileName = data[0].replace(/\\\\/g, "\\");
|
|
4329
|
+
if (/^".*"$/.test(fileName)) {
|
|
4330
|
+
fileName = fileName.substr(1, fileName.length - 2);
|
|
4331
|
+
}
|
|
4332
|
+
if (fileHeader[1] === "---") {
|
|
4333
|
+
index.oldFileName = fileName;
|
|
4334
|
+
index.oldHeader = header;
|
|
4335
|
+
} else {
|
|
4336
|
+
index.newFileName = fileName;
|
|
4337
|
+
index.newHeader = header;
|
|
4338
|
+
}
|
|
4339
|
+
i++;
|
|
4340
|
+
}
|
|
4341
|
+
}
|
|
4342
|
+
function parseHunk() {
|
|
4343
|
+
var _a;
|
|
4344
|
+
const chunkHeaderIndex = i, chunkHeaderLine = diffstr[i++], chunkHeader = chunkHeaderLine.split(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);
|
|
4345
|
+
const hunk = {
|
|
4346
|
+
oldStart: +chunkHeader[1],
|
|
4347
|
+
oldLines: typeof chunkHeader[2] === "undefined" ? 1 : +chunkHeader[2],
|
|
4348
|
+
newStart: +chunkHeader[3],
|
|
4349
|
+
newLines: typeof chunkHeader[4] === "undefined" ? 1 : +chunkHeader[4],
|
|
4350
|
+
lines: []
|
|
4351
|
+
};
|
|
4352
|
+
if (hunk.oldLines === 0) {
|
|
4353
|
+
hunk.oldStart += 1;
|
|
4354
|
+
}
|
|
4355
|
+
if (hunk.newLines === 0) {
|
|
4356
|
+
hunk.newStart += 1;
|
|
4357
|
+
}
|
|
4358
|
+
let addCount = 0, removeCount = 0;
|
|
4359
|
+
for (;i < diffstr.length && (removeCount < hunk.oldLines || addCount < hunk.newLines || ((_a = diffstr[i]) === null || _a === undefined ? undefined : _a.startsWith("\\"))); i++) {
|
|
4360
|
+
const operation = diffstr[i].length == 0 && i != diffstr.length - 1 ? " " : diffstr[i][0];
|
|
4361
|
+
if (operation === "+" || operation === "-" || operation === " " || operation === "\\") {
|
|
4362
|
+
hunk.lines.push(diffstr[i]);
|
|
4363
|
+
if (operation === "+") {
|
|
4364
|
+
addCount++;
|
|
4365
|
+
} else if (operation === "-") {
|
|
4366
|
+
removeCount++;
|
|
4367
|
+
} else if (operation === " ") {
|
|
4368
|
+
addCount++;
|
|
4369
|
+
removeCount++;
|
|
4370
|
+
}
|
|
4371
|
+
} else {
|
|
4372
|
+
throw new Error(`Hunk at line ${chunkHeaderIndex + 1} contained invalid line ${diffstr[i]}`);
|
|
4373
|
+
}
|
|
4374
|
+
}
|
|
4375
|
+
if (!addCount && hunk.newLines === 1) {
|
|
4376
|
+
hunk.newLines = 0;
|
|
4377
|
+
}
|
|
4378
|
+
if (!removeCount && hunk.oldLines === 1) {
|
|
4379
|
+
hunk.oldLines = 0;
|
|
4380
|
+
}
|
|
4381
|
+
if (addCount !== hunk.newLines) {
|
|
4382
|
+
throw new Error("Added line count did not match for hunk at line " + (chunkHeaderIndex + 1));
|
|
4383
|
+
}
|
|
4384
|
+
if (removeCount !== hunk.oldLines) {
|
|
4385
|
+
throw new Error("Removed line count did not match for hunk at line " + (chunkHeaderIndex + 1));
|
|
4386
|
+
}
|
|
4387
|
+
return hunk;
|
|
4388
|
+
}
|
|
4389
|
+
while (i < diffstr.length) {
|
|
4390
|
+
parseIndex();
|
|
4391
|
+
}
|
|
4392
|
+
return list;
|
|
4393
|
+
}
|
|
4394
|
+
|
|
4395
|
+
// src/renderables/Diff.ts
|
|
4396
|
+
class DiffRenderable extends Renderable {
|
|
4397
|
+
_diff;
|
|
4398
|
+
_view;
|
|
4399
|
+
_parsedDiff = null;
|
|
4400
|
+
_filetype;
|
|
4401
|
+
_syntaxStyle;
|
|
4402
|
+
_wrapMode;
|
|
4403
|
+
_conceal;
|
|
4404
|
+
_showLineNumbers;
|
|
4405
|
+
_lineNumberFg;
|
|
4406
|
+
_lineNumberBg;
|
|
4407
|
+
_addedBg;
|
|
4408
|
+
_removedBg;
|
|
4409
|
+
_addedSignColor;
|
|
4410
|
+
_removedSignColor;
|
|
4411
|
+
leftSide = null;
|
|
4412
|
+
rightSide = null;
|
|
4413
|
+
leftSideAdded = false;
|
|
4414
|
+
rightSideAdded = false;
|
|
4415
|
+
leftCodeRenderable = null;
|
|
4416
|
+
rightCodeRenderable = null;
|
|
4417
|
+
pendingRebuild = false;
|
|
4418
|
+
constructor(ctx, options) {
|
|
4419
|
+
super(ctx, {
|
|
4420
|
+
...options,
|
|
4421
|
+
flexDirection: options.view === "split" ? "row" : "column"
|
|
4422
|
+
});
|
|
4423
|
+
this._diff = options.diff ?? "";
|
|
4424
|
+
this._view = options.view ?? "unified";
|
|
4425
|
+
this._filetype = options.filetype;
|
|
4426
|
+
this._syntaxStyle = options.syntaxStyle;
|
|
4427
|
+
this._wrapMode = options.wrapMode;
|
|
4428
|
+
this._conceal = options.conceal ?? true;
|
|
4429
|
+
this._showLineNumbers = options.showLineNumbers ?? true;
|
|
4430
|
+
this._lineNumberFg = parseColor(options.lineNumberFg ?? "#888888");
|
|
4431
|
+
this._lineNumberBg = parseColor(options.lineNumberBg ?? "transparent");
|
|
4432
|
+
this._addedBg = parseColor(options.addedBg ?? "#1a4d1a");
|
|
4433
|
+
this._removedBg = parseColor(options.removedBg ?? "#4d1a1a");
|
|
4434
|
+
this._addedSignColor = parseColor(options.addedSignColor ?? "#22c55e");
|
|
4435
|
+
this._removedSignColor = parseColor(options.removedSignColor ?? "#ef4444");
|
|
4436
|
+
if (this._diff) {
|
|
4437
|
+
this.parseDiff();
|
|
4438
|
+
this.buildView();
|
|
4439
|
+
}
|
|
4440
|
+
}
|
|
4441
|
+
parseDiff() {
|
|
4442
|
+
if (!this._diff) {
|
|
4443
|
+
this._parsedDiff = null;
|
|
4444
|
+
return;
|
|
4445
|
+
}
|
|
4446
|
+
const patches = parsePatch(this._diff);
|
|
4447
|
+
if (patches.length === 0) {
|
|
4448
|
+
this._parsedDiff = null;
|
|
4449
|
+
return;
|
|
4450
|
+
}
|
|
4451
|
+
this._parsedDiff = patches[0];
|
|
4452
|
+
}
|
|
4453
|
+
buildView() {
|
|
4454
|
+
if (!this._parsedDiff || this._parsedDiff.hunks.length === 0) {
|
|
4455
|
+
return;
|
|
4456
|
+
}
|
|
4457
|
+
if (this._view === "unified") {
|
|
4458
|
+
this.buildUnifiedView();
|
|
4459
|
+
} else {
|
|
4460
|
+
this.buildSplitView();
|
|
4461
|
+
}
|
|
4462
|
+
}
|
|
4463
|
+
onResize(width, height) {
|
|
4464
|
+
super.onResize(width, height);
|
|
4465
|
+
if (this._view === "split" && this._wrapMode !== "none" && this._wrapMode !== undefined) {
|
|
4466
|
+
this.requestRebuild();
|
|
4467
|
+
}
|
|
4468
|
+
}
|
|
4469
|
+
requestRebuild() {
|
|
4470
|
+
if (this.pendingRebuild) {
|
|
4471
|
+
return;
|
|
4472
|
+
}
|
|
4473
|
+
this.pendingRebuild = true;
|
|
4474
|
+
queueMicrotask(() => {
|
|
4475
|
+
if (!this.isDestroyed && this.pendingRebuild) {
|
|
4476
|
+
this.pendingRebuild = false;
|
|
4477
|
+
this.buildView();
|
|
4478
|
+
this.requestRender();
|
|
4479
|
+
}
|
|
4480
|
+
});
|
|
4481
|
+
}
|
|
4482
|
+
destroyRecursively() {
|
|
4483
|
+
this.pendingRebuild = false;
|
|
4484
|
+
this.leftSideAdded = false;
|
|
4485
|
+
this.rightSideAdded = false;
|
|
4486
|
+
super.destroyRecursively();
|
|
4487
|
+
}
|
|
4488
|
+
buildUnifiedView() {
|
|
4489
|
+
if (!this._parsedDiff)
|
|
4490
|
+
return;
|
|
4491
|
+
const contentLines = [];
|
|
4492
|
+
const lineColors = new Map;
|
|
4493
|
+
const lineSigns = new Map;
|
|
4494
|
+
const lineNumbers = new Map;
|
|
4495
|
+
let lineIndex = 0;
|
|
4496
|
+
for (const hunk of this._parsedDiff.hunks) {
|
|
4497
|
+
let oldLineNum = hunk.oldStart;
|
|
4498
|
+
let newLineNum = hunk.newStart;
|
|
4499
|
+
for (const line of hunk.lines) {
|
|
4500
|
+
const firstChar = line[0];
|
|
4501
|
+
const content2 = line.slice(1);
|
|
4502
|
+
if (firstChar === "+") {
|
|
4503
|
+
contentLines.push(content2);
|
|
4504
|
+
lineColors.set(lineIndex, this._addedBg);
|
|
4505
|
+
lineSigns.set(lineIndex, {
|
|
4506
|
+
after: " +",
|
|
4507
|
+
afterColor: this._addedSignColor
|
|
4508
|
+
});
|
|
4509
|
+
lineNumbers.set(lineIndex, newLineNum);
|
|
4510
|
+
newLineNum++;
|
|
4511
|
+
lineIndex++;
|
|
4512
|
+
} else if (firstChar === "-") {
|
|
4513
|
+
contentLines.push(content2);
|
|
4514
|
+
lineColors.set(lineIndex, this._removedBg);
|
|
4515
|
+
lineSigns.set(lineIndex, {
|
|
4516
|
+
after: " -",
|
|
4517
|
+
afterColor: this._removedSignColor
|
|
4518
|
+
});
|
|
4519
|
+
lineNumbers.set(lineIndex, oldLineNum);
|
|
4520
|
+
oldLineNum++;
|
|
4521
|
+
lineIndex++;
|
|
4522
|
+
} else if (firstChar === " ") {
|
|
4523
|
+
contentLines.push(content2);
|
|
4524
|
+
lineNumbers.set(lineIndex, newLineNum);
|
|
4525
|
+
oldLineNum++;
|
|
4526
|
+
newLineNum++;
|
|
4527
|
+
lineIndex++;
|
|
4528
|
+
}
|
|
4529
|
+
}
|
|
4530
|
+
}
|
|
4531
|
+
const content = contentLines.join(`
|
|
4532
|
+
`);
|
|
4533
|
+
if (!this.leftCodeRenderable) {
|
|
4534
|
+
const codeOptions = {
|
|
4535
|
+
id: this.id ? `${this.id}-left-code` : undefined,
|
|
4536
|
+
content,
|
|
4537
|
+
filetype: this._filetype,
|
|
4538
|
+
wrapMode: this._wrapMode,
|
|
4539
|
+
conceal: this._conceal,
|
|
4540
|
+
width: "100%",
|
|
4541
|
+
height: "100%"
|
|
4542
|
+
};
|
|
4543
|
+
if (this._syntaxStyle) {
|
|
4544
|
+
codeOptions.syntaxStyle = this._syntaxStyle;
|
|
4545
|
+
}
|
|
4546
|
+
this.leftCodeRenderable = new CodeRenderable(this.ctx, codeOptions);
|
|
4547
|
+
} else {
|
|
4548
|
+
this.leftCodeRenderable.content = content;
|
|
4549
|
+
if (this._filetype !== undefined) {
|
|
4550
|
+
this.leftCodeRenderable.filetype = this._filetype;
|
|
4551
|
+
}
|
|
4552
|
+
if (this._syntaxStyle !== undefined) {
|
|
4553
|
+
this.leftCodeRenderable.syntaxStyle = this._syntaxStyle;
|
|
4554
|
+
}
|
|
4555
|
+
this.leftCodeRenderable.wrapMode = this._wrapMode ?? "none";
|
|
4556
|
+
}
|
|
4557
|
+
if (!this.leftSide) {
|
|
4558
|
+
this.leftSide = new LineNumberRenderable(this.ctx, {
|
|
4559
|
+
id: this.id ? `${this.id}-left` : undefined,
|
|
4560
|
+
target: this.leftCodeRenderable,
|
|
4561
|
+
fg: this._lineNumberFg,
|
|
4562
|
+
bg: this._lineNumberBg,
|
|
4563
|
+
lineColors,
|
|
4564
|
+
lineSigns,
|
|
4565
|
+
lineNumbers,
|
|
4566
|
+
lineNumberOffset: 0,
|
|
4567
|
+
hideLineNumbers: new Set,
|
|
4568
|
+
width: "100%",
|
|
4569
|
+
height: "100%"
|
|
4570
|
+
});
|
|
4571
|
+
this.leftSide.showLineNumbers = this._showLineNumbers;
|
|
4572
|
+
super.add(this.leftSide);
|
|
4573
|
+
this.leftSideAdded = true;
|
|
4574
|
+
} else {
|
|
4575
|
+
this.leftSide.setLineColors(lineColors);
|
|
4576
|
+
this.leftSide.setLineSigns(lineSigns);
|
|
4577
|
+
this.leftSide.setLineNumbers(lineNumbers);
|
|
4578
|
+
this.leftSide.setHideLineNumbers(new Set);
|
|
4579
|
+
this.leftSide.width = "100%";
|
|
4580
|
+
if (!this.leftSideAdded) {
|
|
4581
|
+
super.add(this.leftSide);
|
|
4582
|
+
this.leftSideAdded = true;
|
|
4583
|
+
}
|
|
4584
|
+
}
|
|
4585
|
+
if (this.rightSide && this.rightSideAdded) {
|
|
4586
|
+
super.remove(this.rightSide.id);
|
|
4587
|
+
this.rightSideAdded = false;
|
|
4588
|
+
}
|
|
4589
|
+
}
|
|
4590
|
+
buildSplitView() {
|
|
4591
|
+
if (!this._parsedDiff)
|
|
4592
|
+
return;
|
|
4593
|
+
const leftLogicalLines = [];
|
|
4594
|
+
const rightLogicalLines = [];
|
|
4595
|
+
for (const hunk of this._parsedDiff.hunks) {
|
|
4596
|
+
let oldLineNum = hunk.oldStart;
|
|
4597
|
+
let newLineNum = hunk.newStart;
|
|
4598
|
+
let i = 0;
|
|
4599
|
+
while (i < hunk.lines.length) {
|
|
4600
|
+
const line = hunk.lines[i];
|
|
4601
|
+
const firstChar = line[0];
|
|
4602
|
+
if (firstChar === " ") {
|
|
4603
|
+
const content = line.slice(1);
|
|
4604
|
+
leftLogicalLines.push({
|
|
4605
|
+
content,
|
|
4606
|
+
lineNum: oldLineNum,
|
|
4607
|
+
type: "context"
|
|
4608
|
+
});
|
|
4609
|
+
rightLogicalLines.push({
|
|
4610
|
+
content,
|
|
4611
|
+
lineNum: newLineNum,
|
|
4612
|
+
type: "context"
|
|
4613
|
+
});
|
|
4614
|
+
oldLineNum++;
|
|
4615
|
+
newLineNum++;
|
|
4616
|
+
i++;
|
|
4617
|
+
} else if (firstChar === "\\") {
|
|
4618
|
+
i++;
|
|
4619
|
+
} else {
|
|
4620
|
+
const removes = [];
|
|
4621
|
+
const adds = [];
|
|
4622
|
+
while (i < hunk.lines.length) {
|
|
4623
|
+
const currentLine = hunk.lines[i];
|
|
4624
|
+
const currentChar = currentLine[0];
|
|
4625
|
+
if (currentChar === " " || currentChar === "\\") {
|
|
4626
|
+
break;
|
|
4627
|
+
}
|
|
4628
|
+
const content = currentLine.slice(1);
|
|
4629
|
+
if (currentChar === "-") {
|
|
4630
|
+
removes.push({ content, lineNum: oldLineNum });
|
|
4631
|
+
oldLineNum++;
|
|
4632
|
+
} else if (currentChar === "+") {
|
|
4633
|
+
adds.push({ content, lineNum: newLineNum });
|
|
4634
|
+
newLineNum++;
|
|
4635
|
+
}
|
|
4636
|
+
i++;
|
|
4637
|
+
}
|
|
4638
|
+
const maxLength = Math.max(removes.length, adds.length);
|
|
4639
|
+
for (let j = 0;j < maxLength; j++) {
|
|
4640
|
+
if (j < removes.length) {
|
|
4641
|
+
leftLogicalLines.push({
|
|
4642
|
+
content: removes[j].content,
|
|
4643
|
+
lineNum: removes[j].lineNum,
|
|
4644
|
+
color: this._removedBg,
|
|
4645
|
+
sign: {
|
|
4646
|
+
after: " -",
|
|
4647
|
+
afterColor: this._removedSignColor
|
|
4648
|
+
},
|
|
4649
|
+
type: "remove"
|
|
4650
|
+
});
|
|
4651
|
+
} else {
|
|
4652
|
+
leftLogicalLines.push({
|
|
4653
|
+
content: "",
|
|
4654
|
+
hideLineNumber: true,
|
|
4655
|
+
type: "empty"
|
|
4656
|
+
});
|
|
4657
|
+
}
|
|
4658
|
+
if (j < adds.length) {
|
|
4659
|
+
rightLogicalLines.push({
|
|
4660
|
+
content: adds[j].content,
|
|
4661
|
+
lineNum: adds[j].lineNum,
|
|
4662
|
+
color: this._addedBg,
|
|
4663
|
+
sign: {
|
|
4664
|
+
after: " +",
|
|
4665
|
+
afterColor: this._addedSignColor
|
|
4666
|
+
},
|
|
4667
|
+
type: "add"
|
|
4668
|
+
});
|
|
4669
|
+
} else {
|
|
4670
|
+
rightLogicalLines.push({
|
|
4671
|
+
content: "",
|
|
4672
|
+
hideLineNumber: true,
|
|
4673
|
+
type: "empty"
|
|
4674
|
+
});
|
|
4675
|
+
}
|
|
4676
|
+
}
|
|
4677
|
+
}
|
|
4678
|
+
}
|
|
4679
|
+
}
|
|
4680
|
+
const canDoWrapAlignment = this.width > 0 && (this._wrapMode === "word" || this._wrapMode === "char");
|
|
4681
|
+
const preLeftContent = leftLogicalLines.map((l) => l.content).join(`
|
|
4682
|
+
`);
|
|
4683
|
+
const preRightContent = rightLogicalLines.map((l) => l.content).join(`
|
|
4684
|
+
`);
|
|
4685
|
+
const effectiveWrapMode = canDoWrapAlignment ? this._wrapMode : "none";
|
|
4686
|
+
if (!this.leftCodeRenderable) {
|
|
4687
|
+
const leftCodeOptions = {
|
|
4688
|
+
id: this.id ? `${this.id}-left-code` : undefined,
|
|
4689
|
+
content: preLeftContent,
|
|
4690
|
+
filetype: this._filetype,
|
|
4691
|
+
wrapMode: effectiveWrapMode,
|
|
4692
|
+
conceal: this._conceal,
|
|
4693
|
+
drawUnstyledText: true,
|
|
4694
|
+
width: "100%",
|
|
4695
|
+
height: "100%"
|
|
4696
|
+
};
|
|
4697
|
+
if (this._syntaxStyle) {
|
|
4698
|
+
leftCodeOptions.syntaxStyle = this._syntaxStyle;
|
|
4699
|
+
}
|
|
4700
|
+
this.leftCodeRenderable = new CodeRenderable(this.ctx, leftCodeOptions);
|
|
4701
|
+
} else {
|
|
4702
|
+
this.leftCodeRenderable.content = preLeftContent;
|
|
4703
|
+
this.leftCodeRenderable.wrapMode = effectiveWrapMode;
|
|
4704
|
+
this.leftCodeRenderable.drawUnstyledText = true;
|
|
4705
|
+
if (this._filetype !== undefined) {
|
|
4706
|
+
this.leftCodeRenderable.filetype = this._filetype;
|
|
4707
|
+
}
|
|
4708
|
+
if (this._syntaxStyle !== undefined) {
|
|
4709
|
+
this.leftCodeRenderable.syntaxStyle = this._syntaxStyle;
|
|
4710
|
+
}
|
|
4711
|
+
}
|
|
4712
|
+
if (!this.rightCodeRenderable) {
|
|
4713
|
+
const rightCodeOptions = {
|
|
4714
|
+
id: this.id ? `${this.id}-right-code` : undefined,
|
|
4715
|
+
content: preRightContent,
|
|
4716
|
+
filetype: this._filetype,
|
|
4717
|
+
wrapMode: effectiveWrapMode,
|
|
4718
|
+
conceal: this._conceal,
|
|
4719
|
+
drawUnstyledText: true,
|
|
4720
|
+
width: "100%",
|
|
4721
|
+
height: "100%"
|
|
4722
|
+
};
|
|
4723
|
+
if (this._syntaxStyle) {
|
|
4724
|
+
rightCodeOptions.syntaxStyle = this._syntaxStyle;
|
|
4725
|
+
}
|
|
4726
|
+
this.rightCodeRenderable = new CodeRenderable(this.ctx, rightCodeOptions);
|
|
4727
|
+
} else {
|
|
4728
|
+
this.rightCodeRenderable.content = preRightContent;
|
|
4729
|
+
this.rightCodeRenderable.wrapMode = effectiveWrapMode;
|
|
4730
|
+
this.rightCodeRenderable.drawUnstyledText = true;
|
|
4731
|
+
if (this._filetype !== undefined) {
|
|
4732
|
+
this.rightCodeRenderable.filetype = this._filetype;
|
|
4733
|
+
}
|
|
4734
|
+
if (this._syntaxStyle !== undefined) {
|
|
4735
|
+
this.rightCodeRenderable.syntaxStyle = this._syntaxStyle;
|
|
4736
|
+
}
|
|
4737
|
+
}
|
|
4738
|
+
let finalLeftLines;
|
|
4739
|
+
let finalRightLines;
|
|
4740
|
+
if (canDoWrapAlignment) {
|
|
4741
|
+
const leftLineInfo = this.leftCodeRenderable.lineInfo;
|
|
4742
|
+
const rightLineInfo = this.rightCodeRenderable.lineInfo;
|
|
4743
|
+
const leftSources = leftLineInfo.lineSources || [];
|
|
4744
|
+
const rightSources = rightLineInfo.lineSources || [];
|
|
4745
|
+
const leftVisualCounts = new Map;
|
|
4746
|
+
const rightVisualCounts = new Map;
|
|
4747
|
+
for (const logicalLine of leftSources) {
|
|
4748
|
+
leftVisualCounts.set(logicalLine, (leftVisualCounts.get(logicalLine) || 0) + 1);
|
|
4749
|
+
}
|
|
4750
|
+
for (const logicalLine of rightSources) {
|
|
4751
|
+
rightVisualCounts.set(logicalLine, (rightVisualCounts.get(logicalLine) || 0) + 1);
|
|
4752
|
+
}
|
|
4753
|
+
finalLeftLines = [];
|
|
4754
|
+
finalRightLines = [];
|
|
4755
|
+
let leftVisualPos = 0;
|
|
4756
|
+
let rightVisualPos = 0;
|
|
4757
|
+
for (let i = 0;i < leftLogicalLines.length; i++) {
|
|
4758
|
+
const leftLine = leftLogicalLines[i];
|
|
4759
|
+
const rightLine = rightLogicalLines[i];
|
|
4760
|
+
const leftVisualCount = leftVisualCounts.get(i) || 1;
|
|
4761
|
+
const rightVisualCount = rightVisualCounts.get(i) || 1;
|
|
4762
|
+
if (leftVisualPos < rightVisualPos) {
|
|
4763
|
+
const pad = rightVisualPos - leftVisualPos;
|
|
4764
|
+
for (let p = 0;p < pad; p++) {
|
|
4765
|
+
finalLeftLines.push({ content: "", hideLineNumber: true, type: "empty" });
|
|
4766
|
+
}
|
|
4767
|
+
leftVisualPos += pad;
|
|
4768
|
+
} else if (rightVisualPos < leftVisualPos) {
|
|
4769
|
+
const pad = leftVisualPos - rightVisualPos;
|
|
4770
|
+
for (let p = 0;p < pad; p++) {
|
|
4771
|
+
finalRightLines.push({ content: "", hideLineNumber: true, type: "empty" });
|
|
4772
|
+
}
|
|
4773
|
+
rightVisualPos += pad;
|
|
4774
|
+
}
|
|
4775
|
+
finalLeftLines.push(leftLine);
|
|
4776
|
+
finalRightLines.push(rightLine);
|
|
4777
|
+
leftVisualPos += leftVisualCount;
|
|
4778
|
+
rightVisualPos += rightVisualCount;
|
|
4779
|
+
}
|
|
4780
|
+
if (leftVisualPos < rightVisualPos) {
|
|
4781
|
+
const pad = rightVisualPos - leftVisualPos;
|
|
4782
|
+
for (let p = 0;p < pad; p++) {
|
|
4783
|
+
finalLeftLines.push({ content: "", hideLineNumber: true, type: "empty" });
|
|
4784
|
+
}
|
|
4785
|
+
} else if (rightVisualPos < leftVisualPos) {
|
|
4786
|
+
const pad = leftVisualPos - rightVisualPos;
|
|
4787
|
+
for (let p = 0;p < pad; p++) {
|
|
4788
|
+
finalRightLines.push({ content: "", hideLineNumber: true, type: "empty" });
|
|
4789
|
+
}
|
|
4790
|
+
}
|
|
4791
|
+
} else {
|
|
4792
|
+
finalLeftLines = leftLogicalLines;
|
|
4793
|
+
finalRightLines = rightLogicalLines;
|
|
4794
|
+
}
|
|
4795
|
+
const leftLineColors = new Map;
|
|
4796
|
+
const rightLineColors = new Map;
|
|
4797
|
+
const leftLineSigns = new Map;
|
|
4798
|
+
const rightLineSigns = new Map;
|
|
4799
|
+
const leftHideLineNumbers = new Set;
|
|
4800
|
+
const rightHideLineNumbers = new Set;
|
|
4801
|
+
const leftLineNumbers = new Map;
|
|
4802
|
+
const rightLineNumbers = new Map;
|
|
4803
|
+
finalLeftLines.forEach((line, index) => {
|
|
4804
|
+
if (line.lineNum !== undefined) {
|
|
4805
|
+
leftLineNumbers.set(index, line.lineNum);
|
|
4806
|
+
}
|
|
4807
|
+
if (line.hideLineNumber) {
|
|
4808
|
+
leftHideLineNumbers.add(index);
|
|
4809
|
+
}
|
|
4810
|
+
if (line.color) {
|
|
4811
|
+
leftLineColors.set(index, line.color);
|
|
4812
|
+
}
|
|
4813
|
+
if (line.sign) {
|
|
4814
|
+
leftLineSigns.set(index, line.sign);
|
|
4815
|
+
}
|
|
4816
|
+
});
|
|
4817
|
+
finalRightLines.forEach((line, index) => {
|
|
4818
|
+
if (line.lineNum !== undefined) {
|
|
4819
|
+
rightLineNumbers.set(index, line.lineNum);
|
|
4820
|
+
}
|
|
4821
|
+
if (line.hideLineNumber) {
|
|
4822
|
+
rightHideLineNumbers.add(index);
|
|
4823
|
+
}
|
|
4824
|
+
if (line.color) {
|
|
4825
|
+
rightLineColors.set(index, line.color);
|
|
4826
|
+
}
|
|
4827
|
+
if (line.sign) {
|
|
4828
|
+
rightLineSigns.set(index, line.sign);
|
|
4829
|
+
}
|
|
4830
|
+
});
|
|
4831
|
+
const leftContentFinal = finalLeftLines.map((l) => l.content).join(`
|
|
4832
|
+
`);
|
|
4833
|
+
const rightContentFinal = finalRightLines.map((l) => l.content).join(`
|
|
4834
|
+
`);
|
|
4835
|
+
this.leftCodeRenderable.content = leftContentFinal;
|
|
4836
|
+
this.rightCodeRenderable.content = rightContentFinal;
|
|
4837
|
+
if (!this.leftSide) {
|
|
4838
|
+
this.leftSide = new LineNumberRenderable(this.ctx, {
|
|
4839
|
+
id: this.id ? `${this.id}-left` : undefined,
|
|
4840
|
+
target: this.leftCodeRenderable,
|
|
4841
|
+
fg: this._lineNumberFg,
|
|
4842
|
+
bg: this._lineNumberBg,
|
|
4843
|
+
lineColors: leftLineColors,
|
|
4844
|
+
lineSigns: leftLineSigns,
|
|
4845
|
+
lineNumbers: leftLineNumbers,
|
|
4846
|
+
lineNumberOffset: 0,
|
|
4847
|
+
hideLineNumbers: leftHideLineNumbers,
|
|
4848
|
+
width: "50%",
|
|
4849
|
+
height: "100%"
|
|
4850
|
+
});
|
|
4851
|
+
this.leftSide.showLineNumbers = this._showLineNumbers;
|
|
4852
|
+
super.add(this.leftSide);
|
|
4853
|
+
this.leftSideAdded = true;
|
|
4854
|
+
} else {
|
|
4855
|
+
this.leftSide.width = "50%";
|
|
4856
|
+
this.leftSide.setLineColors(leftLineColors);
|
|
4857
|
+
this.leftSide.setLineSigns(leftLineSigns);
|
|
4858
|
+
this.leftSide.setLineNumbers(leftLineNumbers);
|
|
4859
|
+
this.leftSide.setHideLineNumbers(leftHideLineNumbers);
|
|
4860
|
+
if (!this.leftSideAdded) {
|
|
4861
|
+
super.add(this.leftSide);
|
|
4862
|
+
this.leftSideAdded = true;
|
|
4863
|
+
}
|
|
2985
4864
|
}
|
|
2986
|
-
this.
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
4865
|
+
if (!this.rightSide) {
|
|
4866
|
+
this.rightSide = new LineNumberRenderable(this.ctx, {
|
|
4867
|
+
id: this.id ? `${this.id}-right` : undefined,
|
|
4868
|
+
target: this.rightCodeRenderable,
|
|
4869
|
+
fg: this._lineNumberFg,
|
|
4870
|
+
bg: this._lineNumberBg,
|
|
4871
|
+
lineColors: rightLineColors,
|
|
4872
|
+
lineSigns: rightLineSigns,
|
|
4873
|
+
lineNumbers: rightLineNumbers,
|
|
4874
|
+
lineNumberOffset: 0,
|
|
4875
|
+
hideLineNumbers: rightHideLineNumbers,
|
|
4876
|
+
width: "50%",
|
|
4877
|
+
height: "100%"
|
|
4878
|
+
});
|
|
4879
|
+
this.rightSide.showLineNumbers = this._showLineNumbers;
|
|
4880
|
+
super.add(this.rightSide);
|
|
4881
|
+
this.rightSideAdded = true;
|
|
4882
|
+
} else {
|
|
4883
|
+
this.rightSide.setLineColors(rightLineColors);
|
|
4884
|
+
this.rightSide.setLineSigns(rightLineSigns);
|
|
4885
|
+
this.rightSide.setLineNumbers(rightLineNumbers);
|
|
4886
|
+
this.rightSide.setHideLineNumbers(rightHideLineNumbers);
|
|
4887
|
+
if (!this.rightSideAdded) {
|
|
4888
|
+
super.add(this.rightSide);
|
|
4889
|
+
this.rightSideAdded = true;
|
|
4890
|
+
}
|
|
2993
4891
|
}
|
|
2994
|
-
const child = this._children[childIndex];
|
|
2995
|
-
this._children.splice(childIndex, 1);
|
|
2996
|
-
child.parent = null;
|
|
2997
|
-
this.requestRender();
|
|
2998
|
-
return this;
|
|
2999
|
-
}
|
|
3000
|
-
clear() {
|
|
3001
|
-
this._children = [];
|
|
3002
|
-
this.requestRender();
|
|
3003
4892
|
}
|
|
3004
|
-
|
|
3005
|
-
return
|
|
3006
|
-
fg: this._fg ?? parentStyle.fg,
|
|
3007
|
-
bg: this._bg ?? parentStyle.bg,
|
|
3008
|
-
attributes: this._attributes | parentStyle.attributes
|
|
3009
|
-
};
|
|
4893
|
+
get diff() {
|
|
4894
|
+
return this._diff;
|
|
3010
4895
|
}
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
if (
|
|
3016
|
-
|
|
3017
|
-
__isChunk: true,
|
|
3018
|
-
text: child,
|
|
3019
|
-
fg: currentStyle.fg,
|
|
3020
|
-
bg: currentStyle.bg,
|
|
3021
|
-
attributes: currentStyle.attributes
|
|
3022
|
-
});
|
|
4896
|
+
set diff(value) {
|
|
4897
|
+
if (this._diff !== value) {
|
|
4898
|
+
this._diff = value;
|
|
4899
|
+
this.parseDiff();
|
|
4900
|
+
if (this._view === "split") {
|
|
4901
|
+
this.requestRebuild();
|
|
3023
4902
|
} else {
|
|
3024
|
-
|
|
3025
|
-
chunks.push(...childChunks);
|
|
4903
|
+
this.buildView();
|
|
3026
4904
|
}
|
|
3027
4905
|
}
|
|
3028
|
-
this.markClean();
|
|
3029
|
-
return chunks;
|
|
3030
4906
|
}
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
node.add(text);
|
|
3034
|
-
return node;
|
|
4907
|
+
get view() {
|
|
4908
|
+
return this._view;
|
|
3035
4909
|
}
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
4910
|
+
set view(value) {
|
|
4911
|
+
if (this._view !== value) {
|
|
4912
|
+
this._view = value;
|
|
4913
|
+
this.flexDirection = value === "split" ? "row" : "column";
|
|
4914
|
+
this.buildView();
|
|
3040
4915
|
}
|
|
3041
|
-
return node;
|
|
3042
|
-
}
|
|
3043
|
-
toChunks(parentStyle = { fg: undefined, bg: undefined, attributes: 0 }) {
|
|
3044
|
-
return this.gatherWithInheritedStyle(parentStyle);
|
|
3045
|
-
}
|
|
3046
|
-
getChildren() {
|
|
3047
|
-
return this._children.filter((child) => typeof child !== "string");
|
|
3048
4916
|
}
|
|
3049
|
-
|
|
3050
|
-
return this.
|
|
3051
|
-
}
|
|
3052
|
-
getRenderable(id) {
|
|
3053
|
-
return this._children.find((child) => typeof child !== "string" && child.id === id);
|
|
3054
|
-
}
|
|
3055
|
-
getRenderableIndex(id) {
|
|
3056
|
-
return this._children.findIndex((child) => isTextNodeRenderable(child) && child.id === id);
|
|
3057
|
-
}
|
|
3058
|
-
get fg() {
|
|
3059
|
-
return this._fg;
|
|
3060
|
-
}
|
|
3061
|
-
set fg(fg2) {
|
|
3062
|
-
if (!fg2) {
|
|
3063
|
-
this._fg = undefined;
|
|
3064
|
-
this.requestRender();
|
|
3065
|
-
return;
|
|
3066
|
-
}
|
|
3067
|
-
this._fg = parseColor(fg2);
|
|
3068
|
-
this.requestRender();
|
|
4917
|
+
get filetype() {
|
|
4918
|
+
return this._filetype;
|
|
3069
4919
|
}
|
|
3070
|
-
set
|
|
3071
|
-
if (
|
|
3072
|
-
this.
|
|
3073
|
-
this.
|
|
3074
|
-
|
|
4920
|
+
set filetype(value) {
|
|
4921
|
+
if (this._filetype !== value) {
|
|
4922
|
+
this._filetype = value;
|
|
4923
|
+
if (this._view === "split") {
|
|
4924
|
+
this.requestRebuild();
|
|
4925
|
+
} else {
|
|
4926
|
+
this.buildView();
|
|
4927
|
+
}
|
|
3075
4928
|
}
|
|
3076
|
-
this._bg = parseColor(bg2);
|
|
3077
|
-
this.requestRender();
|
|
3078
|
-
}
|
|
3079
|
-
get bg() {
|
|
3080
|
-
return this._bg;
|
|
3081
|
-
}
|
|
3082
|
-
set attributes(attributes) {
|
|
3083
|
-
this._attributes = attributes;
|
|
3084
|
-
this.requestRender();
|
|
3085
|
-
}
|
|
3086
|
-
get attributes() {
|
|
3087
|
-
return this._attributes;
|
|
3088
4929
|
}
|
|
3089
|
-
|
|
3090
|
-
return;
|
|
4930
|
+
get syntaxStyle() {
|
|
4931
|
+
return this._syntaxStyle;
|
|
3091
4932
|
}
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
4933
|
+
set syntaxStyle(value) {
|
|
4934
|
+
if (this._syntaxStyle !== value) {
|
|
4935
|
+
this._syntaxStyle = value;
|
|
4936
|
+
if (this._view === "split") {
|
|
4937
|
+
this.requestRebuild();
|
|
4938
|
+
} else {
|
|
4939
|
+
this.buildView();
|
|
4940
|
+
}
|
|
4941
|
+
}
|
|
3101
4942
|
}
|
|
3102
|
-
|
|
3103
|
-
this.
|
|
3104
|
-
this.ctx.requestRender();
|
|
4943
|
+
get wrapMode() {
|
|
4944
|
+
return this._wrapMode;
|
|
3105
4945
|
}
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
}
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
}
|
|
3115
|
-
function Text(props, ...children) {
|
|
3116
|
-
return h(TextRenderable, props || {}, ...children);
|
|
3117
|
-
}
|
|
3118
|
-
function ASCIIFont(props, ...children) {
|
|
3119
|
-
return h(ASCIIFontRenderable, props || {}, ...children);
|
|
3120
|
-
}
|
|
3121
|
-
function Input(props, ...children) {
|
|
3122
|
-
return h(InputRenderable, props || {}, ...children);
|
|
3123
|
-
}
|
|
3124
|
-
function Select(props, ...children) {
|
|
3125
|
-
return h(SelectRenderable, props || {}, ...children);
|
|
3126
|
-
}
|
|
3127
|
-
function TabSelect(props, ...children) {
|
|
3128
|
-
return h(TabSelectRenderable, props || {}, ...children);
|
|
3129
|
-
}
|
|
3130
|
-
function FrameBuffer(props, ...children) {
|
|
3131
|
-
return h(FrameBufferRenderable, props, ...children);
|
|
3132
|
-
}
|
|
3133
|
-
function StyledText2(props, ...children) {
|
|
3134
|
-
const styledProps = props;
|
|
3135
|
-
const textNodeOptions = {
|
|
3136
|
-
...styledProps,
|
|
3137
|
-
attributes: styledProps?.attributes ?? 0
|
|
3138
|
-
};
|
|
3139
|
-
const textNode = new TextNodeRenderable(textNodeOptions);
|
|
3140
|
-
for (const child of children) {
|
|
3141
|
-
textNode.add(child);
|
|
4946
|
+
set wrapMode(value) {
|
|
4947
|
+
if (this._wrapMode !== value) {
|
|
4948
|
+
this._wrapMode = value;
|
|
4949
|
+
if (this._view === "unified" && this.leftCodeRenderable) {
|
|
4950
|
+
this.leftCodeRenderable.wrapMode = value ?? "none";
|
|
4951
|
+
} else if (this._view === "split") {
|
|
4952
|
+
this.requestRebuild();
|
|
4953
|
+
}
|
|
4954
|
+
}
|
|
3142
4955
|
}
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
var vstyles = {
|
|
3146
|
-
bold: (...children) => StyledText2({ attributes: TextAttributes.BOLD }, ...children),
|
|
3147
|
-
italic: (...children) => StyledText2({ attributes: TextAttributes.ITALIC }, ...children),
|
|
3148
|
-
underline: (...children) => StyledText2({ attributes: TextAttributes.UNDERLINE }, ...children),
|
|
3149
|
-
dim: (...children) => StyledText2({ attributes: TextAttributes.DIM }, ...children),
|
|
3150
|
-
blink: (...children) => StyledText2({ attributes: TextAttributes.BLINK }, ...children),
|
|
3151
|
-
inverse: (...children) => StyledText2({ attributes: TextAttributes.INVERSE }, ...children),
|
|
3152
|
-
hidden: (...children) => StyledText2({ attributes: TextAttributes.HIDDEN }, ...children),
|
|
3153
|
-
strikethrough: (...children) => StyledText2({ attributes: TextAttributes.STRIKETHROUGH }, ...children),
|
|
3154
|
-
boldItalic: (...children) => StyledText2({ attributes: TextAttributes.BOLD | TextAttributes.ITALIC }, ...children),
|
|
3155
|
-
boldUnderline: (...children) => StyledText2({ attributes: TextAttributes.BOLD | TextAttributes.UNDERLINE }, ...children),
|
|
3156
|
-
italicUnderline: (...children) => StyledText2({ attributes: TextAttributes.ITALIC | TextAttributes.UNDERLINE }, ...children),
|
|
3157
|
-
boldItalicUnderline: (...children) => StyledText2({ attributes: TextAttributes.BOLD | TextAttributes.ITALIC | TextAttributes.UNDERLINE }, ...children),
|
|
3158
|
-
color: (color, ...children) => StyledText2({ fg: color }, ...children),
|
|
3159
|
-
bgColor: (bgColor, ...children) => StyledText2({ bg: bgColor }, ...children),
|
|
3160
|
-
fg: (color, ...children) => StyledText2({ fg: color }, ...children),
|
|
3161
|
-
bg: (bgColor, ...children) => StyledText2({ bg: bgColor }, ...children),
|
|
3162
|
-
styled: (attributes = 0, ...children) => StyledText2({ attributes }, ...children)
|
|
3163
|
-
};
|
|
3164
|
-
// src/renderables/composition/VRenderable.ts
|
|
3165
|
-
class VRenderable extends Renderable {
|
|
3166
|
-
options;
|
|
3167
|
-
constructor(ctx, options) {
|
|
3168
|
-
super(ctx, options);
|
|
3169
|
-
this.options = options;
|
|
4956
|
+
get showLineNumbers() {
|
|
4957
|
+
return this._showLineNumbers;
|
|
3170
4958
|
}
|
|
3171
|
-
|
|
3172
|
-
if (this.
|
|
3173
|
-
this.
|
|
4959
|
+
set showLineNumbers(value) {
|
|
4960
|
+
if (this._showLineNumbers !== value) {
|
|
4961
|
+
this._showLineNumbers = value;
|
|
4962
|
+
if (this.leftSide) {
|
|
4963
|
+
this.leftSide.showLineNumbers = value;
|
|
4964
|
+
}
|
|
4965
|
+
if (this.rightSide) {
|
|
4966
|
+
this.rightSide.showLineNumbers = value;
|
|
4967
|
+
}
|
|
3174
4968
|
}
|
|
3175
4969
|
}
|
|
3176
4970
|
}
|
|
@@ -4094,6 +5888,8 @@ class ScrollBoxRenderable extends BoxRenderable {
|
|
|
4094
5888
|
cachedAutoScrollSpeed = 3;
|
|
4095
5889
|
autoScrollAccumulatorX = 0;
|
|
4096
5890
|
autoScrollAccumulatorY = 0;
|
|
5891
|
+
scrollAccumulatorX = 0;
|
|
5892
|
+
scrollAccumulatorY = 0;
|
|
4097
5893
|
_stickyScroll;
|
|
4098
5894
|
_stickyScrollTop = false;
|
|
4099
5895
|
_stickyScrollBottom = false;
|
|
@@ -4369,14 +6165,35 @@ class ScrollBoxRenderable extends BoxRenderable {
|
|
|
4369
6165
|
const baseDelta = event.scroll?.delta ?? 0;
|
|
4370
6166
|
const now = Date.now();
|
|
4371
6167
|
const multiplier = this.scrollAccel.tick(now);
|
|
6168
|
+
const scrollAmount = baseDelta * multiplier;
|
|
4372
6169
|
if (dir === "up") {
|
|
4373
|
-
this.
|
|
6170
|
+
this.scrollAccumulatorY -= scrollAmount;
|
|
6171
|
+
const integerScroll = Math.trunc(this.scrollAccumulatorY);
|
|
6172
|
+
if (integerScroll !== 0) {
|
|
6173
|
+
this.scrollTop += integerScroll;
|
|
6174
|
+
this.scrollAccumulatorY -= integerScroll;
|
|
6175
|
+
}
|
|
4374
6176
|
} else if (dir === "down") {
|
|
4375
|
-
this.
|
|
6177
|
+
this.scrollAccumulatorY += scrollAmount;
|
|
6178
|
+
const integerScroll = Math.trunc(this.scrollAccumulatorY);
|
|
6179
|
+
if (integerScroll !== 0) {
|
|
6180
|
+
this.scrollTop += integerScroll;
|
|
6181
|
+
this.scrollAccumulatorY -= integerScroll;
|
|
6182
|
+
}
|
|
4376
6183
|
} else if (dir === "left") {
|
|
4377
|
-
this.
|
|
6184
|
+
this.scrollAccumulatorX -= scrollAmount;
|
|
6185
|
+
const integerScroll = Math.trunc(this.scrollAccumulatorX);
|
|
6186
|
+
if (integerScroll !== 0) {
|
|
6187
|
+
this.scrollLeft += integerScroll;
|
|
6188
|
+
this.scrollAccumulatorX -= integerScroll;
|
|
6189
|
+
}
|
|
4378
6190
|
} else if (dir === "right") {
|
|
4379
|
-
this.
|
|
6191
|
+
this.scrollAccumulatorX += scrollAmount;
|
|
6192
|
+
const integerScroll = Math.trunc(this.scrollAccumulatorX);
|
|
6193
|
+
if (integerScroll !== 0) {
|
|
6194
|
+
this.scrollLeft += integerScroll;
|
|
6195
|
+
this.scrollAccumulatorX -= integerScroll;
|
|
6196
|
+
}
|
|
4380
6197
|
}
|
|
4381
6198
|
const maxScrollTop = Math.max(0, this.scrollHeight - this.viewport.height);
|
|
4382
6199
|
const maxScrollLeft = Math.max(0, this.scrollWidth - this.viewport.width);
|
|
@@ -4394,15 +6211,21 @@ class ScrollBoxRenderable extends BoxRenderable {
|
|
|
4394
6211
|
if (this.verticalScrollBar.handleKeyPress(key)) {
|
|
4395
6212
|
this._hasManualScroll = true;
|
|
4396
6213
|
this.scrollAccel.reset();
|
|
6214
|
+
this.resetScrollAccumulators();
|
|
4397
6215
|
return true;
|
|
4398
6216
|
}
|
|
4399
6217
|
if (this.horizontalScrollBar.handleKeyPress(key)) {
|
|
4400
6218
|
this._hasManualScroll = true;
|
|
4401
6219
|
this.scrollAccel.reset();
|
|
6220
|
+
this.resetScrollAccumulators();
|
|
4402
6221
|
return true;
|
|
4403
6222
|
}
|
|
4404
6223
|
return false;
|
|
4405
6224
|
}
|
|
6225
|
+
resetScrollAccumulators() {
|
|
6226
|
+
this.scrollAccumulatorX = 0;
|
|
6227
|
+
this.scrollAccumulatorY = 0;
|
|
6228
|
+
}
|
|
4406
6229
|
startAutoScroll(mouseX, mouseY) {
|
|
4407
6230
|
this.stopAutoScroll();
|
|
4408
6231
|
this.autoScrollMouseX = mouseX;
|
|
@@ -4699,8 +6522,8 @@ class SelectRenderable extends Renderable {
|
|
|
4699
6522
|
text: option.name,
|
|
4700
6523
|
x: contentX + 1 + indicatorWidth,
|
|
4701
6524
|
y: itemY,
|
|
4702
|
-
|
|
4703
|
-
|
|
6525
|
+
color: nameColor,
|
|
6526
|
+
backgroundColor: isSelected ? this._selectedBackgroundColor : bgColor,
|
|
4704
6527
|
font: this._font
|
|
4705
6528
|
});
|
|
4706
6529
|
descX = contentX + 1 + indicatorWidth;
|
|
@@ -4709,7 +6532,6 @@ class SelectRenderable extends Renderable {
|
|
|
4709
6532
|
}
|
|
4710
6533
|
if (this._showDescription && itemY + this.fontHeight < contentY + contentHeight) {
|
|
4711
6534
|
const descColor = isSelected ? this._selectedDescriptionColor : this._descriptionColor;
|
|
4712
|
-
const descBg = this._focused ? this._focusedBackgroundColor : this._backgroundColor;
|
|
4713
6535
|
this.frameBuffer.drawText(option.description, descX, itemY + this.fontHeight, descColor);
|
|
4714
6536
|
}
|
|
4715
6537
|
}
|
|
@@ -5341,6 +7163,7 @@ class EditBufferRenderable extends Renderable {
|
|
|
5341
7163
|
lastLocalSelection = null;
|
|
5342
7164
|
_tabIndicator;
|
|
5343
7165
|
_tabIndicatorColor;
|
|
7166
|
+
_selectionAnchorState = null;
|
|
5344
7167
|
_cursorChangeListener = undefined;
|
|
5345
7168
|
_contentChangeListener = undefined;
|
|
5346
7169
|
editBuffer;
|
|
@@ -5397,6 +7220,9 @@ class EditBufferRenderable extends Renderable {
|
|
|
5397
7220
|
this.setupMeasureFunc();
|
|
5398
7221
|
this.setupEventListeners(options);
|
|
5399
7222
|
}
|
|
7223
|
+
get lineInfo() {
|
|
7224
|
+
return this.editorView.getLogicalLineInfo();
|
|
7225
|
+
}
|
|
5400
7226
|
setupEventListeners(options) {
|
|
5401
7227
|
this._cursorChangeListener = options.onCursorChange;
|
|
5402
7228
|
this._contentChangeListener = options.onContentChange;
|
|
@@ -5412,11 +7238,18 @@ class EditBufferRenderable extends Renderable {
|
|
|
5412
7238
|
this.editBuffer.on("content-changed", () => {
|
|
5413
7239
|
this.yogaNode.markDirty();
|
|
5414
7240
|
this.requestRender();
|
|
7241
|
+
this.emit("line-info-change");
|
|
5415
7242
|
if (this._contentChangeListener) {
|
|
5416
7243
|
this._contentChangeListener({});
|
|
5417
7244
|
}
|
|
5418
7245
|
});
|
|
5419
7246
|
}
|
|
7247
|
+
get lineCount() {
|
|
7248
|
+
return this.editBuffer.getLineCount();
|
|
7249
|
+
}
|
|
7250
|
+
get scrollY() {
|
|
7251
|
+
return this.editorView.getViewport().offsetY;
|
|
7252
|
+
}
|
|
5420
7253
|
get plainText() {
|
|
5421
7254
|
return this.editBuffer.getText();
|
|
5422
7255
|
}
|
|
@@ -5609,19 +7442,25 @@ class EditBufferRenderable extends Renderable {
|
|
|
5609
7442
|
}
|
|
5610
7443
|
setupMeasureFunc() {
|
|
5611
7444
|
const measureFunc = (width, widthMode, height, heightMode) => {
|
|
5612
|
-
|
|
5613
|
-
|
|
5614
|
-
|
|
5615
|
-
this.editorView.setViewportSize(effectiveWidth, effectiveHeight);
|
|
7445
|
+
let effectiveWidth;
|
|
7446
|
+
if (widthMode === MeasureMode.Undefined || isNaN(width)) {
|
|
7447
|
+
effectiveWidth = 0;
|
|
5616
7448
|
} else {
|
|
5617
|
-
|
|
7449
|
+
effectiveWidth = width;
|
|
7450
|
+
}
|
|
7451
|
+
const effectiveHeight = isNaN(height) ? 1 : height;
|
|
7452
|
+
const measureResult = this.editorView.measureForDimensions(Math.floor(effectiveWidth), Math.floor(effectiveHeight));
|
|
7453
|
+
const measuredWidth = measureResult ? Math.max(1, measureResult.maxWidth) : 1;
|
|
7454
|
+
const measuredHeight = measureResult ? Math.max(1, measureResult.lineCount) : 1;
|
|
7455
|
+
if (widthMode === MeasureMode.AtMost && this._positionType !== "absolute") {
|
|
7456
|
+
return {
|
|
7457
|
+
width: Math.min(effectiveWidth, measuredWidth),
|
|
7458
|
+
height: Math.min(effectiveHeight, measuredHeight)
|
|
7459
|
+
};
|
|
5618
7460
|
}
|
|
5619
|
-
const lineInfo = this.editorView.getLogicalLineInfo();
|
|
5620
|
-
const measuredWidth = lineInfo.maxLineWidth;
|
|
5621
|
-
const measuredHeight = lineInfo.lineStarts.length;
|
|
5622
7461
|
return {
|
|
5623
|
-
width:
|
|
5624
|
-
height:
|
|
7462
|
+
width: measuredWidth,
|
|
7463
|
+
height: measuredHeight
|
|
5625
7464
|
};
|
|
5626
7465
|
};
|
|
5627
7466
|
this.yogaNode.setMeasureFunc(measureFunc);
|
|
@@ -5742,6 +7581,55 @@ class EditBufferRenderable extends Renderable {
|
|
|
5742
7581
|
getTextRangeByCoords(startRow, startCol, endRow, endCol) {
|
|
5743
7582
|
return this.editBuffer.getTextRangeByCoords(startRow, startCol, endRow, endCol);
|
|
5744
7583
|
}
|
|
7584
|
+
updateSelectionForMovement(shiftPressed, isBeforeMovement) {
|
|
7585
|
+
if (!this.selectable)
|
|
7586
|
+
return;
|
|
7587
|
+
if (!shiftPressed) {
|
|
7588
|
+
this._ctx.clearSelection();
|
|
7589
|
+
this._selectionAnchorState = null;
|
|
7590
|
+
return;
|
|
7591
|
+
}
|
|
7592
|
+
const visualCursor = this.editorView.getVisualCursor();
|
|
7593
|
+
const viewport = this.editorView.getViewport();
|
|
7594
|
+
const cursorX = this.x + visualCursor.visualCol;
|
|
7595
|
+
const cursorY = this.y + visualCursor.visualRow;
|
|
7596
|
+
if (isBeforeMovement) {
|
|
7597
|
+
if (!this._ctx.hasSelection) {
|
|
7598
|
+
this._ctx.startSelection(this, cursorX, cursorY);
|
|
7599
|
+
this._selectionAnchorState = {
|
|
7600
|
+
screenX: cursorX,
|
|
7601
|
+
screenY: cursorY,
|
|
7602
|
+
viewportX: viewport.offsetX,
|
|
7603
|
+
viewportY: viewport.offsetY
|
|
7604
|
+
};
|
|
7605
|
+
} else if (!this._selectionAnchorState) {
|
|
7606
|
+
const selection = this._ctx.getSelection();
|
|
7607
|
+
if (selection && selection.isActive) {
|
|
7608
|
+
this._selectionAnchorState = {
|
|
7609
|
+
screenX: selection.anchor.x,
|
|
7610
|
+
screenY: selection.anchor.y,
|
|
7611
|
+
viewportX: viewport.offsetX,
|
|
7612
|
+
viewportY: viewport.offsetY
|
|
7613
|
+
};
|
|
7614
|
+
}
|
|
7615
|
+
}
|
|
7616
|
+
} else {
|
|
7617
|
+
if (this._selectionAnchorState) {
|
|
7618
|
+
const deltaY = viewport.offsetY - this._selectionAnchorState.viewportY;
|
|
7619
|
+
const deltaX = viewport.offsetX - this._selectionAnchorState.viewportX;
|
|
7620
|
+
if (deltaY !== 0 || deltaX !== 0) {
|
|
7621
|
+
const newAnchorX = this._selectionAnchorState.screenX - deltaX;
|
|
7622
|
+
const newAnchorY = this._selectionAnchorState.screenY - deltaY;
|
|
7623
|
+
this._ctx.startSelection(this, newAnchorX, newAnchorY);
|
|
7624
|
+
this._ctx.updateSelection(this, cursorX, cursorY);
|
|
7625
|
+
} else {
|
|
7626
|
+
this._ctx.updateSelection(this, cursorX, cursorY);
|
|
7627
|
+
}
|
|
7628
|
+
} else {
|
|
7629
|
+
this._ctx.updateSelection(this, cursorX, cursorY);
|
|
7630
|
+
}
|
|
7631
|
+
}
|
|
7632
|
+
}
|
|
5745
7633
|
}
|
|
5746
7634
|
|
|
5747
7635
|
// src/lib/keymapping.ts
|
|
@@ -5779,12 +7667,12 @@ var defaultTextareaKeybindings = [
|
|
|
5779
7667
|
{ name: "right", shift: true, action: "select-right" },
|
|
5780
7668
|
{ name: "up", shift: true, action: "select-up" },
|
|
5781
7669
|
{ name: "down", shift: true, action: "select-down" },
|
|
5782
|
-
{ name: "home", action: "
|
|
5783
|
-
{ name: "end", action: "
|
|
5784
|
-
{ name: "home", shift: true, action: "select-
|
|
5785
|
-
{ name: "end", shift: true, action: "select-
|
|
5786
|
-
{ name: "a", ctrl: true, action: "
|
|
5787
|
-
{ name: "e", ctrl: true, action: "
|
|
7670
|
+
{ name: "home", action: "buffer-home" },
|
|
7671
|
+
{ name: "end", action: "buffer-end" },
|
|
7672
|
+
{ name: "home", shift: true, action: "select-buffer-home" },
|
|
7673
|
+
{ name: "end", shift: true, action: "select-buffer-end" },
|
|
7674
|
+
{ name: "a", ctrl: true, action: "line-home" },
|
|
7675
|
+
{ name: "e", ctrl: true, action: "line-end" },
|
|
5788
7676
|
{ name: "f", ctrl: true, action: "move-right" },
|
|
5789
7677
|
{ name: "b", ctrl: true, action: "move-left" },
|
|
5790
7678
|
{ name: "d", ctrl: true, action: "delete-word-forward" },
|
|
@@ -5882,6 +7770,8 @@ class TextareaRenderable extends EditBufferRenderable {
|
|
|
5882
7770
|
["line-end", () => this.gotoLineEnd()],
|
|
5883
7771
|
["select-line-home", () => this.gotoLineHome({ select: true })],
|
|
5884
7772
|
["select-line-end", () => this.gotoLineEnd({ select: true })],
|
|
7773
|
+
["select-buffer-home", () => this.gotoBufferHome({ select: true })],
|
|
7774
|
+
["select-buffer-end", () => this.gotoBufferEnd({ select: true })],
|
|
5885
7775
|
["buffer-home", () => this.gotoBufferHome()],
|
|
5886
7776
|
["buffer-end", () => this.gotoBufferEnd()],
|
|
5887
7777
|
["delete-line", () => this.deleteLine()],
|
|
@@ -5998,33 +7888,33 @@ class TextareaRenderable extends EditBufferRenderable {
|
|
|
5998
7888
|
}
|
|
5999
7889
|
moveCursorLeft(options) {
|
|
6000
7890
|
const select = options?.select ?? false;
|
|
6001
|
-
this.
|
|
7891
|
+
this.updateSelectionForMovement(select, true);
|
|
6002
7892
|
this.editBuffer.moveCursorLeft();
|
|
6003
|
-
this.
|
|
7893
|
+
this.updateSelectionForMovement(select, false);
|
|
6004
7894
|
this.requestRender();
|
|
6005
7895
|
return true;
|
|
6006
7896
|
}
|
|
6007
7897
|
moveCursorRight(options) {
|
|
6008
7898
|
const select = options?.select ?? false;
|
|
6009
|
-
this.
|
|
7899
|
+
this.updateSelectionForMovement(select, true);
|
|
6010
7900
|
this.editBuffer.moveCursorRight();
|
|
6011
|
-
this.
|
|
7901
|
+
this.updateSelectionForMovement(select, false);
|
|
6012
7902
|
this.requestRender();
|
|
6013
7903
|
return true;
|
|
6014
7904
|
}
|
|
6015
7905
|
moveCursorUp(options) {
|
|
6016
7906
|
const select = options?.select ?? false;
|
|
6017
|
-
this.
|
|
7907
|
+
this.updateSelectionForMovement(select, true);
|
|
6018
7908
|
this.editorView.moveUpVisual();
|
|
6019
|
-
this.
|
|
7909
|
+
this.updateSelectionForMovement(select, false);
|
|
6020
7910
|
this.requestRender();
|
|
6021
7911
|
return true;
|
|
6022
7912
|
}
|
|
6023
7913
|
moveCursorDown(options) {
|
|
6024
7914
|
const select = options?.select ?? false;
|
|
6025
|
-
this.
|
|
7915
|
+
this.updateSelectionForMovement(select, true);
|
|
6026
7916
|
this.editorView.moveDownVisual();
|
|
6027
|
-
this.
|
|
7917
|
+
this.updateSelectionForMovement(select, false);
|
|
6028
7918
|
this.requestRender();
|
|
6029
7919
|
return true;
|
|
6030
7920
|
}
|
|
@@ -6034,29 +7924,35 @@ class TextareaRenderable extends EditBufferRenderable {
|
|
|
6034
7924
|
}
|
|
6035
7925
|
gotoLineHome(options) {
|
|
6036
7926
|
const select = options?.select ?? false;
|
|
6037
|
-
this.
|
|
7927
|
+
this.updateSelectionForMovement(select, true);
|
|
6038
7928
|
const cursor = this.editorView.getCursor();
|
|
6039
7929
|
this.editBuffer.setCursor(cursor.row, 0);
|
|
6040
|
-
this.
|
|
7930
|
+
this.updateSelectionForMovement(select, false);
|
|
6041
7931
|
this.requestRender();
|
|
6042
7932
|
return true;
|
|
6043
7933
|
}
|
|
6044
7934
|
gotoLineEnd(options) {
|
|
6045
7935
|
const select = options?.select ?? false;
|
|
6046
|
-
this.
|
|
7936
|
+
this.updateSelectionForMovement(select, true);
|
|
6047
7937
|
const eol = this.editBuffer.getEOL();
|
|
6048
7938
|
this.editBuffer.setCursor(eol.row, eol.col);
|
|
6049
|
-
this.
|
|
7939
|
+
this.updateSelectionForMovement(select, false);
|
|
6050
7940
|
this.requestRender();
|
|
6051
7941
|
return true;
|
|
6052
7942
|
}
|
|
6053
|
-
gotoBufferHome() {
|
|
7943
|
+
gotoBufferHome(options) {
|
|
7944
|
+
const select = options?.select ?? false;
|
|
7945
|
+
this.updateSelectionForMovement(select, true);
|
|
6054
7946
|
this.editBuffer.setCursor(0, 0);
|
|
7947
|
+
this.updateSelectionForMovement(select, false);
|
|
6055
7948
|
this.requestRender();
|
|
6056
7949
|
return true;
|
|
6057
7950
|
}
|
|
6058
|
-
gotoBufferEnd() {
|
|
7951
|
+
gotoBufferEnd(options) {
|
|
7952
|
+
const select = options?.select ?? false;
|
|
7953
|
+
this.updateSelectionForMovement(select, true);
|
|
6059
7954
|
this.editBuffer.gotoLine(999999);
|
|
7955
|
+
this.updateSelectionForMovement(select, false);
|
|
6060
7956
|
this.requestRender();
|
|
6061
7957
|
return true;
|
|
6062
7958
|
}
|
|
@@ -6091,19 +7987,19 @@ class TextareaRenderable extends EditBufferRenderable {
|
|
|
6091
7987
|
}
|
|
6092
7988
|
moveWordForward(options) {
|
|
6093
7989
|
const select = options?.select ?? false;
|
|
6094
|
-
this.
|
|
7990
|
+
this.updateSelectionForMovement(select, true);
|
|
6095
7991
|
const nextWord = this.editBuffer.getNextWordBoundary();
|
|
6096
7992
|
this.editBuffer.setCursorByOffset(nextWord.offset);
|
|
6097
|
-
this.
|
|
7993
|
+
this.updateSelectionForMovement(select, false);
|
|
6098
7994
|
this.requestRender();
|
|
6099
7995
|
return true;
|
|
6100
7996
|
}
|
|
6101
7997
|
moveWordBackward(options) {
|
|
6102
7998
|
const select = options?.select ?? false;
|
|
6103
|
-
this.
|
|
7999
|
+
this.updateSelectionForMovement(select, true);
|
|
6104
8000
|
const prevWord = this.editBuffer.getPrevWordBoundary();
|
|
6105
8001
|
this.editBuffer.setCursorByOffset(prevWord.offset);
|
|
6106
|
-
this.
|
|
8002
|
+
this.updateSelectionForMovement(select, false);
|
|
6107
8003
|
this.requestRender();
|
|
6108
8004
|
return true;
|
|
6109
8005
|
}
|
|
@@ -6135,25 +8031,6 @@ class TextareaRenderable extends EditBufferRenderable {
|
|
|
6135
8031
|
this.requestRender();
|
|
6136
8032
|
return true;
|
|
6137
8033
|
}
|
|
6138
|
-
handleShiftSelection(shiftPressed, isBeforeMovement) {
|
|
6139
|
-
if (!this.selectable)
|
|
6140
|
-
return;
|
|
6141
|
-
if (!shiftPressed) {
|
|
6142
|
-
this._ctx.clearSelection();
|
|
6143
|
-
return;
|
|
6144
|
-
}
|
|
6145
|
-
const visualCursor = this.editorView.getVisualCursor();
|
|
6146
|
-
const viewport = this.editorView.getViewport();
|
|
6147
|
-
const cursorX = this.x + visualCursor.visualCol;
|
|
6148
|
-
const cursorY = this.y + (visualCursor.visualRow - viewport.offsetY);
|
|
6149
|
-
if (isBeforeMovement) {
|
|
6150
|
-
if (!this._ctx.hasSelection) {
|
|
6151
|
-
this._ctx.startSelection(this, cursorX, cursorY);
|
|
6152
|
-
}
|
|
6153
|
-
} else {
|
|
6154
|
-
this._ctx.updateSelection(this, cursorX, cursorY);
|
|
6155
|
-
}
|
|
6156
|
-
}
|
|
6157
8034
|
focus() {
|
|
6158
8035
|
super.focus();
|
|
6159
8036
|
this.updateColors();
|
|
@@ -6383,6 +8260,7 @@ export {
|
|
|
6383
8260
|
MacOSScrollAccel,
|
|
6384
8261
|
LogLevel,
|
|
6385
8262
|
LinearScrollAccel,
|
|
8263
|
+
LineNumberRenderable,
|
|
6386
8264
|
LayoutEvents,
|
|
6387
8265
|
KeyHandler,
|
|
6388
8266
|
KeyEvent,
|
|
@@ -6397,6 +8275,7 @@ export {
|
|
|
6397
8275
|
EditorView,
|
|
6398
8276
|
EditBuffer,
|
|
6399
8277
|
DistortionEffect,
|
|
8278
|
+
DiffRenderable,
|
|
6400
8279
|
DebugOverlayCorner,
|
|
6401
8280
|
DataPathsManager,
|
|
6402
8281
|
ConsolePosition,
|
|
@@ -6417,5 +8296,5 @@ export {
|
|
|
6417
8296
|
ASCIIFont
|
|
6418
8297
|
};
|
|
6419
8298
|
|
|
6420
|
-
//# debugId=
|
|
8299
|
+
//# debugId=84CD912F2F121D3E64756E2164756E21
|
|
6421
8300
|
//# sourceMappingURL=index.js.map
|