@pierre/diffs 1.3.5 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/CodeView.d.ts +113 -68
- package/dist/components/CodeView.d.ts.map +1 -1
- package/dist/components/CodeView.js +153 -58
- package/dist/components/CodeView.js.map +1 -1
- package/dist/components/File.d.ts +75 -15
- package/dist/components/File.d.ts.map +1 -1
- package/dist/components/File.js +223 -62
- package/dist/components/File.js.map +1 -1
- package/dist/components/FileDiff.d.ts +97 -21
- package/dist/components/FileDiff.d.ts.map +1 -1
- package/dist/components/FileDiff.js +400 -100
- package/dist/components/FileDiff.js.map +1 -1
- package/dist/components/UnresolvedFile.d.ts +2 -2
- package/dist/components/UnresolvedFile.d.ts.map +1 -1
- package/dist/components/UnresolvedFile.js +2 -2
- package/dist/components/UnresolvedFile.js.map +1 -1
- package/dist/components/VirtualizedFile.d.ts +16 -7
- package/dist/components/VirtualizedFile.d.ts.map +1 -1
- package/dist/components/VirtualizedFile.js +140 -51
- package/dist/components/VirtualizedFile.js.map +1 -1
- package/dist/components/VirtualizedFileDiff.d.ts +14 -8
- package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
- package/dist/components/VirtualizedFileDiff.js +183 -93
- package/dist/components/VirtualizedFileDiff.js.map +1 -1
- package/dist/components/VirtulizerDevelopment.d.ts +1 -1
- package/dist/components/VirtulizerDevelopment.d.ts.map +1 -1
- package/dist/edit/index.d.ts +7 -4
- package/dist/edit/index.js +5 -1
- package/dist/editor/EditStateManager.d.ts +56 -0
- package/dist/editor/EditStateManager.d.ts.map +1 -0
- package/dist/editor/EditStateManager.js +135 -0
- package/dist/editor/EditStateManager.js.map +1 -0
- package/dist/editor/cloneRetainedDiffSessionSnapshot.d.ts +7 -0
- package/dist/editor/cloneRetainedDiffSessionSnapshot.d.ts.map +1 -0
- package/dist/editor/cloneRetainedDiffSessionSnapshot.js +16 -0
- package/dist/editor/cloneRetainedDiffSessionSnapshot.js.map +1 -0
- package/dist/editor/editPrediction.d.ts +76 -0
- package/dist/editor/editPrediction.d.ts.map +1 -0
- package/dist/editor/editPrediction.js +365 -0
- package/dist/editor/editPrediction.js.map +1 -0
- package/dist/editor/editStack.d.ts +19 -40
- package/dist/editor/editStack.d.ts.map +1 -1
- package/dist/editor/editStack.js +67 -4
- package/dist/editor/editStack.js.map +1 -1
- package/dist/editor/editor.d.ts +118 -29
- package/dist/editor/editor.d.ts.map +1 -1
- package/dist/editor/editor.js +1196 -403
- package/dist/editor/editor.js.map +1 -1
- package/dist/editor/editor2.js +1 -1
- package/dist/editor/languages.d.ts +3 -3
- package/dist/editor/languages.d.ts.map +1 -1
- package/dist/editor/languages.js.map +1 -1
- package/dist/editor/lineAnnotations.d.ts +3 -3
- package/dist/editor/lineAnnotations.d.ts.map +1 -1
- package/dist/editor/lineAnnotations.js +16 -7
- package/dist/editor/lineAnnotations.js.map +1 -1
- package/dist/editor/marker.d.ts +2 -2
- package/dist/editor/marker.d.ts.map +1 -1
- package/dist/editor/marker.js.map +1 -1
- package/dist/editor/matchBrackets.d.ts +2 -2
- package/dist/editor/matchBrackets.d.ts.map +1 -1
- package/dist/editor/matchBrackets.js.map +1 -1
- package/dist/editor/pieceTable.d.ts +1 -1
- package/dist/editor/pieceTable.js.map +1 -1
- package/dist/editor/searchPanel.d.ts +2 -2
- package/dist/editor/searchPanel.d.ts.map +1 -1
- package/dist/editor/searchPanel.js +3 -2
- package/dist/editor/searchPanel.js.map +1 -1
- package/dist/editor/selection.d.ts +33 -23
- package/dist/editor/selection.d.ts.map +1 -1
- package/dist/editor/selection.js +3 -3
- package/dist/editor/selection.js.map +1 -1
- package/dist/editor/selectionAction.d.ts +3 -3
- package/dist/editor/selectionAction.d.ts.map +1 -1
- package/dist/editor/selectionAction.js.map +1 -1
- package/dist/editor/textDocument.d.ts +11 -8
- package/dist/editor/textDocument.d.ts.map +1 -1
- package/dist/editor/textDocument.js +28 -5
- package/dist/editor/textDocument.js.map +1 -1
- package/dist/editor/textDocumentChangeTransaction.d.ts +15 -0
- package/dist/editor/textDocumentChangeTransaction.d.ts.map +1 -0
- package/dist/editor/textDocumentChangeTransaction.js +12 -0
- package/dist/editor/textDocumentChangeTransaction.js.map +1 -0
- package/dist/editor/textMeasure.d.ts +5 -0
- package/dist/editor/textMeasure.d.ts.map +1 -1
- package/dist/editor/textMeasure.js +10 -0
- package/dist/editor/textMeasure.js.map +1 -1
- package/dist/editor/tokenizer.d.ts +1 -1
- package/dist/editor/tokenizer.d.ts.map +1 -1
- package/dist/editor/tokenizer.js +6 -3
- package/dist/editor/tokenizer.js.map +1 -1
- package/dist/editor/types.d.ts +267 -0
- package/dist/editor/types.d.ts.map +1 -0
- package/dist/editor/types.js +0 -0
- package/dist/editor/utils.d.ts +2 -1
- package/dist/editor/utils.d.ts.map +1 -1
- package/dist/editor/utils.js +4 -1
- package/dist/editor/utils.js.map +1 -1
- package/dist/index.d.ts +8 -6
- package/dist/index.js +9 -8
- package/dist/managers/InteractionManager.d.ts.map +1 -1
- package/dist/managers/InteractionManager.js +7 -0
- package/dist/managers/InteractionManager.js.map +1 -1
- package/dist/react/CodeView.d.ts +36 -25
- package/dist/react/CodeView.d.ts.map +1 -1
- package/dist/react/CodeView.js +15 -14
- package/dist/react/CodeView.js.map +1 -1
- package/dist/react/EditContext.d.ts +8 -11
- package/dist/react/EditContext.d.ts.map +1 -1
- package/dist/react/EditContext.js +2 -9
- package/dist/react/EditContext.js.map +1 -1
- package/dist/react/File.d.ts +10 -6
- package/dist/react/File.d.ts.map +1 -1
- package/dist/react/File.js +8 -4
- package/dist/react/File.js.map +1 -1
- package/dist/react/FileDiff.d.ts +10 -5
- package/dist/react/FileDiff.d.ts.map +1 -1
- package/dist/react/FileDiff.js +8 -4
- package/dist/react/FileDiff.js.map +1 -1
- package/dist/react/MultiFileDiff.d.ts +8 -5
- package/dist/react/MultiFileDiff.d.ts.map +1 -1
- package/dist/react/MultiFileDiff.js +8 -12
- package/dist/react/MultiFileDiff.js.map +1 -1
- package/dist/react/PatchDiff.d.ts +7 -4
- package/dist/react/PatchDiff.d.ts.map +1 -1
- package/dist/react/PatchDiff.js +8 -4
- package/dist/react/PatchDiff.js.map +1 -1
- package/dist/react/UnresolvedFile.d.ts +3 -3
- package/dist/react/UnresolvedFile.d.ts.map +1 -1
- package/dist/react/UnresolvedFile.js.map +1 -1
- package/dist/react/index.d.ts +8 -5
- package/dist/react/types.d.ts +46 -9
- package/dist/react/types.d.ts.map +1 -1
- package/dist/react/utils/renderDiffChildren.d.ts +14 -12
- package/dist/react/utils/renderDiffChildren.d.ts.map +1 -1
- package/dist/react/utils/renderDiffChildren.js +2 -2
- package/dist/react/utils/renderDiffChildren.js.map +1 -1
- package/dist/react/utils/renderFileChildren.d.ts +14 -12
- package/dist/react/utils/renderFileChildren.d.ts.map +1 -1
- package/dist/react/utils/renderFileChildren.js +2 -2
- package/dist/react/utils/renderFileChildren.js.map +1 -1
- package/dist/react/utils/useFileDiffInstance.d.ts +22 -10
- package/dist/react/utils/useFileDiffInstance.d.ts.map +1 -1
- package/dist/react/utils/useFileDiffInstance.js +112 -22
- package/dist/react/utils/useFileDiffInstance.js.map +1 -1
- package/dist/react/utils/useFileInstance.d.ts +15 -9
- package/dist/react/utils/useFileInstance.d.ts.map +1 -1
- package/dist/react/utils/useFileInstance.js +84 -25
- package/dist/react/utils/useFileInstance.js.map +1 -1
- package/dist/renderers/DiffHunksRenderer.d.ts +30 -15
- package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
- package/dist/renderers/DiffHunksRenderer.js +172 -108
- package/dist/renderers/DiffHunksRenderer.js.map +1 -1
- package/dist/renderers/FileRenderer.d.ts +27 -11
- package/dist/renderers/FileRenderer.d.ts.map +1 -1
- package/dist/renderers/FileRenderer.js +138 -64
- package/dist/renderers/FileRenderer.js.map +1 -1
- package/dist/renderers/UnresolvedFileHunksRenderer.d.ts +2 -2
- package/dist/renderers/UnresolvedFileHunksRenderer.d.ts.map +1 -1
- package/dist/renderers/UnresolvedFileHunksRenderer.js +2 -2
- package/dist/renderers/UnresolvedFileHunksRenderer.js.map +1 -1
- package/dist/shiki-stream/tokenizer.d.ts.map +1 -1
- package/dist/shiki-stream/tokenizer.js +2 -1
- package/dist/shiki-stream/tokenizer.js.map +1 -1
- package/dist/ssr/index.d.ts +2 -2
- package/dist/ssr/preloadDiffs.d.ts +21 -21
- package/dist/ssr/preloadDiffs.d.ts.map +1 -1
- package/dist/ssr/preloadDiffs.js +1 -1
- package/dist/ssr/preloadDiffs.js.map +1 -1
- package/dist/ssr/preloadFile.d.ts +6 -6
- package/dist/ssr/preloadFile.d.ts.map +1 -1
- package/dist/ssr/preloadFile.js.map +1 -1
- package/dist/ssr/preloadPatchFile.d.ts +4 -4
- package/dist/ssr/preloadPatchFile.d.ts.map +1 -1
- package/dist/ssr/preloadPatchFile.js.map +1 -1
- package/dist/style.js +1 -1
- package/dist/types.d.ts +13 -263
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/appendItems.d.ts +5 -0
- package/dist/utils/appendItems.d.ts.map +1 -0
- package/dist/utils/appendItems.js +8 -0
- package/dist/utils/appendItems.js.map +1 -0
- package/dist/utils/areDiffTargetsEqual.js +1 -1
- package/dist/utils/areDiffTargetsEqual.js.map +1 -1
- package/dist/utils/areFileTargetsEqual.d.ts +7 -0
- package/dist/utils/areFileTargetsEqual.d.ts.map +1 -0
- package/dist/utils/areFileTargetsEqual.js +8 -0
- package/dist/utils/areFileTargetsEqual.js.map +1 -0
- package/dist/utils/areManagedSnapshotsEqual.d.ts +1 -1
- package/dist/utils/areManagedSnapshotsEqual.d.ts.map +1 -1
- package/dist/utils/areManagedSnapshotsEqual.js.map +1 -1
- package/dist/utils/areOptionsEqual.d.ts +3 -3
- package/dist/utils/areOptionsEqual.d.ts.map +1 -1
- package/dist/utils/areOptionsEqual.js.map +1 -1
- package/dist/utils/cloneFileDiffMetadata.d.ts +3 -2
- package/dist/utils/cloneFileDiffMetadata.d.ts.map +1 -1
- package/dist/utils/cloneFileDiffMetadata.js +8 -5
- package/dist/utils/cloneFileDiffMetadata.js.map +1 -1
- package/dist/utils/composeCacheKey.d.ts +6 -0
- package/dist/utils/composeCacheKey.d.ts.map +1 -0
- package/dist/utils/composeCacheKey.js +10 -0
- package/dist/utils/composeCacheKey.js.map +1 -0
- package/dist/utils/editSessionAnnotations.d.ts +69 -0
- package/dist/utils/editSessionAnnotations.d.ts.map +1 -0
- package/dist/utils/editSessionAnnotations.js +64 -0
- package/dist/utils/editSessionAnnotations.js.map +1 -0
- package/dist/utils/editSessionHunks.d.ts +5 -3
- package/dist/utils/editSessionHunks.d.ts.map +1 -1
- package/dist/utils/editSessionHunks.js +7 -5
- package/dist/utils/editSessionHunks.js.map +1 -1
- package/dist/utils/getDiffHunksRendererOptions.d.ts +1 -1
- package/dist/utils/getDiffHunksRendererOptions.d.ts.map +1 -1
- package/dist/utils/getDiffHunksRendererOptions.js.map +1 -1
- package/dist/utils/getFileRendererOptions.d.ts +1 -1
- package/dist/utils/getFileRendererOptions.d.ts.map +1 -1
- package/dist/utils/getFileRendererOptions.js.map +1 -1
- package/dist/utils/hydratePartialDiff.d.ts.map +1 -1
- package/dist/utils/hydratePartialDiff.js +2 -1
- package/dist/utils/hydratePartialDiff.js.map +1 -1
- package/dist/utils/lineAnnotationIdentity.d.ts +16 -0
- package/dist/utils/lineAnnotationIdentity.d.ts.map +1 -0
- package/dist/utils/lineAnnotationIdentity.js +17 -0
- package/dist/utils/lineAnnotationIdentity.js.map +1 -0
- package/dist/utils/parseDiffFromFile.d.ts +2 -2
- package/dist/utils/parseDiffFromFile.d.ts.map +1 -1
- package/dist/utils/parseDiffFromFile.js +6 -6
- package/dist/utils/parseDiffFromFile.js.map +1 -1
- package/dist/utils/parsePatchFiles.d.ts +6 -3
- package/dist/utils/parsePatchFiles.d.ts.map +1 -1
- package/dist/utils/parsePatchFiles.js +34 -9
- package/dist/utils/parsePatchFiles.js.map +1 -1
- package/dist/utils/renderDiffWithHighlighter.d.ts.map +1 -1
- package/dist/utils/renderDiffWithHighlighter.js +6 -5
- package/dist/utils/renderDiffWithHighlighter.js.map +1 -1
- package/dist/utils/renderFileWithHighlighter.d.ts.map +1 -1
- package/dist/utils/renderFileWithHighlighter.js +7 -4
- package/dist/utils/renderFileWithHighlighter.js.map +1 -1
- package/dist/utils/trimPatchContext.d.ts.map +1 -1
- package/dist/utils/trimPatchContext.js +3 -2
- package/dist/utils/trimPatchContext.js.map +1 -1
- package/dist/utils/updateDiffHunks.js +1 -1
- package/dist/utils/virtualDiffLayout.js +1 -1
- package/dist/worker/WorkerPoolManager.d.ts +4 -3
- package/dist/worker/WorkerPoolManager.d.ts.map +1 -1
- package/dist/worker/WorkerPoolManager.js +33 -4
- package/dist/worker/WorkerPoolManager.js.map +1 -1
- package/dist/worker/types.d.ts +5 -0
- package/dist/worker/types.d.ts.map +1 -1
- package/dist/worker/worker-portable.js +14 -6
- package/dist/worker/worker-portable.js.map +1 -1
- package/dist/worker/worker.js +14 -6
- package/dist/worker/worker.js.map +1 -1
- package/package.json +9 -1
- package/dist/editor/stateStorage.d.ts +0 -15
- package/dist/editor/stateStorage.d.ts.map +0 -1
- package/dist/editor/stateStorage.js +0 -65
- package/dist/editor/stateStorage.js.map +0 -1
package/dist/editor/editor.js
CHANGED
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
import { dequeueRender, queueRender } from "../managers/UniversalRenderingManager.js";
|
|
2
2
|
import { isGutterUtilityPath } from "../utils/isGutterUtilityPath.js";
|
|
3
|
+
import { computeLineOffsets } from "../utils/computeFileOffsets.js";
|
|
3
4
|
import { getFiletypeFromFileName } from "../utils/getFiletypeFromFileName.js";
|
|
4
5
|
import { isSafari } from "../utils/platform.js";
|
|
6
|
+
import { EditStack } from "./editStack.js";
|
|
7
|
+
import { getTextDocumentChangeTransaction } from "./textDocumentChangeTransaction.js";
|
|
8
|
+
import { TextDocument } from "./textDocument.js";
|
|
9
|
+
import { EditStateManager, cloneEditorViewState, toManagedEditState } from "./EditStateManager.js";
|
|
5
10
|
import { isMoveCursorShortcut, isPrimaryModifier } from "./platform.js";
|
|
6
11
|
import { resolveEditorCommandFromKeyboardEvent, resolveFindAgainShortcut } from "./command.js";
|
|
7
|
-
import {
|
|
12
|
+
import { cloneRetainedDiffSessionSnapshot } from "./cloneRetainedDiffSessionSnapshot.js";
|
|
8
13
|
import editor_default from "./editor2.js";
|
|
14
|
+
import { buildEditPredictionRequest, matchesEditPredictionPattern, recordEditPrediction } from "./editPrediction.js";
|
|
9
15
|
import { resolveBlockCommentEdits, resolveCommentConfig, resolveLineCommentEdits } from "./languages.js";
|
|
10
16
|
import { addEventListener, clampDomOffset, extend, getLineNumberAttr, h, lookupScrollContainer, round } from "./utils.js";
|
|
11
17
|
import { applyDocumentChangeToLineAnnotations, renderLineAnnotations } from "./lineAnnotations.js";
|
|
12
18
|
import { PopoverManager } from "./popover.js";
|
|
13
|
-
import { applyDeleteCharacterToSelections, applyDeleteHardLineForwardToSelections, applyDeleteSoftLineBackwardToSelections, applyDeleteWordBackwardToSelections, applyTextChangeToSelections, applyTextReplaceToSelections, applyTransposeToSelections, comparePosition, convertSelection, createSelectionFrom, createSelectionFromAnchorAndFocusOffsets, expandCollapsedSelectionToWord, extendSelection, extendSelections, findNextMatch, getAutoSurroundReplacementTexts, getCaretPosition, getDocumentBoundarySelection, getDocumentFullSelection, getSelectedLineBlocks, getSelectionAnchor, getSelectionClipboardTexts, getSelectionText, isCollapsedSelection, isLineEditable, mapCursorMove, mapSelectionShift, mergeOverlappingSelections, remapSelectionsAfterEdits, resolveIndentEdits, resolveSelectionCut, selectionIntersects, shiftSelectionLines } from "./selection.js";
|
|
19
|
+
import { applyDeleteCharacterToSelections, applyDeleteHardLineForwardToSelections, applyDeleteSoftLineBackwardToSelections, applyDeleteWordBackwardToSelections, applyTextChangeToSelections, applyTextReplaceToSelections, applyTransposeToSelections, comparePosition, convertSelection, createSelectionFrom, createSelectionFromAnchorAndFocusOffsets, expandCollapsedSelectionToWord, extendSelection, extendSelections, findNextMatch, getAutoSurroundReplacementTexts, getCaretPosition, getDocumentBoundarySelection, getDocumentFullSelection, getSelectedLineBlocks, getSelectionAnchor, getSelectionClipboardTexts, getSelectionText, isCollapsedSelection, isLineEditable, mapCursorMove, mapSelectionShift, mergeOverlappingSelections, remapOffsetThroughEdits, remapSelectionsAfterEdits, resolveIndentEdits, resolveSelectionCut, selectionIntersects, shiftSelectionLines, snapCharacterToGraphemeBoundary } from "./selection.js";
|
|
14
20
|
import { MarkerRenderer, markerSeverityDatasetKey } from "./marker.js";
|
|
15
21
|
import { findBracketMatchRanges } from "./matchBrackets.js";
|
|
16
22
|
import { createSpriteElement } from "./sprite.js";
|
|
17
23
|
import { SearchPanelWidget } from "./searchPanel.js";
|
|
18
24
|
import { SelectionActionWidget } from "./selectionAction.js";
|
|
19
|
-
import { cloneEditorState, createStateStorage } from "./stateStorage.js";
|
|
20
|
-
import { TextDocument } from "./textDocument.js";
|
|
21
25
|
import { Metrics, getExpandedAsciiTextColumns, getUnicodeMeasurementOffsets, snapTextOffsetToUnicodeBoundary } from "./textMeasure.js";
|
|
22
26
|
import { EditorTokenizer, renderLineTokens } from "./tokenizer.js";
|
|
23
27
|
//#region src/editor/editor.ts
|
|
@@ -33,29 +37,45 @@ function getShadowRootRange(shadowRoot) {
|
|
|
33
37
|
endOffset: range.endOffset
|
|
34
38
|
};
|
|
35
39
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
40
|
+
/** Describe replacing the complete document from its previous text. */
|
|
41
|
+
function createFullDocumentChange(previousContents, contents) {
|
|
42
|
+
const lineOffsets = computeLineOffsets(previousContents);
|
|
43
|
+
const lastLineOffset = lineOffsets[lineOffsets.length - 1] ?? 0;
|
|
44
|
+
return {
|
|
45
|
+
start: 0,
|
|
46
|
+
end: previousContents.length,
|
|
47
|
+
text: contents,
|
|
48
|
+
range: {
|
|
49
|
+
start: {
|
|
50
|
+
line: 0,
|
|
51
|
+
character: 0
|
|
52
|
+
},
|
|
53
|
+
end: {
|
|
54
|
+
line: lineOffsets.length - 1,
|
|
55
|
+
character: previousContents.length - lastLineOffset
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
39
59
|
}
|
|
40
|
-
function
|
|
41
|
-
return
|
|
60
|
+
function isVirtualizedEditorComponent(instance) {
|
|
61
|
+
return instance != null && "renderType" in instance && instance.renderType === "virtualized";
|
|
42
62
|
}
|
|
43
63
|
const MAX_EDIT_WIDEN_WINDOW_MULTIPLE = 2;
|
|
44
64
|
const MAX_WRAP_OFFSETS_CACHE_LINES = 1e4;
|
|
65
|
+
const EDIT_PREDICTION_DEBOUNCE_MS = 300;
|
|
66
|
+
const MAX_EDIT_PREDICTION_RESPONSE_EDITS = 256;
|
|
67
|
+
const MAX_EDIT_PREDICTION_RESPONSE_BYTES = 128 * 1024;
|
|
68
|
+
const editPredictionTextEncoder = new TextEncoder();
|
|
45
69
|
const SELECTION_ACTION_POPOVER_PLACEMENT_KEY = "selection-action";
|
|
46
70
|
const MULTI_SELECTION_CLIPBOARD_TYPE = "application/vnd.pierre.diffs-selections+json";
|
|
47
71
|
var Editor = class {
|
|
72
|
+
type;
|
|
48
73
|
#options;
|
|
74
|
+
#initialState;
|
|
75
|
+
#editSession;
|
|
49
76
|
#metrics = new Metrics();
|
|
50
77
|
#tokenizer;
|
|
51
78
|
#popoverManager;
|
|
52
|
-
#textDocumentCache = /* @__PURE__ */ new Map();
|
|
53
|
-
#stateStorage;
|
|
54
|
-
#stateStorageOption;
|
|
55
|
-
#pendingStateWrites = /* @__PURE__ */ new Map();
|
|
56
|
-
#pendingStateRestore;
|
|
57
|
-
#stateRestoreGeneration = 0;
|
|
58
|
-
#restoreStateOnNextSync = false;
|
|
59
79
|
#editorEventDisposes;
|
|
60
80
|
#globalEventDisposes;
|
|
61
81
|
#selectEventDisposes;
|
|
@@ -79,17 +99,25 @@ var Editor = class {
|
|
|
79
99
|
#fileContainer;
|
|
80
100
|
#gutterElement;
|
|
81
101
|
#contentElement;
|
|
102
|
+
#deletionsColumn;
|
|
82
103
|
#overlayElement;
|
|
83
104
|
#overlayElements;
|
|
105
|
+
#caretElements;
|
|
106
|
+
#caretHighlightElements;
|
|
84
107
|
#primaryCaretElement;
|
|
85
108
|
#resizeObserver;
|
|
86
109
|
#fileInstance;
|
|
87
|
-
#
|
|
110
|
+
#applyDocumentChange;
|
|
111
|
+
#publishChange;
|
|
112
|
+
#isRendering = false;
|
|
113
|
+
#restoreEditorStateOnSync = false;
|
|
88
114
|
#lineAnnotations;
|
|
89
|
-
#
|
|
115
|
+
#editStateKey;
|
|
116
|
+
#ownsVerticalViewport;
|
|
90
117
|
#renderRange;
|
|
91
118
|
#viewportWindowLines;
|
|
92
119
|
#markerRenderer;
|
|
120
|
+
#carets;
|
|
93
121
|
#searchPanel;
|
|
94
122
|
#selectionAction;
|
|
95
123
|
#canMountSelectionAction = true;
|
|
@@ -100,6 +128,7 @@ var Editor = class {
|
|
|
100
128
|
#isComposing = false;
|
|
101
129
|
#isGutterMouseDown = false;
|
|
102
130
|
#isContentMouseDown = false;
|
|
131
|
+
#altColumnDrag;
|
|
103
132
|
#shiftKeyPressed = false;
|
|
104
133
|
#selectionStart;
|
|
105
134
|
#deletedSelectionText = "";
|
|
@@ -114,53 +143,166 @@ var Editor = class {
|
|
|
114
143
|
#retainSearchPanelFocus = false;
|
|
115
144
|
#fontRemeasureScheduled = false;
|
|
116
145
|
#themeSelectionRefreshFrame;
|
|
146
|
+
#editPredictionTimer;
|
|
147
|
+
#editPredictionAbortController;
|
|
148
|
+
#editPredictionGeneration = 0;
|
|
149
|
+
#editPredictionRevealed = false;
|
|
150
|
+
#retryEditPredictionOnRender = false;
|
|
151
|
+
#editPrediction;
|
|
152
|
+
#editPredictionHistory = [];
|
|
153
|
+
#editPredictionSpacers = /* @__PURE__ */ new Map();
|
|
154
|
+
#ghostTextRows = /* @__PURE__ */ new Map();
|
|
117
155
|
#onDeferTokenize = (lines, themeType) => {
|
|
156
|
+
if (!this.#isRendering) return;
|
|
118
157
|
this.#fileInstance?.updateRenderCache(lines, themeType);
|
|
119
158
|
if (this.#renderRange !== void 0 && this.#renderRange.totalLines !== Infinity) {
|
|
159
|
+
const predictionLines = this.#editPrediction === void 0 ? void 0 : new Set(this.#editPrediction.response.edits.map((edit) => edit.range.start.line));
|
|
160
|
+
let refreshPrediction = false;
|
|
120
161
|
const { startingLine, totalLines } = this.#renderRange;
|
|
121
|
-
const endLine = Math.min(startingLine + totalLines, this.#
|
|
162
|
+
const endLine = Math.min(startingLine + totalLines, (this.#editSession ?? this.#initialState)?.document?.lineCount ?? 0);
|
|
122
163
|
for (const [line, tokens] of lines) if (line >= startingLine && line < endLine) {
|
|
123
164
|
const lineElement = this.#getLineElement(line);
|
|
124
|
-
if (lineElement !== void 0)
|
|
165
|
+
if (lineElement !== void 0) {
|
|
166
|
+
lineElement.replaceChildren(...renderLineTokens(tokens));
|
|
167
|
+
refreshPrediction ||= predictionLines?.has(line) === true;
|
|
168
|
+
}
|
|
125
169
|
}
|
|
170
|
+
if (refreshPrediction && this.#selections !== void 0) this.#updateSelections(this.#selections);
|
|
126
171
|
}
|
|
127
172
|
};
|
|
128
|
-
|
|
173
|
+
/**
|
|
174
|
+
* @param type The component surface this editor can attach to.
|
|
175
|
+
* @param options Configure editor behavior and lifecycle callbacks.
|
|
176
|
+
* @param editStateKey Retain this editable draft and its undo/redo history
|
|
177
|
+
* in memory so a later editor using the same type and key can resume them.
|
|
178
|
+
*/
|
|
179
|
+
constructor(type, options = {}, editStateKey) {
|
|
180
|
+
this.type = type;
|
|
129
181
|
this.#options = options;
|
|
182
|
+
this.#ownsVerticalViewport = options.ownsVerticalViewport === true;
|
|
183
|
+
this.#initialState = options.initialState;
|
|
184
|
+
this.#editStateKey = editStateKey;
|
|
185
|
+
}
|
|
186
|
+
get #getTypedEditor() {
|
|
187
|
+
return this.type === "file" ? this : this;
|
|
130
188
|
}
|
|
131
189
|
setOptions(options) {
|
|
132
|
-
const
|
|
133
|
-
const
|
|
190
|
+
const previousRenderCaret = this.#options.renderCaret;
|
|
191
|
+
const previousEditPrediction = this.#options.editPrediction;
|
|
192
|
+
this.#options = {
|
|
134
193
|
...this.#options,
|
|
135
194
|
...options
|
|
136
195
|
};
|
|
137
|
-
if (
|
|
138
|
-
|
|
139
|
-
|
|
196
|
+
if (previousRenderCaret !== this.#options.renderCaret) {
|
|
197
|
+
this.#caretElements?.forEach((element) => element.remove());
|
|
198
|
+
this.#caretElements = void 0;
|
|
199
|
+
this.#renderCarets();
|
|
140
200
|
}
|
|
141
|
-
this.#options
|
|
142
|
-
|
|
143
|
-
this.#
|
|
144
|
-
this.#
|
|
145
|
-
this.#restoreStateOnNextSync = false;
|
|
146
|
-
}
|
|
147
|
-
if ((this.#options.persistStateStorage ?? "inMemory") !== previousStorageOption) {
|
|
148
|
-
this.#stateRestoreGeneration++;
|
|
149
|
-
this.#stateStorage = void 0;
|
|
150
|
-
this.#stateStorageOption = void 0;
|
|
151
|
-
this.#pendingStateWrites.clear();
|
|
201
|
+
if (previousEditPrediction !== this.#options.editPrediction) {
|
|
202
|
+
this.#cancelEditPrediction(true);
|
|
203
|
+
this.#editPredictionHistory = [];
|
|
204
|
+
this.#scheduleEditPrediction();
|
|
152
205
|
}
|
|
153
206
|
}
|
|
207
|
+
__emitEditComplete(event) {
|
|
208
|
+
this.#options.onComplete?.(event);
|
|
209
|
+
}
|
|
210
|
+
/** @internal */
|
|
211
|
+
__getGhostTextRows() {
|
|
212
|
+
return this.#ghostTextRows;
|
|
213
|
+
}
|
|
214
|
+
setCarets(carets) {
|
|
215
|
+
const textDocument = this.#editSession?.document;
|
|
216
|
+
if (textDocument === void 0) return;
|
|
217
|
+
this.#caretElements?.forEach((element) => element.remove());
|
|
218
|
+
this.#caretElements = void 0;
|
|
219
|
+
this.#caretHighlightElements?.forEach((element) => element.remove());
|
|
220
|
+
this.#caretHighlightElements = void 0;
|
|
221
|
+
this.#carets = carets.length === 0 ? void 0 : carets.map((caret) => {
|
|
222
|
+
const anchor = textDocument.normalizePosition(caret.anchor);
|
|
223
|
+
const focus = textDocument.normalizePosition(caret.focus);
|
|
224
|
+
return {
|
|
225
|
+
caret: {
|
|
226
|
+
...caret,
|
|
227
|
+
anchor,
|
|
228
|
+
focus
|
|
229
|
+
},
|
|
230
|
+
anchorOffset: textDocument.offsetAt(anchor),
|
|
231
|
+
focusOffset: textDocument.offsetAt(focus)
|
|
232
|
+
};
|
|
233
|
+
});
|
|
234
|
+
this.#renderCarets();
|
|
235
|
+
}
|
|
154
236
|
edit(fileInstance) {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
this.#
|
|
237
|
+
const editor = this.#getTypedEditor;
|
|
238
|
+
const previousSession = this.#editSession;
|
|
239
|
+
if (this.#isRendering) throw new Error("Editor.edit: the editor is already rendering its component");
|
|
240
|
+
if (this.#fileInstance != null && this.#fileInstance !== fileInstance) throw new Error("Editor.edit: a recycled edit session cannot attach to a different component");
|
|
241
|
+
const initialState = this.#initialState;
|
|
242
|
+
const initialEditorState = initialState?.editor;
|
|
243
|
+
const editStateKey = this.#editStateKey;
|
|
244
|
+
const editSession = getEditSession({
|
|
245
|
+
type: this.type,
|
|
246
|
+
editStateKey,
|
|
247
|
+
owner: this,
|
|
248
|
+
initialState,
|
|
249
|
+
previousSession
|
|
250
|
+
});
|
|
251
|
+
const previousDiffSession = editSession.diffSession;
|
|
252
|
+
this.#initialState = void 0;
|
|
253
|
+
this.#editSession = editSession;
|
|
160
254
|
this.#fileInstance = fileInstance;
|
|
161
|
-
this.#
|
|
162
|
-
this.#
|
|
163
|
-
|
|
255
|
+
this.#isRendering = true;
|
|
256
|
+
this.#restoreEditorStateOnSync = editSession.editor != null;
|
|
257
|
+
try {
|
|
258
|
+
this.#initialize();
|
|
259
|
+
if (fileInstance.type === "file" && editor.type === "file") {
|
|
260
|
+
editor.#applyDocumentChange = fileInstance.applyDocumentChange.bind(fileInstance);
|
|
261
|
+
editor.#publishChange = (changes, file, lineAnnotations) => {
|
|
262
|
+
const event = {
|
|
263
|
+
changes,
|
|
264
|
+
file,
|
|
265
|
+
editor,
|
|
266
|
+
lineAnnotations
|
|
267
|
+
};
|
|
268
|
+
editor.#options.onChange?.(event);
|
|
269
|
+
fileInstance.emitEditChange(event);
|
|
270
|
+
};
|
|
271
|
+
if (this.#detach == null) this.#detach = fileInstance.__attachEditor(editor);
|
|
272
|
+
else fileInstance.__resumeEditor(editor);
|
|
273
|
+
} else if (fileInstance.type === "file-diff" && editor.type === "file-diff") {
|
|
274
|
+
editor.#applyDocumentChange = fileInstance.applyDocumentChange.bind(fileInstance);
|
|
275
|
+
editor.#publishChange = (changes, file, lineAnnotations) => {
|
|
276
|
+
const event = {
|
|
277
|
+
changes,
|
|
278
|
+
file,
|
|
279
|
+
editor,
|
|
280
|
+
lineAnnotations
|
|
281
|
+
};
|
|
282
|
+
editor.#options.onChange?.(event);
|
|
283
|
+
fileInstance.emitEditChange(event);
|
|
284
|
+
};
|
|
285
|
+
if (this.#detach == null) this.#detach = fileInstance.__attachEditor(editor);
|
|
286
|
+
else fileInstance.__resumeEditor(editor);
|
|
287
|
+
} else throw new Error("Editor.edit: Impossible edit state");
|
|
288
|
+
} catch (error) {
|
|
289
|
+
this.cleanUp("recycle");
|
|
290
|
+
if (editSession.type === "file-diff" && editSession.diffSession == null) editSession.diffSession = previousDiffSession;
|
|
291
|
+
if (this.#detach == null && editStateKey != null) if (editor.type === "file") EditStateManager.releaseFile(editStateKey, editor);
|
|
292
|
+
else EditStateManager.releaseFileDiff(editStateKey, editor);
|
|
293
|
+
this.#editSession = previousSession;
|
|
294
|
+
if (this.#detach == null) {
|
|
295
|
+
this.#fileInstance = void 0;
|
|
296
|
+
this.#applyDocumentChange = void 0;
|
|
297
|
+
this.#publishChange = void 0;
|
|
298
|
+
}
|
|
299
|
+
if (initialState != null && initialEditorState != null) initialState.editor = initialEditorState;
|
|
300
|
+
this.#initialState = initialState;
|
|
301
|
+
throw error;
|
|
302
|
+
}
|
|
303
|
+
return () => {
|
|
304
|
+
this.cleanUp("complete");
|
|
305
|
+
};
|
|
164
306
|
}
|
|
165
307
|
/**
|
|
166
308
|
* Apply edits to current attached file. Every edit joins the undo timeline:
|
|
@@ -173,8 +315,8 @@ var Editor = class {
|
|
|
173
315
|
* are remapped during replay and the text edit still joins the undo timeline.
|
|
174
316
|
*/
|
|
175
317
|
applyEdits(edits, updateHistory = true) {
|
|
176
|
-
const textDocument = this.#
|
|
177
|
-
if (textDocument == null) throw new Error("Editor is not attached");
|
|
318
|
+
const textDocument = this.#editSession?.document;
|
|
319
|
+
if (textDocument == null) throw new Error("Editor.applyEdits: Editor is not attached");
|
|
178
320
|
const wasFocused = this.#contentHasFocus;
|
|
179
321
|
const selectionsBefore = this.#selections;
|
|
180
322
|
const selectionOffsetsBefore = selectionsBefore?.map((selection) => [textDocument.offsetAt(selection.start), textDocument.offsetAt(selection.end)]);
|
|
@@ -190,11 +332,11 @@ var Editor = class {
|
|
|
190
332
|
}
|
|
191
333
|
/** Whether there is an edit to undo. */
|
|
192
334
|
get canUndo() {
|
|
193
|
-
return this.#
|
|
335
|
+
return (this.#editSession ?? this.#initialState)?.document?.canUndo ?? false;
|
|
194
336
|
}
|
|
195
337
|
/** Whether there is an undone edit to redo. */
|
|
196
338
|
get canRedo() {
|
|
197
|
-
return this.#
|
|
339
|
+
return (this.#editSession ?? this.#initialState)?.document?.canRedo ?? false;
|
|
198
340
|
}
|
|
199
341
|
/** Undo the last edit. Does nothing when there is nothing to undo. */
|
|
200
342
|
undo() {
|
|
@@ -205,8 +347,9 @@ var Editor = class {
|
|
|
205
347
|
this.#runCommand("redo");
|
|
206
348
|
}
|
|
207
349
|
getFile() {
|
|
208
|
-
const
|
|
209
|
-
const
|
|
350
|
+
const editSession = this.#editSession ?? this.#initialState;
|
|
351
|
+
const fileInfo = editSession?.fileInfo;
|
|
352
|
+
const textDocument = editSession?.document;
|
|
210
353
|
if (fileInfo === void 0 || textDocument === void 0) return;
|
|
211
354
|
const file = { ...fileInfo };
|
|
212
355
|
Object.defineProperty(file, "contents", {
|
|
@@ -216,32 +359,56 @@ var Editor = class {
|
|
|
216
359
|
return file;
|
|
217
360
|
}
|
|
218
361
|
getText() {
|
|
219
|
-
return this.#
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
|
|
362
|
+
return (this.#editSession ?? this.#initialState)?.document?.getText() ?? "";
|
|
363
|
+
}
|
|
364
|
+
/** Return an isolated copy of selections and restorable view state. */
|
|
365
|
+
getViewState() {
|
|
366
|
+
const fileInstance = this.#isRendering ? this.#fileInstance : void 0;
|
|
367
|
+
if (!this.#isRendering && this.#editSession?.editor != null) return cloneEditorViewState(this.#editSession.editor);
|
|
368
|
+
const selections = this.#selections?.map((selection) => ({
|
|
369
|
+
...selection,
|
|
370
|
+
start: { ...selection.start },
|
|
371
|
+
end: { ...selection.end }
|
|
372
|
+
}));
|
|
373
|
+
if (fileInstance == null) return { selections };
|
|
374
|
+
const viewport = this.#getOwnedVerticalViewport();
|
|
375
|
+
const scrollLeft = fileInstance.getCodeScrollLeft();
|
|
376
|
+
if (viewport == null) return {
|
|
377
|
+
selections,
|
|
378
|
+
view: { scrollLeft }
|
|
379
|
+
};
|
|
223
380
|
return {
|
|
224
|
-
selections
|
|
225
|
-
view:
|
|
226
|
-
scrollLeft
|
|
227
|
-
scrollTop:
|
|
228
|
-
}
|
|
381
|
+
selections,
|
|
382
|
+
view: {
|
|
383
|
+
scrollLeft,
|
|
384
|
+
scrollTop: viewport.scrollTop
|
|
385
|
+
}
|
|
229
386
|
};
|
|
230
387
|
}
|
|
231
|
-
|
|
232
|
-
|
|
388
|
+
/**
|
|
389
|
+
* Return the objects that make up the active edit session, or undefined when
|
|
390
|
+
* no complete session exists.
|
|
391
|
+
*/
|
|
392
|
+
getEditState() {
|
|
393
|
+
const editSession = this.#editSession;
|
|
394
|
+
if (editSession == null) return;
|
|
395
|
+
if (this.#fileInstance == null) throw new Error(`Editor.getEditState: active ${this.type} session has no component`);
|
|
396
|
+
return toManagedEditState(editSession);
|
|
397
|
+
}
|
|
398
|
+
setViewState({ selections, view }) {
|
|
399
|
+
if (!this.#isRendering || this.#fileInstance === void 0 || this.#editSession?.document === void 0) throw new Error("Editor.setViewState: Editor is not attached");
|
|
233
400
|
this.#canMountSelectionAction = false;
|
|
234
401
|
this.#updateSelections(selections ?? []);
|
|
235
402
|
if (view != null) {
|
|
236
403
|
this.#fileInstance.setCodeScrollLeft(view.scrollLeft);
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
}
|
|
240
|
-
this.#
|
|
404
|
+
const viewport = this.#getOwnedVerticalViewport();
|
|
405
|
+
if (view.scrollTop !== void 0 && viewport != null) viewport.scrollTop = view.scrollTop;
|
|
406
|
+
} else if (this.#ownsVerticalViewport) this.#scrollToPrimaryCaret();
|
|
407
|
+
this.#checkpointEditSessionState();
|
|
241
408
|
}
|
|
242
409
|
setSelections(selections) {
|
|
243
|
-
const textDocument = this.#
|
|
244
|
-
if (textDocument === void 0) throw new Error("Text document is not initialized");
|
|
410
|
+
const textDocument = this.#editSession?.document;
|
|
411
|
+
if (textDocument === void 0) throw new Error("Editor.setSelections: Text document is not initialized");
|
|
245
412
|
const resolvedSelections = selections.map((selection) => {
|
|
246
413
|
let start = textDocument.normalizePosition(selection.start);
|
|
247
414
|
let end = textDocument.normalizePosition(selection.end);
|
|
@@ -263,8 +430,8 @@ var Editor = class {
|
|
|
263
430
|
this.#scrollToPrimaryCaret();
|
|
264
431
|
}
|
|
265
432
|
setMarkers(markers) {
|
|
266
|
-
const textDocument = this.#
|
|
267
|
-
if (textDocument === void 0) throw new Error("Text document is not initialized");
|
|
433
|
+
const textDocument = this.#editSession?.document;
|
|
434
|
+
if (textDocument === void 0) throw new Error("Editor.setMarkers: Text document is not initialized");
|
|
268
435
|
if (markers.length === 0) {
|
|
269
436
|
this.#markerRenderer?.cleanup();
|
|
270
437
|
this.#markerRenderer = void 0;
|
|
@@ -283,13 +450,14 @@ var Editor = class {
|
|
|
283
450
|
this.#markerRenderer.setMarkers(markers, textDocument);
|
|
284
451
|
if (this.#contentElement !== void 0) this.#markerRenderer.listenHover(this.#contentElement);
|
|
285
452
|
this.#updateSelections(this.#selections ?? []);
|
|
453
|
+
this.#renderCarets();
|
|
286
454
|
}
|
|
287
455
|
focus(options) {
|
|
288
456
|
const preventScroll = options?.preventScroll ?? false;
|
|
289
457
|
const lineNumber = options?.lineNumber;
|
|
290
458
|
if (lineNumber === "first-visible" || typeof lineNumber === "number") {
|
|
291
|
-
const textDocument = this.#
|
|
292
|
-
if (textDocument == null || this.#fileInstance == null) return;
|
|
459
|
+
const textDocument = this.#editSession?.document;
|
|
460
|
+
if (textDocument == null || !this.#isRendering || this.#fileInstance == null) return;
|
|
293
461
|
const targetLineNumber = lineNumber === "first-visible" ? this.#getFirstVisibleLineNumber(options?.offset) : lineNumber;
|
|
294
462
|
if (targetLineNumber == null) return;
|
|
295
463
|
const position = textDocument.normalizePosition({
|
|
@@ -311,29 +479,30 @@ var Editor = class {
|
|
|
311
479
|
this.#shouldIgnoreSelectionChange = false;
|
|
312
480
|
this.#contentElement?.blur();
|
|
313
481
|
}
|
|
314
|
-
cleanUp(
|
|
482
|
+
cleanUp(reason = "discard") {
|
|
483
|
+
const fileInstance = this.#fileInstance;
|
|
484
|
+
const recycle = reason === "recycle";
|
|
485
|
+
this.#cancelEditPrediction(true, false);
|
|
486
|
+
if (!recycle) this.#editPredictionHistory = [];
|
|
487
|
+
const editSession = this.#editSession;
|
|
488
|
+
if (fileInstance != null && editSession != null) {
|
|
489
|
+
const discardDiffState = !this.#checkpointEditSessionState();
|
|
490
|
+
if (!recycle) this.#releaseEditSession(discardDiffState);
|
|
491
|
+
}
|
|
315
492
|
this.#invalidateOnAttach();
|
|
316
493
|
if (!recycle) this.#attachState.delivered = false;
|
|
317
|
-
|
|
318
|
-
const shouldRestoreState = this.#options.persistState === true;
|
|
319
|
-
this.#stateRestoreGeneration++;
|
|
320
|
-
this.#persistCurrentState();
|
|
321
|
-
if (hadFileInstance) this.#restoreStateOnNextSync = shouldRestoreState;
|
|
494
|
+
this.#isRendering = false;
|
|
322
495
|
dequeueRender(this.#handleCustomPasteEvent);
|
|
323
496
|
this.#tokenizer?.cleanUp();
|
|
324
497
|
this.#tokenizer = void 0;
|
|
325
|
-
if (!recycle) {
|
|
326
|
-
this.#textDocument = void 0;
|
|
327
|
-
this.#fileInfo = void 0;
|
|
328
|
-
}
|
|
329
498
|
this.#globalEventDisposes?.forEach((dispose) => dispose());
|
|
330
499
|
this.#globalEventDisposes = void 0;
|
|
331
500
|
this.#editorEventDisposes?.forEach((dispose) => dispose());
|
|
332
501
|
this.#editorEventDisposes = void 0;
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
502
|
+
if (!recycle) {
|
|
503
|
+
this.#detach?.();
|
|
504
|
+
this.#detach = void 0;
|
|
505
|
+
}
|
|
337
506
|
this.#gutterWidthCache = void 0;
|
|
338
507
|
this.#contentWidthCache = void 0;
|
|
339
508
|
this.#lineYCache.clear();
|
|
@@ -352,6 +521,7 @@ var Editor = class {
|
|
|
352
521
|
this.#popoverManager?.cleanUp();
|
|
353
522
|
this.#popoverManager = void 0;
|
|
354
523
|
this.#gutterElement = void 0;
|
|
524
|
+
this.#deletionsColumn = void 0;
|
|
355
525
|
this.#contentElement?.removeAttribute("contentEditable");
|
|
356
526
|
this.#contentElement = void 0;
|
|
357
527
|
this.#replacementFocusRequest = void 0;
|
|
@@ -365,25 +535,44 @@ var Editor = class {
|
|
|
365
535
|
cancelAnimationFrame(this.#themeSelectionRefreshFrame);
|
|
366
536
|
this.#themeSelectionRefreshFrame = void 0;
|
|
367
537
|
}
|
|
368
|
-
this.#resetState();
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
this.#
|
|
379
|
-
this.#
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
538
|
+
this.#resetState(recycle);
|
|
539
|
+
if (!recycle) try {
|
|
540
|
+
if (fileInstance != null && editSession != null) {
|
|
541
|
+
const editor = this.#getTypedEditor;
|
|
542
|
+
const mode = reason === "complete" ? "install" : "discard";
|
|
543
|
+
if (fileInstance.type === "file" && editor.type === "file") fileInstance.__completeEditSession(editor, mode);
|
|
544
|
+
else if (fileInstance.type === "file-diff" && editor.type === "file-diff") fileInstance.__completeEditSession(editor, mode);
|
|
545
|
+
else throw new Error("Editor.cleanUp: Impossible edit state");
|
|
546
|
+
}
|
|
547
|
+
} finally {
|
|
548
|
+
this.#editSession = void 0;
|
|
549
|
+
this.#fileInstance = void 0;
|
|
550
|
+
this.#applyDocumentChange = void 0;
|
|
551
|
+
this.#publishChange = void 0;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
#checkpointEditSessionState() {
|
|
555
|
+
const fileInstance = this.#fileInstance;
|
|
556
|
+
const editSession = this.#editSession;
|
|
557
|
+
if (fileInstance == null || editSession == null) return false;
|
|
558
|
+
const editorState = this.#isRendering ? this.getViewState() : editSession.editor ?? {};
|
|
559
|
+
const { view } = editorState;
|
|
560
|
+
const hasNonDefaultView = view != null && (view.scrollLeft !== 0 || (view.scrollTop ?? 0) !== 0);
|
|
561
|
+
const hasEditorState = editorState.selections != null || hasNonDefaultView;
|
|
562
|
+
editSession.editor = cloneEditorViewState(editorState);
|
|
563
|
+
if (editSession.type === "file") return false;
|
|
564
|
+
const capturedDiffSession = fileInstance.__captureDocumentSessionState();
|
|
565
|
+
editSession.diffSession = capturedDiffSession?.diffSession;
|
|
566
|
+
if (capturedDiffSession == null) return false;
|
|
567
|
+
const document = editSession.document;
|
|
568
|
+
return capturedDiffSession.hasChanges || hasEditorState || document?.canUndo === true || document?.canRedo === true;
|
|
569
|
+
}
|
|
570
|
+
#releaseEditSession(discardDiffState = false) {
|
|
571
|
+
const editStateKey = this.#editStateKey;
|
|
572
|
+
if (editStateKey == null) return;
|
|
573
|
+
const editor = this.#getTypedEditor;
|
|
574
|
+
if (editor.type === "file") EditStateManager.releaseFile(editStateKey, editor);
|
|
575
|
+
else EditStateManager.releaseFileDiff(editStateKey, editor, discardDiffState);
|
|
387
576
|
}
|
|
388
577
|
/** @internal */
|
|
389
578
|
__postponeBgTokenizeToNextFrame() {
|
|
@@ -402,9 +591,40 @@ var Editor = class {
|
|
|
402
591
|
if (contentElement != null && (this.#contentHasFocus || shadowActiveElement === contentElement || shadowActiveElement != null && contentElement.contains(shadowActiveElement))) this.#replacementFocusRequest = {};
|
|
403
592
|
}
|
|
404
593
|
/** @internal */
|
|
405
|
-
|
|
594
|
+
__getDocumentContents(fallbackFile) {
|
|
595
|
+
const fileInfo = this.#editSession?.fileInfo;
|
|
596
|
+
const textDocument = this.#editSession?.document;
|
|
597
|
+
if (textDocument == null) return fileInfo == null || fallbackFile == null ? void 0 : {
|
|
598
|
+
...fileInfo,
|
|
599
|
+
contents: fallbackFile.contents
|
|
600
|
+
};
|
|
601
|
+
const resolvedFileInfo = fileInfo ?? fallbackFile;
|
|
602
|
+
if (resolvedFileInfo == null) return;
|
|
603
|
+
return {
|
|
604
|
+
name: resolvedFileInfo.name,
|
|
605
|
+
lang: resolvedFileInfo.lang,
|
|
606
|
+
contents: textDocument.getText()
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
/** @internal */
|
|
610
|
+
__getDocumentSessionState() {
|
|
611
|
+
const snapshot = this.#editSession?.diffSession;
|
|
612
|
+
return snapshot != null ? cloneRetainedDiffSessionSnapshot(snapshot) : void 0;
|
|
613
|
+
}
|
|
614
|
+
/** @internal */
|
|
615
|
+
__syncRenderView = (props) => {
|
|
616
|
+
const { highlighter, fileContainer, renderRange, resetHistory = false } = props;
|
|
617
|
+
const renderView = props;
|
|
618
|
+
let fileOrDiff;
|
|
619
|
+
if ("file" in renderView && this.type === "file") fileOrDiff = renderView.file;
|
|
620
|
+
else if ("fileDiff" in renderView && this.type === "file-diff") fileOrDiff = renderView.fileDiff;
|
|
621
|
+
else throw new Error("Editor.__syncRenderView: Impossible render state");
|
|
622
|
+
const lineAnnotations = renderView.lineAnnotations;
|
|
623
|
+
const editStateKey = this.#editStateKey;
|
|
624
|
+
const externalDocument = renderView.externalDocument === true;
|
|
406
625
|
const fileInstance = this.#fileInstance;
|
|
407
|
-
|
|
626
|
+
const editSession = this.#editSession;
|
|
627
|
+
if (!this.#isRendering || fileInstance == null || editSession == null) return;
|
|
408
628
|
const shadowRoot = fileContainer.shadowRoot;
|
|
409
629
|
if (shadowRoot == null) {
|
|
410
630
|
console.error("[editor] Could not find the shadow root.");
|
|
@@ -413,16 +633,26 @@ var Editor = class {
|
|
|
413
633
|
let codeElement;
|
|
414
634
|
let gutterEl;
|
|
415
635
|
let contentEl;
|
|
416
|
-
|
|
417
|
-
|
|
636
|
+
let deletionsGutterEl;
|
|
637
|
+
let deletionsContentEl;
|
|
638
|
+
for (const el of shadowRoot.querySelectorAll("[data-code]")) {
|
|
639
|
+
const isDeletions = el.dataset.deletions != null;
|
|
640
|
+
if (!isDeletions) codeElement = el;
|
|
418
641
|
for (const child of el.children) {
|
|
419
|
-
|
|
420
|
-
const { gutter, content } =
|
|
421
|
-
if (gutter
|
|
422
|
-
else
|
|
642
|
+
if (!(child instanceof HTMLElement)) continue;
|
|
643
|
+
const { gutter, content } = child.dataset;
|
|
644
|
+
if (gutter != null) if (isDeletions) deletionsGutterEl = child;
|
|
645
|
+
else gutterEl = child;
|
|
646
|
+
else if (content != null) if (isDeletions) deletionsContentEl = child;
|
|
647
|
+
else contentEl = child;
|
|
423
648
|
}
|
|
424
|
-
break;
|
|
425
649
|
}
|
|
650
|
+
if (deletionsContentEl == null) this.#deletionsColumn = void 0;
|
|
651
|
+
else if (deletionsGutterEl == null) throw new Error("Editor.__syncRenderView: the deletions column has no gutter");
|
|
652
|
+
else this.#deletionsColumn = {
|
|
653
|
+
content: deletionsContentEl,
|
|
654
|
+
gutter: deletionsGutterEl
|
|
655
|
+
};
|
|
426
656
|
if (codeElement === void 0 || contentEl === void 0) {
|
|
427
657
|
this.#replacementFocusRequest = void 0;
|
|
428
658
|
return;
|
|
@@ -435,45 +665,44 @@ var Editor = class {
|
|
|
435
665
|
if (this.#themeStyleElement !== void 0) shadowRoot.appendChild(this.#themeStyleElement);
|
|
436
666
|
if (this.#spriteElement !== void 0) shadowRoot.prepend(this.#spriteElement);
|
|
437
667
|
}
|
|
438
|
-
const
|
|
439
|
-
const
|
|
440
|
-
|
|
441
|
-
|
|
668
|
+
const languageId = fileOrDiff.lang ?? getFiletypeFromFileName(fileOrDiff.name);
|
|
669
|
+
const contents = "contents" in fileOrDiff ? fileOrDiff.contents : fileOrDiff.additionLines.join("");
|
|
670
|
+
const previousTextDocument = editSession.document;
|
|
671
|
+
const documentChanges = externalDocument && previousTextDocument !== void 0 && previousTextDocument.getText() !== contents ? [createFullDocumentChange(previousTextDocument.getText(), contents)] : void 0;
|
|
672
|
+
const resetForExternalDocument = externalDocument && resetHistory;
|
|
673
|
+
if (editSession.document == null || editSession.fileInfo == null || editStateKey == null && (editSession.fileInfo.name !== fileOrDiff.name || editSession.document.languageId !== languageId) || resetForExternalDocument) {
|
|
674
|
+
this.#cancelEditPrediction(true);
|
|
675
|
+
this.#editPredictionHistory = [];
|
|
442
676
|
this.#invalidateOnAttach();
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
const textDocument = reusableTextDocument ?? new TextDocument(fileOrDiff.name, contents, languageId, 0, editStack);
|
|
452
|
-
this.#fileInfo = {
|
|
677
|
+
const { name, lang } = fileOrDiff;
|
|
678
|
+
let textDocument = resetForExternalDocument || editStateKey == null && editSession.fileInfo != null ? void 0 : editSession.document;
|
|
679
|
+
if (previousTextDocument != null && textDocument == null) editSession.editor = void 0;
|
|
680
|
+
if (textDocument == null) {
|
|
681
|
+
const editStack = new EditStack({ maxEntries: this.#options.historyMaxEntries });
|
|
682
|
+
textDocument = new TextDocument(fileOrDiff.name, contents, languageId, 0, editStack);
|
|
683
|
+
}
|
|
684
|
+
editSession.fileInfo = {
|
|
453
685
|
name,
|
|
454
|
-
lang
|
|
455
|
-
cacheKey
|
|
686
|
+
lang
|
|
456
687
|
};
|
|
457
|
-
|
|
458
|
-
if (
|
|
459
|
-
this.#textDocumentCache.set(persistedCacheKey, textDocument);
|
|
460
|
-
persistedStateTarget = {
|
|
461
|
-
cacheKey: persistedCacheKey,
|
|
462
|
-
textDocument
|
|
463
|
-
};
|
|
464
|
-
}
|
|
688
|
+
editSession.document = textDocument;
|
|
689
|
+
if (resetForExternalDocument) editSession.diffSession = void 0;
|
|
465
690
|
this.#tokenizer?.cleanUp();
|
|
466
691
|
this.#tokenizer = void 0;
|
|
467
692
|
this.#resetState();
|
|
468
693
|
this.#wrapLineOffsetsCache.clear();
|
|
469
694
|
this.#selections = this.#initSelections;
|
|
470
|
-
if (this.#options.__debug === true) console.log(
|
|
695
|
+
if (this.#options.__debug === true) console.log("[diffs/editor] text document initialized from", fileOrDiff.name);
|
|
471
696
|
}
|
|
472
|
-
if (
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
697
|
+
if (externalDocument && !resetForExternalDocument) {
|
|
698
|
+
this.#applyExternalDocumentReplacement(editSession, contents, lineAnnotations);
|
|
699
|
+
const { name, lang } = fileOrDiff;
|
|
700
|
+
editSession.fileInfo = {
|
|
701
|
+
name,
|
|
702
|
+
lang
|
|
703
|
+
};
|
|
704
|
+
}
|
|
705
|
+
const textDocument = editSession.document;
|
|
477
706
|
if (this.#tokenizer == null && textDocument != null) this.#tokenizer = new EditorTokenizer({
|
|
478
707
|
highlighter,
|
|
479
708
|
textDocument,
|
|
@@ -517,178 +746,86 @@ var Editor = class {
|
|
|
517
746
|
this.#renderRange = renderRange;
|
|
518
747
|
this.#viewportWindowLines = renderRange?.totalLines;
|
|
519
748
|
this.#tokenizer?.prebuildStateStack(renderRange);
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
this.#
|
|
524
|
-
this.#
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
749
|
+
const retainedEditorState = editSession.editor;
|
|
750
|
+
const restoreEditorStateOnSync = this.#restoreEditorStateOnSync;
|
|
751
|
+
try {
|
|
752
|
+
this.#markerRenderer?.removePopover();
|
|
753
|
+
if (this.#selections !== void 0 || this.#matches !== void 0 || this.#markerRenderer !== void 0) this.#updateSelections(this.#selections ?? []);
|
|
754
|
+
this.#renderCarets();
|
|
755
|
+
if (this.#retryEditPredictionOnRender) this.#scheduleEditPrediction();
|
|
756
|
+
if (this.#initSelections !== void 0 && this.#primaryCaretElement !== void 0) {
|
|
757
|
+
this.#initSelections = void 0;
|
|
758
|
+
this.#scrollToPrimaryCaret(false, "center");
|
|
759
|
+
} else if (this.#scrollingToLine !== void 0) this.#scrollToLine(this.#scrollingToLine, this.#scrollingToLineChar, this.#scrollingToLineNoFocus);
|
|
760
|
+
else if (this.#replacementFocusRequest !== void 0) this.#restoreReplacementFocus();
|
|
761
|
+
else if (this.#selections !== void 0 && this.#selections.length > 0 && this.#contentHasFocus && !this.#retainSearchPanelFocus) this.focus({ preventScroll: true });
|
|
762
|
+
if (this.#retainSearchPanelFocus) this.#searchPanel?.focus();
|
|
763
|
+
if (restoreEditorStateOnSync) {
|
|
764
|
+
this.#restoreEditorStateOnSync = false;
|
|
765
|
+
if (retainedEditorState !== void 0) this.setViewState(retainedEditorState);
|
|
766
|
+
}
|
|
767
|
+
if (this.#options.__debug === true && renderRange !== void 0) {
|
|
768
|
+
const { startingLine, totalLines } = renderRange;
|
|
769
|
+
console.log("[diffs/editor] render file:", fileOrDiff.name, "RenderRange:", startingLine + "-" + (startingLine + totalLines), "of", editSession.document?.lineCount, "lines");
|
|
770
|
+
}
|
|
771
|
+
this.#checkpointEditSessionState();
|
|
772
|
+
} catch (error) {
|
|
773
|
+
this.#restoreEditorStateOnSync = restoreEditorStateOnSync;
|
|
774
|
+
editSession.editor = retainedEditorState;
|
|
775
|
+
throw error;
|
|
536
776
|
}
|
|
777
|
+
if (documentChanges != null) this.#emitChange(documentChanges, lineAnnotations);
|
|
537
778
|
this.#scheduleOnAttach(fileInstance);
|
|
538
779
|
};
|
|
539
|
-
#
|
|
540
|
-
const textDocument =
|
|
541
|
-
|
|
542
|
-
return textDocument?.languageId === languageId ? textDocument : void 0;
|
|
543
|
-
}
|
|
544
|
-
#getStateStorage() {
|
|
545
|
-
const option = this.#options.persistStateStorage ?? "inMemory";
|
|
546
|
-
if (this.#stateStorage === void 0 || this.#stateStorageOption !== option) {
|
|
547
|
-
this.#stateStorage = createStateStorage(option);
|
|
548
|
-
this.#stateStorageOption = option;
|
|
549
|
-
}
|
|
550
|
-
return this.#stateStorage;
|
|
551
|
-
}
|
|
552
|
-
#persistCurrentState() {
|
|
553
|
-
const fileInfo = this.#fileInfo;
|
|
554
|
-
const textDocument = this.#textDocument;
|
|
555
|
-
if (this.#options.persistState !== true || this.#fileInstance === void 0 || fileInfo === void 0 || textDocument === void 0) return;
|
|
556
|
-
const cacheKey = requirePersistedCacheKey(fileInfo);
|
|
557
|
-
this.#textDocumentCache.set(cacheKey, textDocument);
|
|
558
|
-
let storage;
|
|
559
|
-
try {
|
|
560
|
-
storage = this.#getStateStorage();
|
|
561
|
-
} catch {
|
|
562
|
-
return;
|
|
563
|
-
}
|
|
564
|
-
const state = cloneEditorState(this.getState());
|
|
565
|
-
const pendingRestore = this.#pendingStateRestore;
|
|
566
|
-
if (pendingRestore?.cacheKey === cacheKey && pendingRestore.textDocument === textDocument) {
|
|
567
|
-
this.#pendingStateRestore = void 0;
|
|
568
|
-
if (textDocument.version === pendingRestore.documentVersion && this.#selections === pendingRestore.selections && state.view?.scrollLeft === pendingRestore.view?.scrollLeft && state.view?.scrollTop === pendingRestore.view?.scrollTop) return;
|
|
569
|
-
this.#writeState(storage, cacheKey, state, pendingRestore.completion);
|
|
570
|
-
return;
|
|
571
|
-
}
|
|
572
|
-
this.#writeState(storage, cacheKey, state);
|
|
573
|
-
}
|
|
574
|
-
#writeState(storage, cacheKey, state, waitFor) {
|
|
575
|
-
const previousWrite = this.#pendingStateWrites.get(cacheKey);
|
|
576
|
-
if (waitFor !== void 0 || previousWrite !== void 0) {
|
|
577
|
-
let pending = waitFor ?? Promise.resolve();
|
|
578
|
-
if (previousWrite !== void 0) pending = pending.then(() => previousWrite);
|
|
579
|
-
this.#trackStateWrite(cacheKey, pending.then(() => storage.set(cacheKey, state)));
|
|
580
|
-
return;
|
|
581
|
-
}
|
|
582
|
-
let result;
|
|
583
|
-
try {
|
|
584
|
-
result = storage.set(cacheKey, state);
|
|
585
|
-
} catch {
|
|
586
|
-
return;
|
|
587
|
-
}
|
|
588
|
-
if (!isPromise(result)) return;
|
|
589
|
-
this.#trackStateWrite(cacheKey, result);
|
|
590
|
-
}
|
|
591
|
-
#trackStateWrite(cacheKey, result) {
|
|
592
|
-
const pending = result.catch(() => {});
|
|
593
|
-
this.#pendingStateWrites.set(cacheKey, pending);
|
|
594
|
-
pending.finally(() => {
|
|
595
|
-
if (this.#pendingStateWrites.get(cacheKey) === pending) this.#pendingStateWrites.delete(cacheKey);
|
|
596
|
-
});
|
|
597
|
-
}
|
|
598
|
-
#restorePersistedState(cacheKey, textDocument) {
|
|
599
|
-
const generation = ++this.#stateRestoreGeneration;
|
|
600
|
-
const documentVersion = textDocument.version;
|
|
780
|
+
#applyExternalDocumentReplacement(editSession, contents, lineAnnotations) {
|
|
781
|
+
const textDocument = editSession.document;
|
|
782
|
+
if (textDocument == null || textDocument.getText() === contents) return;
|
|
601
783
|
const selections = this.#selections;
|
|
602
|
-
const
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
const userScrolled = inputWatch?.userScrolled() === true;
|
|
608
|
-
if (state === void 0) {
|
|
609
|
-
this.#fileInstance?.setCodeScrollLeft(0);
|
|
610
|
-
if (!userScrolled) this.#setViewportScrollTop(0);
|
|
611
|
-
return;
|
|
612
|
-
}
|
|
613
|
-
const restored = cloneEditorState(state);
|
|
614
|
-
if (userScrolled && restored.view !== void 0) restored.view = { scrollLeft: restored.view.scrollLeft };
|
|
615
|
-
this.setState(restored);
|
|
616
|
-
};
|
|
617
|
-
const readState = () => {
|
|
618
|
-
let result;
|
|
619
|
-
try {
|
|
620
|
-
result = this.#getStateStorage().get(cacheKey);
|
|
621
|
-
} catch {
|
|
622
|
-
return;
|
|
623
|
-
}
|
|
624
|
-
if (isPromise(result)) return result.then(applyState).catch(() => {});
|
|
625
|
-
else try {
|
|
626
|
-
applyState(result);
|
|
627
|
-
} catch {}
|
|
784
|
+
const selectionOffsets = selections?.map((selection) => [textDocument.offsetAt(selection.start), textDocument.offsetAt(selection.end)]);
|
|
785
|
+
const replacement = {
|
|
786
|
+
start: 0,
|
|
787
|
+
end: textDocument.getText().length,
|
|
788
|
+
text: contents
|
|
628
789
|
};
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
cacheKey,
|
|
635
|
-
textDocument,
|
|
636
|
-
documentVersion,
|
|
637
|
-
selections,
|
|
638
|
-
view,
|
|
639
|
-
completion: result.catch(() => {})
|
|
640
|
-
};
|
|
641
|
-
this.#pendingStateRestore = pendingRestore;
|
|
642
|
-
pendingRestore.completion.finally(() => {
|
|
643
|
-
inputWatch?.dispose();
|
|
644
|
-
if (this.#pendingStateRestore === pendingRestore) this.#pendingStateRestore = void 0;
|
|
645
|
-
});
|
|
790
|
+
if (textDocument.applyResolvedEdits([replacement], true, selections, void 0, true) == null) return;
|
|
791
|
+
if (selections != null && selectionOffsets != null) {
|
|
792
|
+
const nextSelections = remapSelectionsAfterEdits(textDocument, selections, selectionOffsets, [replacement]);
|
|
793
|
+
textDocument.setLastUndoSelectionsAfter(nextSelections);
|
|
794
|
+
this.#selections = nextSelections;
|
|
646
795
|
}
|
|
796
|
+
if (this.#lineAnnotations != null || lineAnnotations != null) textDocument.setLastUndoLineAnnotations(this.#lineAnnotations ?? [], lineAnnotations ?? []);
|
|
797
|
+
this.#tokenizer?.cleanUp();
|
|
798
|
+
this.#tokenizer = void 0;
|
|
799
|
+
this.#resetCache();
|
|
800
|
+
this.#wrapLineOffsetsCache.clear();
|
|
801
|
+
this.#markerRenderer?.removePopover();
|
|
802
|
+
if (this.#searchPanel !== void 0 && this.#matches !== void 0) this.#searchPanel.updateMatches({ syncSelection: false });
|
|
647
803
|
}
|
|
648
|
-
#
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
"wheel",
|
|
654
|
-
"touchstart",
|
|
655
|
-
"mousedown"
|
|
656
|
-
];
|
|
657
|
-
const dispose = () => {
|
|
658
|
-
for (const type of eventTypes) viewport.removeEventListener(type, onInput, { capture: true });
|
|
659
|
-
};
|
|
660
|
-
const onInput = () => {
|
|
661
|
-
scrolled = true;
|
|
662
|
-
dispose();
|
|
663
|
-
};
|
|
664
|
-
for (const type of eventTypes) viewport.addEventListener(type, onInput, {
|
|
665
|
-
capture: true,
|
|
666
|
-
passive: true
|
|
667
|
-
});
|
|
668
|
-
return {
|
|
669
|
-
userScrolled: () => scrolled,
|
|
670
|
-
dispose
|
|
671
|
-
};
|
|
804
|
+
get #fileDiffInstance() {
|
|
805
|
+
return this.#fileInstance?.type === "file-diff" ? this.#fileInstance : void 0;
|
|
806
|
+
}
|
|
807
|
+
get #virtualizedInstance() {
|
|
808
|
+
return isVirtualizedEditorComponent(this.#fileInstance) ? this.#fileInstance : void 0;
|
|
672
809
|
}
|
|
673
810
|
#isLineRenderable(line) {
|
|
674
|
-
return this.#
|
|
811
|
+
return this.#fileDiffInstance?.isLineRenderable?.(line + 1) ?? true;
|
|
675
812
|
}
|
|
676
813
|
get #resolveRenderableLine() {
|
|
677
|
-
const fileInstance = this.#
|
|
678
|
-
if (fileInstance
|
|
814
|
+
const fileInstance = this.#fileDiffInstance;
|
|
815
|
+
if (fileInstance == null) return;
|
|
679
816
|
return (line, direction) => {
|
|
680
817
|
const nearest = fileInstance.getNearestRenderableLine(line + 1, direction);
|
|
681
818
|
return nearest == null ? void 0 : nearest - 1;
|
|
682
819
|
};
|
|
683
820
|
}
|
|
684
821
|
#revealLineIfCollapsed(line) {
|
|
685
|
-
if (!this.#isLineRenderable(line)) this.#
|
|
822
|
+
if (!this.#isLineRenderable(line)) this.#fileDiffInstance?.revealLine?.(line + 1);
|
|
686
823
|
}
|
|
687
824
|
get #diffSyle() {
|
|
688
|
-
return this.#
|
|
825
|
+
return this.#fileDiffInstance?.options.diffStyle ?? "split";
|
|
689
826
|
}
|
|
690
827
|
get #isDiff() {
|
|
691
|
-
return this
|
|
828
|
+
return this.type === "file-diff";
|
|
692
829
|
}
|
|
693
830
|
get #isWrap() {
|
|
694
831
|
return this.#fileInstance?.options.overflow === "wrap";
|
|
@@ -707,16 +844,20 @@ var Editor = class {
|
|
|
707
844
|
this.#lineElementsCache.clear();
|
|
708
845
|
this.#lastAccessedCharX = void 0;
|
|
709
846
|
}
|
|
710
|
-
#resetState() {
|
|
847
|
+
#resetState(preserveCarets = false) {
|
|
711
848
|
this.#setEditorActiveLineSafe(null);
|
|
712
849
|
this.#gutterWidthCache = void 0;
|
|
713
850
|
this.#contentWidthCache = void 0;
|
|
714
|
-
this.#
|
|
851
|
+
this.#resetSelectionGesture();
|
|
715
852
|
this.#suppressNativeSelectionSync = false;
|
|
716
853
|
this.#overlayElements?.forEach((el) => el.remove());
|
|
717
854
|
this.#overlayElements = void 0;
|
|
855
|
+
this.#caretElements?.forEach((element) => element.remove());
|
|
856
|
+
this.#caretElements = void 0;
|
|
857
|
+
this.#caretHighlightElements?.forEach((element) => element.remove());
|
|
858
|
+
this.#caretHighlightElements = void 0;
|
|
859
|
+
if (!preserveCarets) this.#carets = void 0;
|
|
718
860
|
this.#selections = void 0;
|
|
719
|
-
this.#reservedSelections = void 0;
|
|
720
861
|
this.#scrollingToLine = void 0;
|
|
721
862
|
this.#markerRenderer?.cleanup();
|
|
722
863
|
this.#markerRenderer = void 0;
|
|
@@ -736,13 +877,13 @@ var Editor = class {
|
|
|
736
877
|
}
|
|
737
878
|
#scheduleOnAttach(fileInstance) {
|
|
738
879
|
const attachState = this.#attachState;
|
|
739
|
-
const textDocument = this.#
|
|
880
|
+
const textDocument = this.#editSession?.document;
|
|
740
881
|
if (attachState.delivered || attachState.callback != null || textDocument == null) return;
|
|
741
882
|
const { generation } = attachState;
|
|
742
883
|
const callback = () => {
|
|
743
884
|
if (attachState.callback !== callback) return;
|
|
744
885
|
attachState.callback = void 0;
|
|
745
|
-
if (generation !== attachState.generation || this.#fileInstance !== fileInstance || this.#
|
|
886
|
+
if (generation !== attachState.generation || this.#fileInstance !== fileInstance || this.#editSession?.document !== textDocument) return;
|
|
746
887
|
const contentElement = this.#contentElement;
|
|
747
888
|
const shadowRoot = this.#fileContainer?.shadowRoot;
|
|
748
889
|
if (contentElement == null || shadowRoot == null || !shadowRoot.contains(contentElement)) return;
|
|
@@ -753,21 +894,16 @@ var Editor = class {
|
|
|
753
894
|
queueRender(callback);
|
|
754
895
|
}
|
|
755
896
|
#getScrollViewport() {
|
|
756
|
-
const viewport = this.#
|
|
757
|
-
if (viewport
|
|
897
|
+
const viewport = this.#virtualizedInstance?.getEditorViewport?.();
|
|
898
|
+
if (viewport != null) return viewport;
|
|
758
899
|
const fileContainer = this.#fileContainer;
|
|
759
900
|
if (this.#fileInstance == null || fileContainer == null) return;
|
|
760
901
|
return lookupScrollContainer(fileContainer);
|
|
761
902
|
}
|
|
762
|
-
#
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
}
|
|
767
|
-
#setViewportScrollTop(scrollTop) {
|
|
768
|
-
const viewport = this.#getScrollViewport();
|
|
769
|
-
if (viewport instanceof HTMLElement) viewport.scrollTop = scrollTop;
|
|
770
|
-
else if (viewport instanceof Document) viewport.defaultView?.scrollTo({ top: scrollTop });
|
|
903
|
+
#getOwnedVerticalViewport() {
|
|
904
|
+
if (!this.#ownsVerticalViewport) return;
|
|
905
|
+
const viewport = this.#virtualizedInstance?.getEditorViewport?.();
|
|
906
|
+
if (viewport instanceof HTMLElement) return viewport;
|
|
771
907
|
}
|
|
772
908
|
#initialize() {
|
|
773
909
|
this.#globalStyleElement = h("style", {
|
|
@@ -796,6 +932,13 @@ var Editor = class {
|
|
|
796
932
|
this.#contentHasFocus = false;
|
|
797
933
|
this.#shouldIgnoreSelectionChange = false;
|
|
798
934
|
};
|
|
935
|
+
const finishMouseSelection = (event) => {
|
|
936
|
+
if (event.pointerType !== "mouse") return;
|
|
937
|
+
const refocusEditor = this.#isGutterMouseDown;
|
|
938
|
+
this.#resetSelectionGesture();
|
|
939
|
+
if (refocusEditor) this.#focus();
|
|
940
|
+
if (this.#options.enabledSelectionAction === true && this.#selections !== void 0 && this.#selections.length > 0 && !isCollapsedSelection(this.#selections.at(-1))) this.#updateSelections(this.#selections);
|
|
941
|
+
};
|
|
799
942
|
this.#globalEventDisposes = [
|
|
800
943
|
addEventListener(document, "focusin", (event) => {
|
|
801
944
|
if (!replacementFocusTargetIsContent(event)) cancelReplacementFocus();
|
|
@@ -812,7 +955,9 @@ var Editor = class {
|
|
|
812
955
|
if (this.#selections !== void 0 && this.#selections.length > 1 && !this.#isContentMouseDown) return;
|
|
813
956
|
const selectionRaw = document.getSelection();
|
|
814
957
|
if (selectionRaw == null) return;
|
|
815
|
-
|
|
958
|
+
let composedRange;
|
|
959
|
+
if (typeof selectionRaw.getComposedRanges === "function") composedRange = selectionRaw.getComposedRanges({ shadowRoots: [shadowRoot] })?.[0];
|
|
960
|
+
else composedRange = getShadowRootRange(shadowRoot);
|
|
816
961
|
if (composedRange === void 0 || !this.#rangeBelongsToEditor(composedRange)) return;
|
|
817
962
|
let selection = convertSelection(composedRange, 0);
|
|
818
963
|
if (selection === void 0) return;
|
|
@@ -828,32 +973,38 @@ var Editor = class {
|
|
|
828
973
|
const previous = this.#selections[0];
|
|
829
974
|
if (comparePosition(previous.start, selection.start) === 0 && comparePosition(previous.end, selection.end) === 0) selection.direction = previous.direction;
|
|
830
975
|
}
|
|
976
|
+
if (this.#altColumnDrag !== void 0) {
|
|
977
|
+
this.#altColumnDrag.focusLine = getCaretPosition(selection).line;
|
|
978
|
+
if (this.#updateAltColumnSelections()) return;
|
|
979
|
+
}
|
|
831
980
|
if (this.#reservedSelections !== void 0) this.#updateSelections([...this.#reservedSelections.filter((reservedSelection) => !selectionIntersects(reservedSelection, selection)), selection]);
|
|
832
981
|
else this.#updateSelections([selection]);
|
|
833
982
|
}, { passive: true }),
|
|
834
|
-
addEventListener(document, "pointerup",
|
|
835
|
-
|
|
836
|
-
this.#selectEventDisposes?.forEach((dispose) => dispose());
|
|
837
|
-
this.#selectEventDisposes = void 0;
|
|
838
|
-
if (this.#isGutterMouseDown) {
|
|
839
|
-
this.#isGutterMouseDown = false;
|
|
840
|
-
this.#focus();
|
|
841
|
-
}
|
|
842
|
-
this.#shouldIgnoreSelectionChange = false;
|
|
843
|
-
this.#isContentMouseDown = false;
|
|
844
|
-
this.#shiftKeyPressed = false;
|
|
845
|
-
this.#selectionStart = void 0;
|
|
846
|
-
this.#reservedSelections = void 0;
|
|
847
|
-
if (this.#options.enabledSelectionAction === true && this.#selections !== void 0 && this.#selections.length > 0 && !isCollapsedSelection(this.#selections.at(-1))) this.#updateSelections(this.#selections);
|
|
848
|
-
}, { passive: true }),
|
|
983
|
+
addEventListener(document, "pointerup", finishMouseSelection, { passive: true }),
|
|
984
|
+
addEventListener(document, "pointercancel", finishMouseSelection, { passive: true }),
|
|
849
985
|
addEventListener(document, "keydown", (e) => {
|
|
850
986
|
if (e.key === "Shift") this.#selectionStart = this.#selections?.at(-1);
|
|
987
|
+
else if (e.key === "Alt" && !e.repeat && this.#contentHasFocus && this.#options.editPrediction?.mode === "subtle") {
|
|
988
|
+
this.#editPredictionRevealed = !this.#editPredictionRevealed;
|
|
989
|
+
this.#updateSelections(this.#selections ?? []);
|
|
990
|
+
}
|
|
851
991
|
}, { passive: true }),
|
|
852
992
|
addEventListener(document, "keyup", (e) => {
|
|
853
993
|
if (e.key === "Shift") this.#selectionStart = void 0;
|
|
854
994
|
}, { passive: true })
|
|
855
995
|
];
|
|
856
996
|
}
|
|
997
|
+
#resetSelectionGesture() {
|
|
998
|
+
this.#selectEventDisposes?.forEach((dispose) => dispose());
|
|
999
|
+
this.#selectEventDisposes = void 0;
|
|
1000
|
+
this.#shouldIgnoreSelectionChange = false;
|
|
1001
|
+
this.#isGutterMouseDown = false;
|
|
1002
|
+
this.#isContentMouseDown = false;
|
|
1003
|
+
this.#altColumnDrag = void 0;
|
|
1004
|
+
this.#shiftKeyPressed = false;
|
|
1005
|
+
this.#selectionStart = void 0;
|
|
1006
|
+
this.#reservedSelections = void 0;
|
|
1007
|
+
}
|
|
857
1008
|
#replaceSelectEventListeners(disposes) {
|
|
858
1009
|
this.#selectEventDisposes?.forEach((dispose) => dispose());
|
|
859
1010
|
this.#selectEventDisposes = disposes;
|
|
@@ -889,6 +1040,7 @@ var Editor = class {
|
|
|
889
1040
|
this.#canMountSelectionAction = true;
|
|
890
1041
|
this.#suppressNativeSelectionSync = false;
|
|
891
1042
|
if (e.pointerType !== "mouse") return;
|
|
1043
|
+
this.#altColumnDrag = void 0;
|
|
892
1044
|
if (this.#isDeletedLineTarget(e)) {
|
|
893
1045
|
this.#setDeletedTextSelectionActive(true);
|
|
894
1046
|
if (this.#selections !== void 0) this.#updateSelections([]);
|
|
@@ -896,17 +1048,39 @@ var Editor = class {
|
|
|
896
1048
|
}
|
|
897
1049
|
this.#setDeletedTextSelectionActive(false);
|
|
898
1050
|
this.#markerRenderer?.removePopover();
|
|
1051
|
+
const selectEventDisposes = [];
|
|
899
1052
|
if (isSafari() && this.#lineAnnotations !== void 0 && this.#lineAnnotations.length > 0) {
|
|
900
1053
|
const annotationDisposes = [...contentEl.querySelectorAll("[data-line-annotation]")].map((el) => [addEventListener(el, "mouseenter", () => {
|
|
901
1054
|
this.#shouldIgnoreSelectionChange = true;
|
|
902
1055
|
}), addEventListener(el, "mouseleave", () => {
|
|
903
1056
|
this.#shouldIgnoreSelectionChange = false;
|
|
904
1057
|
})]).flat();
|
|
905
|
-
|
|
1058
|
+
selectEventDisposes.push(...annotationDisposes);
|
|
906
1059
|
}
|
|
907
1060
|
this.#isContentMouseDown = true;
|
|
1061
|
+
const isAltColumnDrag = e.button === 0 && e.altKey && !e.ctrlKey && !e.metaKey && !e.shiftKey;
|
|
908
1062
|
this.#selectionStart = void 0;
|
|
909
|
-
if (
|
|
1063
|
+
if (isAltColumnDrag) {
|
|
1064
|
+
this.#altColumnDrag = {
|
|
1065
|
+
pointerId: e.pointerId,
|
|
1066
|
+
startClientX: e.clientX,
|
|
1067
|
+
clientX: e.clientX,
|
|
1068
|
+
startScrollLeft: contentEl.parentElement?.scrollLeft ?? 0
|
|
1069
|
+
};
|
|
1070
|
+
this.#reservedSelections = void 0;
|
|
1071
|
+
this.#selections = void 0;
|
|
1072
|
+
this.#updateSelections([]);
|
|
1073
|
+
selectEventDisposes.push(addEventListener(document, "pointermove", (moveEvent) => {
|
|
1074
|
+
const drag = this.#altColumnDrag;
|
|
1075
|
+
if (drag === void 0 || moveEvent.pointerType !== "mouse" || moveEvent.pointerId !== drag.pointerId) return;
|
|
1076
|
+
drag.clientX = moveEvent.clientX;
|
|
1077
|
+
this.#updateAltColumnSelections();
|
|
1078
|
+
}, {
|
|
1079
|
+
capture: true,
|
|
1080
|
+
passive: true
|
|
1081
|
+
}));
|
|
1082
|
+
} else if (e.button === 0 && isPrimaryModifier(e)) this.#reservedSelections = this.#selections?.map((selection) => ({ ...selection }));
|
|
1083
|
+
this.#replaceSelectEventListeners(selectEventDisposes);
|
|
910
1084
|
if (e.shiftKey) {
|
|
911
1085
|
const primarySelection = this.#selections?.at(-1);
|
|
912
1086
|
if (primarySelection !== void 0) {
|
|
@@ -924,6 +1098,17 @@ var Editor = class {
|
|
|
924
1098
|
if (!targetIsContentElement(e)) return;
|
|
925
1099
|
this.#canMountSelectionAction = true;
|
|
926
1100
|
this.#suppressNativeSelectionSync = false;
|
|
1101
|
+
if (e.isComposing || e.keyCode === 229) return;
|
|
1102
|
+
if (e.key === "Tab" && !e.shiftKey && !e.ctrlKey && !e.metaKey && !e.isComposing && !this.#isComposing && (!e.altKey || this.#options.editPrediction?.mode === "subtle") && this.#editPrediction?.rendered === true) {
|
|
1103
|
+
this.#acceptEditPrediction();
|
|
1104
|
+
e.preventDefault();
|
|
1105
|
+
return;
|
|
1106
|
+
}
|
|
1107
|
+
if (e.key === "Escape" && this.#editPrediction !== void 0) {
|
|
1108
|
+
this.#cancelEditPrediction(true);
|
|
1109
|
+
e.preventDefault();
|
|
1110
|
+
return;
|
|
1111
|
+
}
|
|
927
1112
|
const command = resolveEditorCommandFromKeyboardEvent(e, this.#options.keymap);
|
|
928
1113
|
if (command !== void 0) {
|
|
929
1114
|
e.preventDefault();
|
|
@@ -938,7 +1123,7 @@ var Editor = class {
|
|
|
938
1123
|
return;
|
|
939
1124
|
}
|
|
940
1125
|
const mvShortcut = isMoveCursorShortcut(e);
|
|
941
|
-
const textDocument = this.#
|
|
1126
|
+
const textDocument = this.#editSession?.document;
|
|
942
1127
|
if (this.#selections !== void 0 && this.#selections.length > 0 && mvShortcut !== void 0 && textDocument !== void 0) {
|
|
943
1128
|
const cursorMoveOptions = {
|
|
944
1129
|
getSoftLineOffsets: this.#isWrap ? (line) => this.#wrapLineTextOrWholeLine(line) : void 0,
|
|
@@ -989,7 +1174,7 @@ var Editor = class {
|
|
|
989
1174
|
if (!targetIsContentElement(e)) return;
|
|
990
1175
|
e.preventDefault();
|
|
991
1176
|
const clipboardData = e.clipboardData;
|
|
992
|
-
const textDocument = this.#
|
|
1177
|
+
const textDocument = this.#editSession?.document;
|
|
993
1178
|
if (clipboardData === null || textDocument === void 0) return;
|
|
994
1179
|
let text = clipboardData.getData("text");
|
|
995
1180
|
const selectionCount = this.#selections?.length ?? 0;
|
|
@@ -1004,7 +1189,10 @@ var Editor = class {
|
|
|
1004
1189
|
}),
|
|
1005
1190
|
addEventListener(contentEl, "beforeinput", (e) => {
|
|
1006
1191
|
if (!targetIsContentElement(e)) return;
|
|
1007
|
-
if (e.inputType === "insertCompositionText")
|
|
1192
|
+
if (e.inputType === "insertCompositionText") {
|
|
1193
|
+
this.#cancelEditPrediction(true);
|
|
1194
|
+
return;
|
|
1195
|
+
}
|
|
1008
1196
|
e.preventDefault();
|
|
1009
1197
|
this.#handleInput(e.inputType, e.data);
|
|
1010
1198
|
}),
|
|
@@ -1014,6 +1202,7 @@ var Editor = class {
|
|
|
1014
1202
|
}),
|
|
1015
1203
|
addEventListener(contentEl, "compositionstart", (e) => {
|
|
1016
1204
|
if (!targetIsContentElement(e)) return;
|
|
1205
|
+
this.#cancelEditPrediction(true);
|
|
1017
1206
|
this.#isComposing = true;
|
|
1018
1207
|
this.#shouldIgnoreSelectionChange = true;
|
|
1019
1208
|
}, { passive: true }),
|
|
@@ -1075,7 +1264,7 @@ var Editor = class {
|
|
|
1075
1264
|
return;
|
|
1076
1265
|
}
|
|
1077
1266
|
if (e.pointerType !== "mouse") return;
|
|
1078
|
-
const textDocument = this.#
|
|
1267
|
+
const textDocument = this.#editSession?.document;
|
|
1079
1268
|
const lineIndex = resolveEditableLine(gutterRow);
|
|
1080
1269
|
if (lineIndex === void 0 || textDocument === void 0) return;
|
|
1081
1270
|
this.#canMountSelectionAction = true;
|
|
@@ -1088,7 +1277,7 @@ var Editor = class {
|
|
|
1088
1277
|
this.#focus();
|
|
1089
1278
|
this.#replaceSelectEventListeners([addEventListener(document, "mousemove", (e) => {
|
|
1090
1279
|
if (!this.#isGutterMouseDown) return;
|
|
1091
|
-
const textDocument = this.#
|
|
1280
|
+
const textDocument = this.#editSession?.document;
|
|
1092
1281
|
const lineIndex = resolveEditableLine(resolveGutterTarget(e.composedPath()[0], true));
|
|
1093
1282
|
if (lineIndex === void 0 || textDocument === void 0) return;
|
|
1094
1283
|
const anchorLine = this.#selectionStart?.start.line ?? lineIndex;
|
|
@@ -1118,14 +1307,14 @@ var Editor = class {
|
|
|
1118
1307
|
if (Array.isArray(selectionTexts) && selectionTexts.length === selectionCount) text = selectionTexts;
|
|
1119
1308
|
} catch {}
|
|
1120
1309
|
}
|
|
1121
|
-
const textDocument = this.#
|
|
1122
|
-
if (textDocument
|
|
1310
|
+
const textDocument = this.#editSession?.document;
|
|
1311
|
+
if (textDocument != null) this.#replaceSelectionText(Array.isArray(text) ? text.map((t) => textDocument.normalizeEol(t)) : textDocument.normalizeEol(text), void 0, true, "document");
|
|
1123
1312
|
}
|
|
1124
1313
|
};
|
|
1125
1314
|
#computeContentOffset(contentEl) {
|
|
1126
1315
|
if (this.#isDiff && this.#diffSyle === "split" && this.#isWrap) {
|
|
1127
1316
|
this.#contentOffset = {
|
|
1128
|
-
top: contentEl.offsetTop,
|
|
1317
|
+
top: contentEl.offsetTop - this.#metrics.paddingTop,
|
|
1129
1318
|
left: contentEl.offsetLeft - this.#getGutterWidth()
|
|
1130
1319
|
};
|
|
1131
1320
|
if (this.#options.__debug === true) console.log("[diffs/editor] content offset:", this.#contentOffset);
|
|
@@ -1135,8 +1324,8 @@ var Editor = class {
|
|
|
1135
1324
|
if (this.#isDiff && this.#diffSyle === "split" && this.#isWrap) return this.#contentOffset;
|
|
1136
1325
|
}
|
|
1137
1326
|
#runCommand(command) {
|
|
1138
|
-
const textDocument = this.#
|
|
1139
|
-
if (textDocument
|
|
1327
|
+
const textDocument = this.#editSession?.document;
|
|
1328
|
+
if (textDocument == null) return;
|
|
1140
1329
|
switch (command) {
|
|
1141
1330
|
case "openSearchPanel":
|
|
1142
1331
|
this.#openSearchPanel("find");
|
|
@@ -1336,8 +1525,8 @@ var Editor = class {
|
|
|
1336
1525
|
}
|
|
1337
1526
|
}
|
|
1338
1527
|
#applyHistoryChange(command) {
|
|
1339
|
-
const textDocument = this.#
|
|
1340
|
-
if (textDocument
|
|
1528
|
+
const textDocument = this.#editSession?.document;
|
|
1529
|
+
if (textDocument == null) return;
|
|
1341
1530
|
if (command === "undo" && !textDocument.canUndo || command === "redo" && !textDocument.canRedo) return;
|
|
1342
1531
|
const selections = this.#selections;
|
|
1343
1532
|
const selectionOffsets = selections?.map((selection) => [textDocument.offsetAt(selection.start), textDocument.offsetAt(selection.end)]);
|
|
@@ -1345,11 +1534,12 @@ var Editor = class {
|
|
|
1345
1534
|
if (result === void 0) return;
|
|
1346
1535
|
const [change, recordedSelections, lineAnnotations, selectionEdits] = result;
|
|
1347
1536
|
const nextSelections = recordedSelections ?? (selections !== void 0 && selectionOffsets !== void 0 && selectionEdits !== void 0 ? remapSelectionsAfterEdits(textDocument, selections, selectionOffsets, selectionEdits) : void 0);
|
|
1348
|
-
this.#
|
|
1537
|
+
const replayedLineAnnotations = lineAnnotations ?? (this.#lineAnnotations != null ? applyDocumentChangeToLineAnnotations(change, this.#lineAnnotations) : void 0);
|
|
1538
|
+
this.#applyChange(change, nextSelections, replayedLineAnnotations);
|
|
1349
1539
|
}
|
|
1350
1540
|
/** Applies one undoable command batch and records its resulting selections. */
|
|
1351
1541
|
#applyCommandEdits(edits, resolveNextSelections) {
|
|
1352
|
-
const textDocument = this.#
|
|
1542
|
+
const textDocument = this.#editSession?.document;
|
|
1353
1543
|
const selections = this.#selections;
|
|
1354
1544
|
if (textDocument === void 0 || selections === void 0) return;
|
|
1355
1545
|
const remapSelections = resolveNextSelections === void 0;
|
|
@@ -1374,7 +1564,7 @@ var Editor = class {
|
|
|
1374
1564
|
}
|
|
1375
1565
|
/** Copies selected line blocks and keeps the selection in the requested copy. */
|
|
1376
1566
|
#copySelectedLines(direction) {
|
|
1377
|
-
const textDocument = this.#
|
|
1567
|
+
const textDocument = this.#editSession?.document;
|
|
1378
1568
|
const selections = this.#selections;
|
|
1379
1569
|
if (textDocument === void 0 || selections === void 0) return;
|
|
1380
1570
|
const blocks = getSelectedLineBlocks(selections);
|
|
@@ -1467,7 +1657,7 @@ var Editor = class {
|
|
|
1467
1657
|
}
|
|
1468
1658
|
/** Inserts an indented blank line after each selection's final line. */
|
|
1469
1659
|
#insertBlankLine() {
|
|
1470
|
-
const textDocument = this.#
|
|
1660
|
+
const textDocument = this.#editSession?.document;
|
|
1471
1661
|
const selections = this.#selections;
|
|
1472
1662
|
if (textDocument === void 0 || selections === void 0) return;
|
|
1473
1663
|
const selectionLines = selections.map((selection) => getCaretPosition(selection).line);
|
|
@@ -1508,7 +1698,7 @@ var Editor = class {
|
|
|
1508
1698
|
this.#applyCommandEdits(edits, () => nextSelections);
|
|
1509
1699
|
}
|
|
1510
1700
|
#moveSelectedLines(direction) {
|
|
1511
|
-
const textDocument = this.#
|
|
1701
|
+
const textDocument = this.#editSession?.document;
|
|
1512
1702
|
const selections = this.#selections;
|
|
1513
1703
|
if (textDocument === void 0 || selections === void 0) return;
|
|
1514
1704
|
const blocks = getSelectedLineBlocks(selections);
|
|
@@ -1585,6 +1775,7 @@ var Editor = class {
|
|
|
1585
1775
|
}
|
|
1586
1776
|
this.#markerRenderer?.removePopover();
|
|
1587
1777
|
this.#computeContentOffset(this.#contentElement);
|
|
1778
|
+
this.#renderCarets();
|
|
1588
1779
|
};
|
|
1589
1780
|
#remeasureMetricsOnFontLoad() {
|
|
1590
1781
|
if (this.#fontRemeasureScheduled) return;
|
|
@@ -1598,19 +1789,21 @@ var Editor = class {
|
|
|
1598
1789
|
this.#resetCache();
|
|
1599
1790
|
this.#wrapLineOffsetsCache.clear();
|
|
1600
1791
|
if (this.#selections !== void 0 || this.#matches !== void 0 || this.#markerRenderer !== void 0) this.#updateSelections(this.#selections ?? []);
|
|
1792
|
+
this.#renderCarets();
|
|
1601
1793
|
this.#markerRenderer?.removePopover();
|
|
1602
1794
|
});
|
|
1603
1795
|
}
|
|
1604
1796
|
#rerender(change, newLineAnnotations, renderRange = this.#renderRange, shouldUpdateBuffer) {
|
|
1605
1797
|
const tokenizer = this.#tokenizer;
|
|
1606
1798
|
const fileInstance = this.#fileInstance;
|
|
1607
|
-
const
|
|
1799
|
+
const applyDocumentChange = this.#applyDocumentChange;
|
|
1800
|
+
const textDocument = this.#editSession?.document;
|
|
1608
1801
|
const gutterEl = this.#gutterElement;
|
|
1609
1802
|
const contentEl = this.#contentElement;
|
|
1610
|
-
if (tokenizer
|
|
1803
|
+
if (tokenizer == null || fileInstance == null || applyDocumentChange == null || textDocument == null || contentEl == null) return;
|
|
1611
1804
|
tokenizer.stopBackgroundTokenize();
|
|
1612
1805
|
const t = performance.now();
|
|
1613
|
-
const dirtyLines = tokenizer.tokenize(change, renderRange, !this.#isDiff);
|
|
1806
|
+
const dirtyLines = tokenizer.tokenize(change, renderRange, !this.#isDiff && this.#virtualizedInstance != null);
|
|
1614
1807
|
const t2 = performance.now();
|
|
1615
1808
|
if (dirtyLines.size > 0) {
|
|
1616
1809
|
const children = contentEl.children;
|
|
@@ -1689,19 +1882,20 @@ var Editor = class {
|
|
|
1689
1882
|
shouldRefreshDiffsView: this.#isDiff && !didLineCountChange,
|
|
1690
1883
|
lineCountChangeInFlight: didLineCountChange
|
|
1691
1884
|
});
|
|
1692
|
-
if (didLineCountChange)
|
|
1885
|
+
if (didLineCountChange) applyDocumentChange(textDocument, newLineAnnotations, shouldUpdateBuffer);
|
|
1693
1886
|
if (didLineCountChange || this.#isDiff && this.#diffSyle === "unified") this.#resetCache();
|
|
1694
|
-
if (newLineAnnotations
|
|
1887
|
+
if (newLineAnnotations != null) {
|
|
1695
1888
|
this.#lineAnnotations = newLineAnnotations;
|
|
1696
|
-
renderLineAnnotations(newLineAnnotations, contentEl, gutterEl);
|
|
1889
|
+
if (!this.#isDiff || !didLineCountChange) renderLineAnnotations(newLineAnnotations, contentEl, gutterEl, fileInstance.getAnnotationSlotName);
|
|
1697
1890
|
}
|
|
1891
|
+
this.#renderCarets();
|
|
1698
1892
|
if (this.#options.__debug === true) console.log(`[diffs/editor] re-render in: ${round(performance.now() - t2)}ms,`, `tokenize in: ${round(t2 - t)}ms (${dirtyLines.size} dirty lines)`);
|
|
1699
1893
|
}
|
|
1700
1894
|
#handleInput(inputType, data) {
|
|
1701
1895
|
switch (inputType) {
|
|
1702
1896
|
case "insertText": {
|
|
1703
1897
|
const text = data ?? "";
|
|
1704
|
-
const textDocument = this.#
|
|
1898
|
+
const textDocument = this.#editSession?.document;
|
|
1705
1899
|
const selections = this.#selections;
|
|
1706
1900
|
const autoSurroundTexts = textDocument !== void 0 && selections !== void 0 ? getAutoSurroundReplacementTexts(textDocument, selections, text, this.#options.autoSurround) : void 0;
|
|
1707
1901
|
this.#replaceSelectionText(autoSurroundTexts ?? text);
|
|
@@ -1710,7 +1904,7 @@ var Editor = class {
|
|
|
1710
1904
|
case "insertCompositionText": break;
|
|
1711
1905
|
case "insertLineBreak":
|
|
1712
1906
|
case "insertParagraph":
|
|
1713
|
-
this.#replaceSelectionText(this.#
|
|
1907
|
+
this.#replaceSelectionText(this.#editSession?.document?.eol ?? "\n");
|
|
1714
1908
|
break;
|
|
1715
1909
|
case "deleteContentBackward":
|
|
1716
1910
|
this.#deleteSelectionText();
|
|
@@ -1802,7 +1996,7 @@ var Editor = class {
|
|
|
1802
1996
|
#getFirstVisibleLineNumber(offset = 0) {
|
|
1803
1997
|
const contentElement = this.#contentElement;
|
|
1804
1998
|
const fileContainer = this.#fileContainer;
|
|
1805
|
-
if (this.#
|
|
1999
|
+
if (this.#editSession?.document == null || contentElement == null || fileContainer == null) return;
|
|
1806
2000
|
const viewport = this.#getScrollViewport();
|
|
1807
2001
|
if (viewport === void 0) return;
|
|
1808
2002
|
let viewportTop;
|
|
@@ -1919,7 +2113,7 @@ var Editor = class {
|
|
|
1919
2113
|
this.#scrollingToLineFixed = false;
|
|
1920
2114
|
this.#scrollingToLineNoFocus = false;
|
|
1921
2115
|
} else {
|
|
1922
|
-
const modelLinePosition = this.#
|
|
2116
|
+
const modelLinePosition = this.#virtualizedInstance?.getLinePosition?.(line + 1);
|
|
1923
2117
|
if (modelLinePosition !== void 0) {
|
|
1924
2118
|
virtualCaret.style.top = modelLinePosition.top + "px";
|
|
1925
2119
|
this.#fileContainer?.shadowRoot?.appendChild(virtualCaret);
|
|
@@ -2068,8 +2262,493 @@ var Editor = class {
|
|
|
2068
2262
|
if (this.#selections !== void 0 || this.#matches !== void 0 || this.#markerRenderer !== void 0) this.#updateSelections(this.#selections ?? []);
|
|
2069
2263
|
});
|
|
2070
2264
|
}
|
|
2265
|
+
#updateAltColumnSelections() {
|
|
2266
|
+
const drag = this.#altColumnDrag;
|
|
2267
|
+
const selectionStart = this.#selectionStart;
|
|
2268
|
+
const textDocument = this.#editSession?.document;
|
|
2269
|
+
if (drag === void 0 || drag.focusLine === void 0 || selectionStart === void 0 || textDocument === void 0) return false;
|
|
2270
|
+
const anchor = selectionStart.direction === -1 ? selectionStart.end : selectionStart.start;
|
|
2271
|
+
const scrollLeft = this.#contentElement?.parentElement?.scrollLeft ?? 0;
|
|
2272
|
+
const characterDeltaRaw = (drag.clientX - drag.startClientX + scrollLeft - drag.startScrollLeft) / this.#metrics.ch;
|
|
2273
|
+
const characterDelta = characterDeltaRaw < 0 ? -Math.round(-characterDeltaRaw) : Math.round(characterDeltaRaw);
|
|
2274
|
+
const focusCharacter = Math.max(0, anchor.character + characterDelta);
|
|
2275
|
+
const goal = {
|
|
2276
|
+
line: drag.focusLine,
|
|
2277
|
+
character: focusCharacter
|
|
2278
|
+
};
|
|
2279
|
+
if (drag.renderedGoal !== void 0 && comparePosition(drag.renderedGoal, goal) === 0) return true;
|
|
2280
|
+
drag.renderedGoal = goal;
|
|
2281
|
+
const selections = [];
|
|
2282
|
+
const step = goal.line < anchor.line ? -1 : 1;
|
|
2283
|
+
for (let line = anchor.line;; line += step) {
|
|
2284
|
+
if (this.#isLineRenderable(line)) {
|
|
2285
|
+
const lineText = textDocument.getLineText(line);
|
|
2286
|
+
const anchorOffset = Math.min(anchor.character, lineText.length);
|
|
2287
|
+
const focusOffset = Math.min(focusCharacter, lineText.length);
|
|
2288
|
+
const anchorCharacter = snapCharacterToGraphemeBoundary(lineText, anchorOffset);
|
|
2289
|
+
const lineFocusCharacter = focusOffset === anchorOffset ? anchorCharacter : snapCharacterToGraphemeBoundary(lineText, focusOffset);
|
|
2290
|
+
selections.push({
|
|
2291
|
+
start: {
|
|
2292
|
+
line,
|
|
2293
|
+
character: Math.min(anchorCharacter, lineFocusCharacter)
|
|
2294
|
+
},
|
|
2295
|
+
end: {
|
|
2296
|
+
line,
|
|
2297
|
+
character: Math.max(anchorCharacter, lineFocusCharacter)
|
|
2298
|
+
},
|
|
2299
|
+
direction: anchorCharacter === lineFocusCharacter ? 0 : anchorCharacter < lineFocusCharacter ? 1 : -1
|
|
2300
|
+
});
|
|
2301
|
+
}
|
|
2302
|
+
if (line === goal.line) break;
|
|
2303
|
+
}
|
|
2304
|
+
this.#updateSelections(selections);
|
|
2305
|
+
return true;
|
|
2306
|
+
}
|
|
2307
|
+
#removeRenderedEditPrediction() {
|
|
2308
|
+
for (const [key, element] of this.#overlayElements ?? []) if (key.startsWith("editPrediction")) {
|
|
2309
|
+
element.remove();
|
|
2310
|
+
this.#overlayElements?.delete(key);
|
|
2311
|
+
}
|
|
2312
|
+
}
|
|
2313
|
+
#composeEditPredictionGroup(textDocument, edits, startIndex) {
|
|
2314
|
+
const firstEdit = edits[startIndex];
|
|
2315
|
+
let endIndex = startIndex;
|
|
2316
|
+
let endLine = firstEdit.range.end.line;
|
|
2317
|
+
while (endIndex + 1 < edits.length && edits[endIndex + 1].range.start.line <= endLine) {
|
|
2318
|
+
endIndex++;
|
|
2319
|
+
endLine = Math.max(endLine, edits[endIndex].range.end.line);
|
|
2320
|
+
}
|
|
2321
|
+
if (endIndex === startIndex && (firstEdit.newText.length === 0 || comparePosition(firstEdit.range.start, firstEdit.range.end) === 0)) return {
|
|
2322
|
+
edit: firstEdit,
|
|
2323
|
+
endIndex
|
|
2324
|
+
};
|
|
2325
|
+
const start = firstEdit.range.start;
|
|
2326
|
+
const end = {
|
|
2327
|
+
line: endLine,
|
|
2328
|
+
character: textDocument.getLineLength(endLine)
|
|
2329
|
+
};
|
|
2330
|
+
const parts = [];
|
|
2331
|
+
let consumed = textDocument.offsetAt(start);
|
|
2332
|
+
for (let index = startIndex; index <= endIndex; index++) {
|
|
2333
|
+
const edit = edits[index];
|
|
2334
|
+
const editStart = textDocument.offsetAt(edit.range.start);
|
|
2335
|
+
const editEnd = textDocument.offsetAt(edit.range.end);
|
|
2336
|
+
parts.push(textDocument.getTextSlice(consumed, editStart), edit.newText);
|
|
2337
|
+
consumed = editEnd;
|
|
2338
|
+
}
|
|
2339
|
+
parts.push(textDocument.getTextSlice(consumed, textDocument.offsetAt(end)));
|
|
2340
|
+
return {
|
|
2341
|
+
edit: {
|
|
2342
|
+
range: {
|
|
2343
|
+
start,
|
|
2344
|
+
end
|
|
2345
|
+
},
|
|
2346
|
+
newText: parts.join("")
|
|
2347
|
+
},
|
|
2348
|
+
endIndex
|
|
2349
|
+
};
|
|
2350
|
+
}
|
|
2351
|
+
#getEditPredictionGroups() {
|
|
2352
|
+
const prediction = this.#editPrediction;
|
|
2353
|
+
const textDocument = this.#editSession?.document;
|
|
2354
|
+
if (prediction == null || textDocument == null || prediction.document !== textDocument || prediction.version !== textDocument.version || this.#options.editPrediction?.mode === "subtle" && !this.#editPredictionRevealed) return;
|
|
2355
|
+
const { edits } = prediction.response;
|
|
2356
|
+
const groups = [];
|
|
2357
|
+
let allVisible = edits.length > 0;
|
|
2358
|
+
for (let startIndex = 0; startIndex < edits.length;) {
|
|
2359
|
+
const { edit, endIndex } = this.#composeEditPredictionGroup(textDocument, edits, startIndex);
|
|
2360
|
+
for (let line = edit.range.start.line; allVisible && line <= edit.range.end.line; line++) allVisible = this.#isLineVisible(line);
|
|
2361
|
+
groups.push({
|
|
2362
|
+
edit,
|
|
2363
|
+
startIndex,
|
|
2364
|
+
endIndex
|
|
2365
|
+
});
|
|
2366
|
+
startIndex = endIndex + 1;
|
|
2367
|
+
}
|
|
2368
|
+
return {
|
|
2369
|
+
groups,
|
|
2370
|
+
allVisible
|
|
2371
|
+
};
|
|
2372
|
+
}
|
|
2373
|
+
#fillGhostTextElement(element, newText, anchorLeft, lineLeft, insertionSuffix) {
|
|
2374
|
+
if (this.#isWrap) {
|
|
2375
|
+
element.dataset.wrap = "";
|
|
2376
|
+
element.style.width = `calc(100cqw - ${lineLeft}px)`;
|
|
2377
|
+
} else {
|
|
2378
|
+
delete element.dataset.wrap;
|
|
2379
|
+
element.style.width = "max-content";
|
|
2380
|
+
}
|
|
2381
|
+
const lines = newText.split(/\r\n|\r|\n/);
|
|
2382
|
+
for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
|
|
2383
|
+
const lineText = lines[lineIndex];
|
|
2384
|
+
const suffix = lineIndex === lines.length - 1 ? insertionSuffix : void 0;
|
|
2385
|
+
const isEmpty = lineText.length === 0 && suffix === void 0;
|
|
2386
|
+
const line = h("span", {
|
|
2387
|
+
dataset: isEmpty ? ["editPredictionLine", "empty"] : "editPredictionLine",
|
|
2388
|
+
textContent: isEmpty ? "" : lineText
|
|
2389
|
+
}, element);
|
|
2390
|
+
if (suffix !== void 0) h("span", { dataset: "editPredictionSuffix" }, line).append(suffix);
|
|
2391
|
+
if (lineIndex === 0 && anchorLeft !== lineLeft) line.style.textIndent = `${anchorLeft - lineLeft}px`;
|
|
2392
|
+
}
|
|
2393
|
+
}
|
|
2394
|
+
#cloneInsertionSuffix(group) {
|
|
2395
|
+
const prediction = this.#editPrediction;
|
|
2396
|
+
const textDocument = this.#editSession?.document;
|
|
2397
|
+
if (prediction == null || textDocument == null) return;
|
|
2398
|
+
const { edit, startIndex, endIndex } = group;
|
|
2399
|
+
const { start, end } = edit.range;
|
|
2400
|
+
if (!(comparePosition(start, end) === 0 && start.character < textDocument.getLineLength(start.line)) || prediction.response.edits[startIndex - 1]?.range.end.line === start.line || prediction.response.edits[endIndex + 1]?.range.start.line === start.line) return;
|
|
2401
|
+
const sourceLine = this.#getLineElement(start.line);
|
|
2402
|
+
if (sourceLine === void 0) return document.createTextNode(textDocument.getLineText(start.line).slice(start.character));
|
|
2403
|
+
const [suffixNode, suffixOffset] = getSelectionAnchor(sourceLine, start.character);
|
|
2404
|
+
const suffixRange = document.createRange();
|
|
2405
|
+
suffixRange.selectNodeContents(sourceLine);
|
|
2406
|
+
suffixRange.setStart(suffixNode, clampDomOffset(suffixNode, suffixOffset));
|
|
2407
|
+
const suffix = suffixRange.cloneContents();
|
|
2408
|
+
if (suffix.firstChild?.textContent === "") suffix.firstChild.remove();
|
|
2409
|
+
return suffix;
|
|
2410
|
+
}
|
|
2411
|
+
#measureGhostTextRows(group) {
|
|
2412
|
+
const { edit } = group;
|
|
2413
|
+
const { start } = edit.range;
|
|
2414
|
+
const [anchorLeft, anchorWrapLine] = this.#getCharX(start.line, start.character);
|
|
2415
|
+
let anchorVisualLines = 1;
|
|
2416
|
+
let ghostVisualLines = edit.newText.split(/\r\n|\r|\n/).length;
|
|
2417
|
+
const overlayElement = this.#overlayElement;
|
|
2418
|
+
if (this.#isWrap && overlayElement != null) {
|
|
2419
|
+
anchorVisualLines = Math.max(1, this.#wrapLineTextOrWholeLine(start.line).length - 1);
|
|
2420
|
+
const probe = h("span", {
|
|
2421
|
+
dataset: "editPrediction",
|
|
2422
|
+
style: { visibility: "hidden" }
|
|
2423
|
+
}, overlayElement);
|
|
2424
|
+
this.#fillGhostTextElement(probe, edit.newText, anchorLeft, this.#getCharX(start.line, 0)[0], this.#cloneInsertionSuffix(group));
|
|
2425
|
+
const { width, height } = probe.getBoundingClientRect();
|
|
2426
|
+
probe.remove();
|
|
2427
|
+
const { lineHeight } = this.#metrics;
|
|
2428
|
+
if (width > 0 && height > 0 && lineHeight > 0) ghostVisualLines = Math.round(height / lineHeight);
|
|
2429
|
+
}
|
|
2430
|
+
return Math.max(0, ghostVisualLines - (anchorVisualLines - anchorWrapLine));
|
|
2431
|
+
}
|
|
2432
|
+
#syncEditPredictionSpacers(notifyComponent = true) {
|
|
2433
|
+
const nextSpacers = /* @__PURE__ */ new Map();
|
|
2434
|
+
const ghostTextRows = /* @__PURE__ */ new Map();
|
|
2435
|
+
const previousRows = this.#ghostTextRows;
|
|
2436
|
+
let rowsChanged = false;
|
|
2437
|
+
const contentElement = this.#contentElement;
|
|
2438
|
+
const composed = this.#getEditPredictionGroups();
|
|
2439
|
+
if (contentElement != null && composed != null && composed.allVisible) {
|
|
2440
|
+
for (const group of composed.groups) {
|
|
2441
|
+
const { edit } = group;
|
|
2442
|
+
if (edit.newText.length === 0) continue;
|
|
2443
|
+
const count = this.#measureGhostTextRows(group);
|
|
2444
|
+
if (count > (ghostTextRows.get(edit.range.start.line) ?? 0)) ghostTextRows.set(edit.range.start.line, count);
|
|
2445
|
+
}
|
|
2446
|
+
if (ghostTextRows.size > 0) {
|
|
2447
|
+
let rowIndexes;
|
|
2448
|
+
const startingLine = this.#renderRange?.startingLine ?? 0;
|
|
2449
|
+
for (const [line, count] of ghostTextRows) {
|
|
2450
|
+
rowsChanged ||= previousRows.get(line) !== count;
|
|
2451
|
+
const lineElement = this.#getLineElement(line);
|
|
2452
|
+
if (lineElement === void 0) continue;
|
|
2453
|
+
let rowIndex = line - startingLine;
|
|
2454
|
+
if (contentElement.children[rowIndex] !== lineElement) {
|
|
2455
|
+
if (rowIndexes === void 0) {
|
|
2456
|
+
rowIndexes = /* @__PURE__ */ new Map();
|
|
2457
|
+
for (let index = 0; index < contentElement.children.length; index++) rowIndexes.set(contentElement.children[index], index);
|
|
2458
|
+
}
|
|
2459
|
+
rowIndex = rowIndexes.get(lineElement) ?? -1;
|
|
2460
|
+
}
|
|
2461
|
+
if (rowIndex < 0) continue;
|
|
2462
|
+
nextSpacers.set(lineElement, count);
|
|
2463
|
+
const gutterRow = this.#gutterElement?.children[rowIndex];
|
|
2464
|
+
if (gutterRow instanceof HTMLElement) nextSpacers.set(gutterRow, count);
|
|
2465
|
+
const partner = this.#deletionsColumnPartner(rowIndex);
|
|
2466
|
+
if (partner != null) {
|
|
2467
|
+
nextSpacers.set(partner.content, (nextSpacers.get(partner.content) ?? 0) + count);
|
|
2468
|
+
nextSpacers.set(partner.gutter, (nextSpacers.get(partner.gutter) ?? 0) + count);
|
|
2469
|
+
}
|
|
2470
|
+
}
|
|
2471
|
+
}
|
|
2472
|
+
}
|
|
2473
|
+
let changed = false;
|
|
2474
|
+
for (const [element, count] of this.#editPredictionSpacers) {
|
|
2475
|
+
if (nextSpacers.get(element) === count) continue;
|
|
2476
|
+
delete element.dataset.editPredictionSpacer;
|
|
2477
|
+
element.style.removeProperty("--diffs-edit-prediction-spacer-height");
|
|
2478
|
+
changed = true;
|
|
2479
|
+
}
|
|
2480
|
+
for (const [element, count] of nextSpacers) {
|
|
2481
|
+
if (this.#editPredictionSpacers.get(element) === count) continue;
|
|
2482
|
+
element.dataset.editPredictionSpacer = "";
|
|
2483
|
+
element.style.setProperty("--diffs-edit-prediction-spacer-height", `${count}lh`);
|
|
2484
|
+
changed = true;
|
|
2485
|
+
}
|
|
2486
|
+
this.#editPredictionSpacers = nextSpacers;
|
|
2487
|
+
if (rowsChanged || ghostTextRows.size !== previousRows.size) {
|
|
2488
|
+
this.#ghostTextRows = ghostTextRows;
|
|
2489
|
+
if (notifyComponent) this.#virtualizedInstance?.syncGhostTextRows();
|
|
2490
|
+
}
|
|
2491
|
+
if (changed) this.#resetCache();
|
|
2492
|
+
}
|
|
2493
|
+
#deletionsColumnPartner(rowIndex) {
|
|
2494
|
+
const deletionsColumn = this.#deletionsColumn;
|
|
2495
|
+
const contentElement = this.#contentElement;
|
|
2496
|
+
if (deletionsColumn == null || contentElement == null || !this.#isDiff || this.#diffSyle !== "split" || this.#isWrap) return;
|
|
2497
|
+
let track = 0;
|
|
2498
|
+
for (let index = 0; index < rowIndex; index++) track += gridTrackSpan(contentElement.children[index]);
|
|
2499
|
+
const { content, gutter } = deletionsColumn;
|
|
2500
|
+
let covered = 0;
|
|
2501
|
+
for (let index = 0; index < content.children.length; index++) {
|
|
2502
|
+
const child = content.children[index];
|
|
2503
|
+
covered += gridTrackSpan(child);
|
|
2504
|
+
if (covered > track) {
|
|
2505
|
+
const gutterChild = gutter.children[index];
|
|
2506
|
+
if (!(child instanceof HTMLElement) || !(gutterChild instanceof HTMLElement)) throw new Error("Editor: deletions column rows and gutter cells are out of step");
|
|
2507
|
+
return {
|
|
2508
|
+
content: child,
|
|
2509
|
+
gutter: gutterChild
|
|
2510
|
+
};
|
|
2511
|
+
}
|
|
2512
|
+
}
|
|
2513
|
+
}
|
|
2514
|
+
#cancelEditPrediction(removeRendered, notifyComponent = true) {
|
|
2515
|
+
if (this.#editPredictionTimer !== void 0) {
|
|
2516
|
+
clearTimeout(this.#editPredictionTimer);
|
|
2517
|
+
this.#editPredictionTimer = void 0;
|
|
2518
|
+
}
|
|
2519
|
+
this.#editPredictionAbortController?.abort();
|
|
2520
|
+
this.#editPredictionAbortController = void 0;
|
|
2521
|
+
this.#editPredictionGeneration++;
|
|
2522
|
+
this.#editPredictionRevealed = false;
|
|
2523
|
+
this.#retryEditPredictionOnRender = false;
|
|
2524
|
+
this.#editPrediction = void 0;
|
|
2525
|
+
this.#syncEditPredictionSpacers(notifyComponent);
|
|
2526
|
+
if (removeRendered) this.#removeRenderedEditPrediction();
|
|
2527
|
+
}
|
|
2528
|
+
#includesEditPredictionPath(path) {
|
|
2529
|
+
const options = this.#options.editPrediction;
|
|
2530
|
+
if (options === void 0) return false;
|
|
2531
|
+
const normalizedPath = path.replaceAll("\\", "/");
|
|
2532
|
+
return (options.include === void 0 || options.include.some((pattern) => matchesEditPredictionPattern(normalizedPath, pattern))) && options.exclude?.some((pattern) => matchesEditPredictionPattern(normalizedPath, pattern)) !== true;
|
|
2533
|
+
}
|
|
2534
|
+
#scheduleEditPrediction() {
|
|
2535
|
+
this.#cancelEditPrediction(true);
|
|
2536
|
+
const selection = this.#selections?.[0];
|
|
2537
|
+
if (this.#options.editPrediction === void 0 || this.#editSession?.document === void 0 || this.#editSession?.fileInfo === void 0 || this.#selections?.length !== 1 || selection === void 0 || !isCollapsedSelection(selection)) return;
|
|
2538
|
+
const document = this.#editSession?.document;
|
|
2539
|
+
const cursorOffset = document.offsetAt(getCaretPosition(selection));
|
|
2540
|
+
this.#editPredictionTimer = setTimeout(() => {
|
|
2541
|
+
this.#editPredictionTimer = void 0;
|
|
2542
|
+
const options = this.#options.editPrediction;
|
|
2543
|
+
const currentSelection = this.#selections?.[0];
|
|
2544
|
+
const path = this.#editSession?.fileInfo?.name;
|
|
2545
|
+
if (options === void 0 || path === void 0 || this.#editSession?.document !== document || this.#selections?.length !== 1 || currentSelection === void 0 || !isCollapsedSelection(currentSelection) || document.offsetAt(getCaretPosition(currentSelection)) !== cursorOffset) return;
|
|
2546
|
+
if (!this.#includesEditPredictionPath(path)) return;
|
|
2547
|
+
const isLineEditable = (line) => this.#isLineInRenderRange(line) && this.#isLineRenderable(line);
|
|
2548
|
+
if (!isLineEditable(getCaretPosition(currentSelection).line)) {
|
|
2549
|
+
this.#retryEditPredictionOnRender = true;
|
|
2550
|
+
return;
|
|
2551
|
+
}
|
|
2552
|
+
const request = buildEditPredictionRequest(path, document, cursorOffset, this.#editPredictionHistory, isLineEditable);
|
|
2553
|
+
if (request === void 0) return;
|
|
2554
|
+
const excerptStartOffset = document.offsetAt({
|
|
2555
|
+
line: request.excerptStartLine,
|
|
2556
|
+
character: 0
|
|
2557
|
+
});
|
|
2558
|
+
const editableStart = excerptStartOffset + request.editableRange.start;
|
|
2559
|
+
const editableEnd = excerptStartOffset + request.editableRange.end;
|
|
2560
|
+
const controller = new AbortController();
|
|
2561
|
+
const generation = ++this.#editPredictionGeneration;
|
|
2562
|
+
this.#editPredictionAbortController = controller;
|
|
2563
|
+
let prediction;
|
|
2564
|
+
try {
|
|
2565
|
+
prediction = options.provider.predict(request, { signal: controller.signal });
|
|
2566
|
+
} catch {
|
|
2567
|
+
this.#editPredictionAbortController = void 0;
|
|
2568
|
+
return;
|
|
2569
|
+
}
|
|
2570
|
+
Promise.resolve(prediction).then((response) => {
|
|
2571
|
+
const selection = this.#selections?.[0];
|
|
2572
|
+
if (controller.signal.aborted || generation !== this.#editPredictionGeneration || this.#editPredictionAbortController !== controller || this.#editSession?.document !== document || document.version !== request.version || this.#selections?.length !== 1 || selection === void 0 || !isCollapsedSelection(selection) || document.offsetAt(getCaretPosition(selection)) !== cursorOffset) return;
|
|
2573
|
+
if (response == null || !Array.isArray(response.edits) || response.edits.length === 0 || response.edits.length > MAX_EDIT_PREDICTION_RESPONSE_EDITS || response.newCursor == null) return;
|
|
2574
|
+
const resolvedEdits = [];
|
|
2575
|
+
let responseBytes = 0;
|
|
2576
|
+
for (const edit of response.edits) {
|
|
2577
|
+
if (edit == null || typeof edit.newText !== "string" || !isValidEditPredictionPosition(document, edit.range?.start) || !isValidEditPredictionPosition(document, edit.range?.end) || comparePosition(edit.range.start, edit.range.end) > 0) return;
|
|
2578
|
+
responseBytes += editPredictionTextEncoder.encode(edit.newText).byteLength;
|
|
2579
|
+
if (responseBytes > MAX_EDIT_PREDICTION_RESPONSE_BYTES) return;
|
|
2580
|
+
const start = document.offsetAt(edit.range.start);
|
|
2581
|
+
const end = document.offsetAt(edit.range.end);
|
|
2582
|
+
const resolvedEdit = document.resolveEdits([edit])[0];
|
|
2583
|
+
if (resolvedEdit.start !== start || resolvedEdit.end !== end) return;
|
|
2584
|
+
resolvedEdits.push(resolvedEdit);
|
|
2585
|
+
}
|
|
2586
|
+
resolvedEdits.sort((left, right) => {
|
|
2587
|
+
const startDelta = left.start - right.start;
|
|
2588
|
+
return startDelta === 0 ? left.end - right.end : startDelta;
|
|
2589
|
+
});
|
|
2590
|
+
for (let index = 0; index < resolvedEdits.length; index++) {
|
|
2591
|
+
const edit = resolvedEdits[index];
|
|
2592
|
+
if (edit.start < editableStart || edit.end > editableEnd || index > 0 && resolvedEdits[index - 1].end > edit.start) return;
|
|
2593
|
+
}
|
|
2594
|
+
const edits = resolvedEdits.filter((edit) => edit.text !== document.getTextSlice(edit.start, edit.end));
|
|
2595
|
+
if (edits.length === 0) return;
|
|
2596
|
+
const firstEditPosition = document.positionAt(edits[0].start);
|
|
2597
|
+
const lastEditPosition = document.positionAt(edits.at(-1).end);
|
|
2598
|
+
const affectedStart = document.offsetAt({
|
|
2599
|
+
line: firstEditPosition.line,
|
|
2600
|
+
character: 0
|
|
2601
|
+
});
|
|
2602
|
+
const affectedEnd = document.offsetAt({
|
|
2603
|
+
line: lastEditPosition.line,
|
|
2604
|
+
character: document.getLineLength(lastEditPosition.line)
|
|
2605
|
+
});
|
|
2606
|
+
const predictedParts = [];
|
|
2607
|
+
let consumed = affectedStart;
|
|
2608
|
+
for (const edit of edits) {
|
|
2609
|
+
predictedParts.push(document.getTextSlice(consumed, edit.start), edit.text);
|
|
2610
|
+
consumed = edit.end;
|
|
2611
|
+
}
|
|
2612
|
+
predictedParts.push(document.getTextSlice(consumed, affectedEnd));
|
|
2613
|
+
const predictedLines = predictedParts.join("").split(/\r\n|\r|\n/);
|
|
2614
|
+
const affectedEndLine = firstEditPosition.line + predictedLines.length - 1;
|
|
2615
|
+
const lineDelta = predictedLines.length - (lastEditPosition.line - firstEditPosition.line + 1);
|
|
2616
|
+
const newCursor = response.newCursor;
|
|
2617
|
+
if (!Number.isInteger(newCursor.line) || !Number.isInteger(newCursor.character) || newCursor.line < 0 || newCursor.character < 0) return;
|
|
2618
|
+
if (newCursor.line >= firstEditPosition.line && newCursor.line <= affectedEndLine) {
|
|
2619
|
+
const line = predictedLines[newCursor.line - firstEditPosition.line];
|
|
2620
|
+
if (newCursor.character > line.length || splitsSurrogatePair(line, newCursor.character)) return;
|
|
2621
|
+
} else {
|
|
2622
|
+
const originalLine = newCursor.line < firstEditPosition.line ? newCursor.line : newCursor.line - lineDelta;
|
|
2623
|
+
if (originalLine < 0 || originalLine >= document.lineCount || newCursor.character > document.getLineLength(originalLine)) return;
|
|
2624
|
+
const originalOffset = document.offsetAt({
|
|
2625
|
+
line: originalLine,
|
|
2626
|
+
character: newCursor.character
|
|
2627
|
+
});
|
|
2628
|
+
if (splitsSurrogatePair(document.charAt(originalOffset - 1) + document.charAt(originalOffset), 1)) return;
|
|
2629
|
+
}
|
|
2630
|
+
this.#editPrediction = {
|
|
2631
|
+
document,
|
|
2632
|
+
version: request.version,
|
|
2633
|
+
cursorOffset,
|
|
2634
|
+
rendered: false,
|
|
2635
|
+
response: {
|
|
2636
|
+
edits: edits.map((edit) => ({
|
|
2637
|
+
range: {
|
|
2638
|
+
start: document.positionAt(edit.start),
|
|
2639
|
+
end: document.positionAt(edit.end)
|
|
2640
|
+
},
|
|
2641
|
+
newText: edit.text
|
|
2642
|
+
})),
|
|
2643
|
+
newCursor: { ...newCursor }
|
|
2644
|
+
}
|
|
2645
|
+
};
|
|
2646
|
+
this.#updateSelections(this.#selections);
|
|
2647
|
+
}).catch(() => {}).finally(() => {
|
|
2648
|
+
if (this.#editPredictionAbortController === controller) this.#editPredictionAbortController = void 0;
|
|
2649
|
+
});
|
|
2650
|
+
}, EDIT_PREDICTION_DEBOUNCE_MS);
|
|
2651
|
+
}
|
|
2652
|
+
#recordEditPredictionHistory(change, source) {
|
|
2653
|
+
const textDocument = this.#editSession?.document;
|
|
2654
|
+
const path = this.#editSession?.fileInfo?.name;
|
|
2655
|
+
const transaction = getTextDocumentChangeTransaction(change);
|
|
2656
|
+
if (textDocument === void 0 || path === void 0 || transaction === void 0 || !this.#includesEditPredictionPath(path)) return;
|
|
2657
|
+
this.#editPredictionHistory = recordEditPrediction(this.#editPredictionHistory, path, textDocument, transaction, source);
|
|
2658
|
+
}
|
|
2659
|
+
#acceptEditPrediction() {
|
|
2660
|
+
const prediction = this.#editPrediction;
|
|
2661
|
+
const textDocument = this.#editSession?.document;
|
|
2662
|
+
const selection = this.#selections?.[0];
|
|
2663
|
+
if (prediction === void 0 || !prediction.rendered || textDocument === void 0 || prediction.document !== textDocument || prediction.version !== textDocument.version || this.#selections?.length !== 1 || selection === void 0 || !isCollapsedSelection(selection) || textDocument.offsetAt(getCaretPosition(selection)) !== prediction.cursorOffset) return;
|
|
2664
|
+
const { edits, newCursor } = prediction.response;
|
|
2665
|
+
this.#cancelEditPrediction(true);
|
|
2666
|
+
const change = textDocument.applyEdits(edits.map((edit) => ({
|
|
2667
|
+
range: {
|
|
2668
|
+
start: { ...edit.range.start },
|
|
2669
|
+
end: { ...edit.range.end }
|
|
2670
|
+
},
|
|
2671
|
+
newText: edit.newText
|
|
2672
|
+
})), true, this.#selections, void 0, true);
|
|
2673
|
+
if (change === void 0) {
|
|
2674
|
+
this.#scheduleEditPrediction();
|
|
2675
|
+
return;
|
|
2676
|
+
}
|
|
2677
|
+
const cursor = textDocument.normalizePosition(newCursor);
|
|
2678
|
+
const nextSelections = [{
|
|
2679
|
+
start: cursor,
|
|
2680
|
+
end: cursor,
|
|
2681
|
+
direction: 0
|
|
2682
|
+
}];
|
|
2683
|
+
textDocument.setLastUndoSelectionsAfter(nextSelections);
|
|
2684
|
+
this.#applyChange(change, nextSelections, this.#applyChangeToLineAnnotations(change), { editSource: "prediction" });
|
|
2685
|
+
}
|
|
2686
|
+
#renderEditPrediction(renderCtx) {
|
|
2687
|
+
const prediction = this.#editPrediction;
|
|
2688
|
+
const textDocument = this.#editSession?.document;
|
|
2689
|
+
if (prediction !== void 0) prediction.rendered = false;
|
|
2690
|
+
const composed = this.#getEditPredictionGroups();
|
|
2691
|
+
if (prediction == null || textDocument == null || composed == null || !composed.allVisible) return;
|
|
2692
|
+
for (const group of composed.groups) {
|
|
2693
|
+
const { edit, endIndex } = group;
|
|
2694
|
+
const { start, end } = edit.range;
|
|
2695
|
+
const isDeletion = edit.newText.length === 0;
|
|
2696
|
+
const isReplacement = comparePosition(start, end) !== 0;
|
|
2697
|
+
const lineLength = textDocument.getLineLength(start.line);
|
|
2698
|
+
const isMidLineInsertion = !isReplacement && start.character < lineLength;
|
|
2699
|
+
if (isReplacement) this.#renderSelection(renderCtx, isDeletion ? "editPredictionDeletion" : "editPredictionReplacement", {
|
|
2700
|
+
start,
|
|
2701
|
+
end
|
|
2702
|
+
});
|
|
2703
|
+
else if (isMidLineInsertion) this.#renderSelection(renderCtx, "editPredictionInsertion", {
|
|
2704
|
+
start,
|
|
2705
|
+
end: {
|
|
2706
|
+
line: start.line,
|
|
2707
|
+
character: lineLength
|
|
2708
|
+
}
|
|
2709
|
+
});
|
|
2710
|
+
if (isDeletion) continue;
|
|
2711
|
+
const [anchorLeft, anchorWrapLine] = this.#getCharX(start.line, start.character);
|
|
2712
|
+
const lineLeft = this.#getCharX(start.line, 0)[0];
|
|
2713
|
+
const anchorTop = this.#getLineY(start.line) + anchorWrapLine * this.#metrics.lineHeight;
|
|
2714
|
+
const key = `editPrediction-${endIndex}`;
|
|
2715
|
+
let element = this.#overlayElements?.get(key);
|
|
2716
|
+
if (element !== void 0) {
|
|
2717
|
+
this.#overlayElements?.delete(key);
|
|
2718
|
+
element.replaceChildren();
|
|
2719
|
+
} else element = h("span", {
|
|
2720
|
+
ariaHidden: "true",
|
|
2721
|
+
contentEditable: "false",
|
|
2722
|
+
dataset: "editPrediction"
|
|
2723
|
+
}, renderCtx.fragment);
|
|
2724
|
+
if (isReplacement) {
|
|
2725
|
+
element.dataset.replacement = "";
|
|
2726
|
+
const lineElement = this.#getLineElement(start.line);
|
|
2727
|
+
if (lineElement !== void 0) element.style.setProperty("--diffs-edit-prediction-bg", getComputedStyle(lineElement).getPropertyValue("--diffs-line-bg"));
|
|
2728
|
+
} else {
|
|
2729
|
+
delete element.dataset.replacement;
|
|
2730
|
+
element.style.removeProperty("--diffs-edit-prediction-bg");
|
|
2731
|
+
}
|
|
2732
|
+
this.#fillGhostTextElement(element, edit.newText, anchorLeft, lineLeft, this.#cloneInsertionSuffix(group));
|
|
2733
|
+
element.style.transform = `translateX(${lineLeft}px) translateY(${anchorTop}px)`;
|
|
2734
|
+
renderCtx.elements.set(key, element);
|
|
2735
|
+
}
|
|
2736
|
+
prediction.rendered = true;
|
|
2737
|
+
}
|
|
2071
2738
|
#updateSelections(selections) {
|
|
2072
2739
|
this.__postponeBgTokenizeToNextFrame();
|
|
2740
|
+
const previousSelections = this.#selections;
|
|
2741
|
+
let selectionsChanged = previousSelections?.length !== selections.length;
|
|
2742
|
+
if (!selectionsChanged && previousSelections !== void 0) for (let i = 0; i < selections.length; i++) {
|
|
2743
|
+
const previous = previousSelections[i];
|
|
2744
|
+
const next = selections[i];
|
|
2745
|
+
if (previous.direction !== next.direction || comparePosition(previous.start, next.start) !== 0 || comparePosition(previous.end, next.end) !== 0) {
|
|
2746
|
+
selectionsChanged = true;
|
|
2747
|
+
break;
|
|
2748
|
+
}
|
|
2749
|
+
}
|
|
2750
|
+
if (selectionsChanged) this.#cancelEditPrediction(true);
|
|
2751
|
+
this.#syncEditPredictionSpacers();
|
|
2073
2752
|
this.#primaryCaretElement = void 0;
|
|
2074
2753
|
this.#setEditorActiveLineSafe(null);
|
|
2075
2754
|
if (selections.length === 0 && this.#matches === void 0 && this.#markerRenderer === void 0) {
|
|
@@ -2078,6 +2757,7 @@ var Editor = class {
|
|
|
2078
2757
|
this.#overlayElements?.clear();
|
|
2079
2758
|
this.#selectionAction?.cleanup();
|
|
2080
2759
|
this.#selectionAction = void 0;
|
|
2760
|
+
if (selectionsChanged) this.#scheduleEditPrediction();
|
|
2081
2761
|
return;
|
|
2082
2762
|
}
|
|
2083
2763
|
const fragment = document.createDocumentFragment();
|
|
@@ -2096,14 +2776,14 @@ var Editor = class {
|
|
|
2096
2776
|
if (!isCollapsedSelection(selection)) this.#renderSelection(renderCtx, "selection", selection);
|
|
2097
2777
|
this.#renderCaret(renderCtx, selection, selection === primarySelection);
|
|
2098
2778
|
}
|
|
2099
|
-
const bracketMatchRanges = this.#options.matchBrackets !== false && this.#
|
|
2779
|
+
const bracketMatchRanges = this.#options.matchBrackets !== false && this.#editSession?.document != null && this.#tokenizer !== void 0 && isCollapsedSelection(primarySelection) ? findBracketMatchRanges(this.#editSession?.document, this.#tokenizer, primarySelection.start) : void 0;
|
|
2100
2780
|
if (bracketMatchRanges !== void 0) for (const range of bracketMatchRanges) this.#renderSelection(renderCtx, "bracketMatch", range);
|
|
2101
2781
|
}
|
|
2102
|
-
const textDocument = this.#
|
|
2782
|
+
const textDocument = this.#editSession?.document;
|
|
2103
2783
|
if (this.#matches !== void 0 && textDocument !== void 0) {
|
|
2104
2784
|
const matches = this.#matches;
|
|
2105
2785
|
const renderRange = this.#renderRange;
|
|
2106
|
-
const renderedLineRanges = renderRange
|
|
2786
|
+
const renderedLineRanges = renderRange != null && Number.isFinite(renderRange.totalLines) || this.#isDiff && this.#fileDiffInstance?.options.expandUnchanged !== true ? this.#getRenderedEditableLineRanges() : void 0;
|
|
2107
2787
|
const primarySelection = this.#selections?.at(-1);
|
|
2108
2788
|
const primaryStartOffset = primarySelection !== void 0 ? textDocument.offsetAt(primarySelection.start) : -1;
|
|
2109
2789
|
const primaryEndOffset = primarySelection !== void 0 ? textDocument.offsetAt(primarySelection.end) : -1;
|
|
@@ -2148,14 +2828,70 @@ var Editor = class {
|
|
|
2148
2828
|
}
|
|
2149
2829
|
}
|
|
2150
2830
|
if (this.#markerRenderer !== void 0 && textDocument !== void 0) for (const marker of this.#markerRenderer.markers) this.#renderSelection(renderCtx, "marker", marker, markerSeverityDatasetKey(marker.severity));
|
|
2831
|
+
this.#renderEditPrediction(renderCtx);
|
|
2151
2832
|
this.#overlayElement?.appendChild(fragment);
|
|
2152
2833
|
this.#overlayElements?.forEach((el) => el.remove());
|
|
2153
2834
|
this.#overlayElements?.clear();
|
|
2154
2835
|
this.#overlayElements = renderCtx.elements;
|
|
2155
2836
|
this.#updateSelectionActionPopover();
|
|
2837
|
+
if (selectionsChanged) this.#scheduleEditPrediction();
|
|
2838
|
+
}
|
|
2839
|
+
#renderCarets() {
|
|
2840
|
+
const carets = this.#carets;
|
|
2841
|
+
const renderCaret = this.#options.renderCaret;
|
|
2842
|
+
const overlayElement = this.#overlayElement;
|
|
2843
|
+
this.#caretHighlightElements?.forEach((element) => element.remove());
|
|
2844
|
+
this.#caretHighlightElements = void 0;
|
|
2845
|
+
if (carets === void 0 || renderCaret === void 0 || overlayElement === void 0) {
|
|
2846
|
+
this.#caretElements?.forEach((element) => element.remove());
|
|
2847
|
+
this.#caretElements = void 0;
|
|
2848
|
+
return;
|
|
2849
|
+
}
|
|
2850
|
+
const elements = this.#caretElements ??= /* @__PURE__ */ new Map();
|
|
2851
|
+
for (const [trackedCaret, element] of elements) if (!this.#isLineVisible(trackedCaret.caret.focus.line)) {
|
|
2852
|
+
element.remove();
|
|
2853
|
+
elements.delete(trackedCaret);
|
|
2854
|
+
}
|
|
2855
|
+
const fragment = document.createDocumentFragment();
|
|
2856
|
+
const highlightElements = [];
|
|
2857
|
+
for (const trackedCaret of carets) {
|
|
2858
|
+
const { caret } = trackedCaret;
|
|
2859
|
+
const { line, character } = caret.focus;
|
|
2860
|
+
if (trackedCaret.anchorOffset !== trackedCaret.focusOffset) {
|
|
2861
|
+
const highlightContext = {
|
|
2862
|
+
fragment,
|
|
2863
|
+
elements: /* @__PURE__ */ new Map()
|
|
2864
|
+
};
|
|
2865
|
+
this.#renderSelection(highlightContext, "caretHighlight", trackedCaret.anchorOffset < trackedCaret.focusOffset ? {
|
|
2866
|
+
start: caret.anchor,
|
|
2867
|
+
end: caret.focus
|
|
2868
|
+
} : {
|
|
2869
|
+
start: caret.focus,
|
|
2870
|
+
end: caret.anchor
|
|
2871
|
+
}, void 0, caret.focus);
|
|
2872
|
+
for (const highlightElement of highlightContext.elements.values()) {
|
|
2873
|
+
highlightElement.style.setProperty("--diffs-caret-highlight-bg", `color-mix(in srgb, ${caret.metadata.color} 32%, transparent)`);
|
|
2874
|
+
highlightElements.push(highlightElement);
|
|
2875
|
+
}
|
|
2876
|
+
}
|
|
2877
|
+
if (!this.#isLineVisible(line)) continue;
|
|
2878
|
+
let element = elements.get(trackedCaret);
|
|
2879
|
+
if (element === void 0) {
|
|
2880
|
+
element = h("div", {
|
|
2881
|
+
dataset: "remoteCaret",
|
|
2882
|
+
children: [renderCaret(caret)]
|
|
2883
|
+
}, fragment);
|
|
2884
|
+
elements.set(trackedCaret, element);
|
|
2885
|
+
}
|
|
2886
|
+
const [left, wrapLine] = this.#getCharX(line, character);
|
|
2887
|
+
const top = this.#getLineY(line) + wrapLine * this.#metrics.lineHeight;
|
|
2888
|
+
element.style.transform = `translateX(${left}px) translateY(${top}px)`;
|
|
2889
|
+
}
|
|
2890
|
+
this.#caretHighlightElements = highlightElements;
|
|
2891
|
+
overlayElement.appendChild(fragment);
|
|
2156
2892
|
}
|
|
2157
|
-
#renderSelection(renderCtx, type, range, extraDataset) {
|
|
2158
|
-
if (this.#
|
|
2893
|
+
#renderSelection(renderCtx, type, range, extraDataset, connectedCaret) {
|
|
2894
|
+
if (this.#editSession?.document == null) return;
|
|
2159
2895
|
const { start, end } = range;
|
|
2160
2896
|
let firstLine = start.line;
|
|
2161
2897
|
let endLine = end.line + 1;
|
|
@@ -2168,12 +2904,18 @@ var Editor = class {
|
|
|
2168
2904
|
if (!this.#isLineVisible(line)) continue;
|
|
2169
2905
|
const isLastLine = line === end.line;
|
|
2170
2906
|
const startChar = line === start.line ? start.character : 0;
|
|
2171
|
-
const endChar = isLastLine ? end.character : this.#
|
|
2907
|
+
const endChar = isLastLine ? end.character : this.#editSession?.document.getLineLength(line);
|
|
2908
|
+
if (startChar === endChar && (type === "editPredictionDeletion" || type === "editPredictionReplacement")) {
|
|
2909
|
+
if (isLastLine && line !== start.line) continue;
|
|
2910
|
+
const [left, wrapLine] = this.#getCharX(line, startChar);
|
|
2911
|
+
this.#renderSelectionBlock(renderCtx, type, line, wrapLine, left, this.#metrics.ch, extraDataset);
|
|
2912
|
+
continue;
|
|
2913
|
+
}
|
|
2172
2914
|
if (this.#isWrap) {
|
|
2173
2915
|
const contentWidth = this.#getContentWidth();
|
|
2174
|
-
const lineText = this.#
|
|
2916
|
+
const lineText = this.#editSession?.document.getLineText(line);
|
|
2175
2917
|
if (2 * this.#metrics.ch + this.#metrics.measureTextWidth(lineText) > contentWidth) {
|
|
2176
|
-
this.#renderWrappedSelection(renderCtx, line, lineText, startChar, endChar, isLastLine, type, extraDataset);
|
|
2918
|
+
this.#renderWrappedSelection(renderCtx, line, lineText, startChar, endChar, isLastLine, type, extraDataset, connectedCaret);
|
|
2177
2919
|
continue;
|
|
2178
2920
|
}
|
|
2179
2921
|
}
|
|
@@ -2185,10 +2927,13 @@ var Editor = class {
|
|
|
2185
2927
|
if (!isLastLine && type === "selection") paddingEnd = this.#metrics.ch;
|
|
2186
2928
|
if (startChar === endChar) width = paddingEnd;
|
|
2187
2929
|
else width = this.#getCharX(line, endChar)[0] - left + paddingEnd;
|
|
2188
|
-
this.#renderSelectionBlock(renderCtx, type, line, 0, left, width, extraDataset
|
|
2930
|
+
this.#renderSelectionBlock(renderCtx, type, line, 0, left, width, extraDataset, {
|
|
2931
|
+
start: connectedCaret?.line === start.line && connectedCaret.character === start.character && line === start.line,
|
|
2932
|
+
end: connectedCaret?.line === end.line && connectedCaret.character === end.character && line === end.line
|
|
2933
|
+
});
|
|
2189
2934
|
}
|
|
2190
2935
|
}
|
|
2191
|
-
#renderWrappedSelection(renderCtx, line, lineText, startChar, endChar, isLastLine, type, extraDataset) {
|
|
2936
|
+
#renderWrappedSelection(renderCtx, line, lineText, startChar, endChar, isLastLine, type, extraDataset, connectedCaret) {
|
|
2192
2937
|
const wrapOffsets = this.#wrapLineTextOrWholeLine(line);
|
|
2193
2938
|
const segmentCount = wrapOffsets.length - 1;
|
|
2194
2939
|
const offsetLeft = this.#getGutterWidth() + this.#metrics.ch + (this.#activeContentOffset?.left ?? 0);
|
|
@@ -2203,7 +2948,10 @@ var Editor = class {
|
|
|
2203
2948
|
let paddingEnd = 0;
|
|
2204
2949
|
if (!isLastLine && wrapLine === segmentCount - 1 && type === "selection") paddingEnd = this.#metrics.ch;
|
|
2205
2950
|
const segmentWidth = wrapStartChar === wrapEndChar ? paddingEnd : this.#segmentTextWidth(lineText, segmentStart, wrapEndChar) - segmentStartWidth + paddingEnd;
|
|
2206
|
-
this.#renderSelectionBlock(renderCtx, type, line, wrapLine, segmentLeft, segmentWidth, extraDataset
|
|
2951
|
+
this.#renderSelectionBlock(renderCtx, type, line, wrapLine, segmentLeft, segmentWidth, extraDataset, {
|
|
2952
|
+
start: connectedCaret?.line === line && connectedCaret.character === startChar && wrapStartChar === startChar,
|
|
2953
|
+
end: connectedCaret?.line === line && connectedCaret.character === endChar && wrapEndChar === endChar
|
|
2954
|
+
});
|
|
2207
2955
|
}
|
|
2208
2956
|
}
|
|
2209
2957
|
#segmentTextWidth(lineText, segmentStart, character) {
|
|
@@ -2212,13 +2960,13 @@ var Editor = class {
|
|
|
2212
2960
|
const asciiColumns = getExpandedAsciiTextColumns(segmentText, this.#metrics.tabSize);
|
|
2213
2961
|
return asciiColumns !== -1 ? asciiColumns * this.#metrics.ch : this.#metrics.measureTextWidth(segmentText);
|
|
2214
2962
|
}
|
|
2215
|
-
#renderSelectionBlock(renderCtx, type, line, wrapLine, left, width, extraDataset) {
|
|
2963
|
+
#renderSelectionBlock(renderCtx, type, line, wrapLine, left, width, extraDataset, connectedCaretEdge) {
|
|
2216
2964
|
if (width === 0) return;
|
|
2217
2965
|
const { ch, lineHeight } = this.#metrics;
|
|
2218
2966
|
const y = this.#getLineY(line) + wrapLine * lineHeight;
|
|
2219
2967
|
const cacheKey = `${type}-${line}/${wrapLine}-${left}-${width} ${extraDataset ?? ""}`;
|
|
2220
2968
|
const overlayEls = this.#overlayElements;
|
|
2221
|
-
const rounded = (this.#options.roundedSelection ?? true) && type === "selection";
|
|
2969
|
+
const rounded = (this.#options.roundedSelection ?? true) && (type === "selection" || type === "caretHighlight");
|
|
2222
2970
|
const addRoundedCorner = (line, wrapLine, left, radius) => {
|
|
2223
2971
|
const top = this.#getLineY(line) + wrapLine * lineHeight;
|
|
2224
2972
|
const lineElement = this.#getLineElement(line);
|
|
@@ -2248,7 +2996,7 @@ var Editor = class {
|
|
|
2248
2996
|
cornerEl.style.cssText = css;
|
|
2249
2997
|
overlayEls.delete(cacheKey);
|
|
2250
2998
|
} else cornerEl = h("div", {
|
|
2251
|
-
dataset: "selectionRange",
|
|
2999
|
+
dataset: type === "caretHighlight" ? "caretHighlightRange" : "selectionRange",
|
|
2252
3000
|
style: { cssText: css },
|
|
2253
3001
|
children: [h("div", { dataset })]
|
|
2254
3002
|
}, renderCtx.fragment);
|
|
@@ -2293,6 +3041,14 @@ var Editor = class {
|
|
|
2293
3041
|
dataset.rbl = "";
|
|
2294
3042
|
dataset.rbr = "";
|
|
2295
3043
|
}
|
|
3044
|
+
if (connectedCaretEdge?.start === true) {
|
|
3045
|
+
delete dataset.rtl;
|
|
3046
|
+
delete dataset.rbl;
|
|
3047
|
+
}
|
|
3048
|
+
if (connectedCaretEdge?.end === true) {
|
|
3049
|
+
delete dataset.rtr;
|
|
3050
|
+
delete dataset.rbr;
|
|
3051
|
+
}
|
|
2296
3052
|
};
|
|
2297
3053
|
let rangeEl = renderCtx.elements.get(cacheKey);
|
|
2298
3054
|
if (rangeEl !== void 0) {
|
|
@@ -2305,6 +3061,10 @@ var Editor = class {
|
|
|
2305
3061
|
} else rangeEl = h("div", { dataset: extraDataset ? [type + "Range", extraDataset] : type + "Range" }, renderCtx.fragment);
|
|
2306
3062
|
rangeEl.style.width = `${width}px`;
|
|
2307
3063
|
rangeEl.style.transform = `translateX(${left}px) translateY(${y}px)`;
|
|
3064
|
+
if (type === "editPredictionInsertion" || type === "editPredictionReplacement") {
|
|
3065
|
+
const lineElement = this.#getLineElement(line);
|
|
3066
|
+
if (lineElement !== void 0) rangeEl.style.setProperty("--diffs-edit-prediction-bg", getComputedStyle(lineElement).getPropertyValue("--diffs-line-bg"));
|
|
3067
|
+
} else rangeEl.style.removeProperty("--diffs-edit-prediction-bg");
|
|
2308
3068
|
if (rounded) addRadiusStyle(rangeEl);
|
|
2309
3069
|
renderCtx.elements.set(cacheKey, rangeEl);
|
|
2310
3070
|
}
|
|
@@ -2327,7 +3087,7 @@ var Editor = class {
|
|
|
2327
3087
|
#updateSelectionActionPopover() {
|
|
2328
3088
|
const primarySelection = this.#selections?.at(-1);
|
|
2329
3089
|
const overlayElement = this.#overlayElement;
|
|
2330
|
-
const textDocument = this.#
|
|
3090
|
+
const textDocument = this.#editSession?.document;
|
|
2331
3091
|
const renderSelectionAction = this.#options.renderSelectionAction;
|
|
2332
3092
|
const cleanup = () => {
|
|
2333
3093
|
this.#selectionAction?.cleanup();
|
|
@@ -2351,7 +3111,7 @@ var Editor = class {
|
|
|
2351
3111
|
return getActiveSelection();
|
|
2352
3112
|
},
|
|
2353
3113
|
applyEdits: (edits) => this.applyEdits(edits),
|
|
2354
|
-
getSelectionText: () => this.#
|
|
3114
|
+
getSelectionText: () => this.#editSession?.document?.getText(getActiveSelection()) ?? "",
|
|
2355
3115
|
replaceSelectionText: (text) => {
|
|
2356
3116
|
this.#replaceSelectionText(text, [getActiveSelection()]);
|
|
2357
3117
|
},
|
|
@@ -2421,7 +3181,7 @@ var Editor = class {
|
|
|
2421
3181
|
}
|
|
2422
3182
|
#renderSearchPanel(mode) {
|
|
2423
3183
|
this.#searchPanel?.cleanup();
|
|
2424
|
-
const textDocument = this.#
|
|
3184
|
+
const textDocument = this.#editSession?.document;
|
|
2425
3185
|
const preElement = this.#fileContainer?.shadowRoot?.querySelector("pre");
|
|
2426
3186
|
const selections = this.#selections;
|
|
2427
3187
|
if (textDocument === void 0 || preElement == null) return;
|
|
@@ -2504,13 +3264,13 @@ var Editor = class {
|
|
|
2504
3264
|
this.#retainSearchPanelFocus = false;
|
|
2505
3265
|
}
|
|
2506
3266
|
#getSelectionText() {
|
|
2507
|
-
const textDocument = this.#
|
|
3267
|
+
const textDocument = this.#editSession?.document;
|
|
2508
3268
|
const selections = this.#selections;
|
|
2509
3269
|
if (textDocument === void 0 || selections === void 0) return "";
|
|
2510
3270
|
return getSelectionText(textDocument, selections);
|
|
2511
3271
|
}
|
|
2512
3272
|
#getSelectionClipboardTexts() {
|
|
2513
|
-
const textDocument = this.#
|
|
3273
|
+
const textDocument = this.#editSession?.document;
|
|
2514
3274
|
const selections = this.#selections;
|
|
2515
3275
|
if (textDocument === void 0 || selections === void 0) return [];
|
|
2516
3276
|
return getSelectionClipboardTexts(textDocument, selections);
|
|
@@ -2522,7 +3282,7 @@ var Editor = class {
|
|
|
2522
3282
|
if (selectionTexts.length > 1) clipboardData.setData(MULTI_SELECTION_CLIPBOARD_TYPE, JSON.stringify(selectionTexts));
|
|
2523
3283
|
}
|
|
2524
3284
|
#cutSelectionText() {
|
|
2525
|
-
const textDocument = this.#
|
|
3285
|
+
const textDocument = this.#editSession?.document;
|
|
2526
3286
|
const selections = this.#selections;
|
|
2527
3287
|
if (textDocument === void 0 || selections === void 0 || selections.length === 0) return "";
|
|
2528
3288
|
if (selections.some((selection) => isCollapsedSelection(selection))) {
|
|
@@ -2535,7 +3295,7 @@ var Editor = class {
|
|
|
2535
3295
|
return text;
|
|
2536
3296
|
}
|
|
2537
3297
|
#applySelectionCutEdits(edits, nextSelectionOffsets) {
|
|
2538
|
-
const textDocument = this.#
|
|
3298
|
+
const textDocument = this.#editSession?.document;
|
|
2539
3299
|
const selections = this.#selections;
|
|
2540
3300
|
if (textDocument === void 0 || selections === void 0 || edits.length === 0) return;
|
|
2541
3301
|
const change = textDocument.applyResolvedEdits(edits, true, selections, void 0, true);
|
|
@@ -2553,7 +3313,7 @@ var Editor = class {
|
|
|
2553
3313
|
}
|
|
2554
3314
|
#replaceSelectionText(text, selections = this.#selections, undoBoundary = false, textOrder = "selection") {
|
|
2555
3315
|
if (selections === void 0) return;
|
|
2556
|
-
const textDocument = this.#
|
|
3316
|
+
const textDocument = this.#editSession?.document;
|
|
2557
3317
|
const primarySelection = selections.at(-1);
|
|
2558
3318
|
if (textDocument === void 0 || primarySelection === void 0) return;
|
|
2559
3319
|
const { nextSelections, change } = Array.isArray(text) && text.length === selections.length ? applyTextReplaceToSelections(textDocument, selections, text, this.#lineAnnotations, undoBoundary, textOrder) : applyTextChangeToSelections(textDocument, selections, {
|
|
@@ -2565,14 +3325,14 @@ var Editor = class {
|
|
|
2565
3325
|
}
|
|
2566
3326
|
#deleteSelectionText(forward = false) {
|
|
2567
3327
|
const selections = this.#selections;
|
|
2568
|
-
const textDocument = this.#
|
|
3328
|
+
const textDocument = this.#editSession?.document;
|
|
2569
3329
|
if (selections === void 0 || textDocument === void 0) return;
|
|
2570
3330
|
const { nextSelections, change } = applyDeleteCharacterToSelections(textDocument, selections, forward, this.#lineAnnotations, this.#metrics.tabSize);
|
|
2571
3331
|
if (change !== void 0) this.#applyChange(change, nextSelections, this.#applyChangeToLineAnnotations(change));
|
|
2572
3332
|
}
|
|
2573
3333
|
#deleteSoftLineBackward() {
|
|
2574
3334
|
const selections = this.#selections;
|
|
2575
|
-
const textDocument = this.#
|
|
3335
|
+
const textDocument = this.#editSession?.document;
|
|
2576
3336
|
if (selections === void 0 || textDocument === void 0) return;
|
|
2577
3337
|
const { nextSelections, change } = applyDeleteSoftLineBackwardToSelections(textDocument, selections, this.#isWrap ? (line, character) => {
|
|
2578
3338
|
const wrapOffsets = this.#wrapLineTextOrWholeLine(line);
|
|
@@ -2587,35 +3347,33 @@ var Editor = class {
|
|
|
2587
3347
|
}
|
|
2588
3348
|
#deleteWordBackward() {
|
|
2589
3349
|
const selections = this.#selections;
|
|
2590
|
-
const textDocument = this.#
|
|
3350
|
+
const textDocument = this.#editSession?.document;
|
|
2591
3351
|
if (selections === void 0 || textDocument === void 0) return;
|
|
2592
3352
|
const { nextSelections, change } = applyDeleteWordBackwardToSelections(textDocument, selections, this.#lineAnnotations);
|
|
2593
3353
|
if (change !== void 0) this.#applyChange(change, nextSelections, this.#applyChangeToLineAnnotations(change));
|
|
2594
3354
|
}
|
|
2595
3355
|
#deleteHardLineForward() {
|
|
2596
3356
|
const selections = this.#selections;
|
|
2597
|
-
const textDocument = this.#
|
|
3357
|
+
const textDocument = this.#editSession?.document;
|
|
2598
3358
|
if (selections === void 0 || textDocument === void 0) return;
|
|
2599
3359
|
const { nextSelections, change } = applyDeleteHardLineForwardToSelections(textDocument, selections, this.#lineAnnotations);
|
|
2600
3360
|
if (change !== void 0) this.#applyChange(change, nextSelections, this.#applyChangeToLineAnnotations(change));
|
|
2601
3361
|
}
|
|
2602
3362
|
#insertTranspose() {
|
|
2603
3363
|
const selections = this.#selections;
|
|
2604
|
-
const textDocument = this.#
|
|
3364
|
+
const textDocument = this.#editSession?.document;
|
|
2605
3365
|
if (selections === void 0 || textDocument === void 0) return;
|
|
2606
3366
|
const { nextSelections, change } = applyTransposeToSelections(textDocument, selections, this.#lineAnnotations);
|
|
2607
3367
|
if (change !== void 0) this.#applyChange(change, nextSelections, this.#applyChangeToLineAnnotations(change));
|
|
2608
3368
|
}
|
|
2609
3369
|
#applyChange(change, newSelections, newLineAnnotations, options) {
|
|
2610
|
-
|
|
2611
|
-
const
|
|
2612
|
-
if (
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
lineAnnotations
|
|
2618
|
-
});
|
|
3370
|
+
if (this.#editPrediction != null) this.#cancelEditPrediction(true);
|
|
3371
|
+
const textDocument = this.#editSession?.document;
|
|
3372
|
+
if (textDocument !== void 0 && this.#carets !== void 0) for (const trackedCaret of this.#carets) {
|
|
3373
|
+
trackedCaret.anchorOffset = remapOffsetThroughEdits(trackedCaret.anchorOffset, change.changes);
|
|
3374
|
+
trackedCaret.focusOffset = remapOffsetThroughEdits(trackedCaret.focusOffset, change.changes);
|
|
3375
|
+
trackedCaret.caret.anchor = textDocument.positionAt(trackedCaret.anchorOffset);
|
|
3376
|
+
trackedCaret.caret.focus = textDocument.positionAt(trackedCaret.focusOffset);
|
|
2619
3377
|
}
|
|
2620
3378
|
if (change.lineDelta !== 0 || this.#isWrap) {
|
|
2621
3379
|
for (const line of this.#lineYCache.keys()) if (line >= change.startLine) this.#lineYCache.delete(line);
|
|
@@ -2644,9 +3402,13 @@ var Editor = class {
|
|
|
2644
3402
|
}
|
|
2645
3403
|
}
|
|
2646
3404
|
this.#rerender(change, newLineAnnotations, renderRange, shouldUpdateBuffer);
|
|
3405
|
+
if (newSelections != null) this.#updateSelections(newSelections);
|
|
3406
|
+
this.#checkpointEditSessionState();
|
|
3407
|
+
this.#recordEditPredictionHistory(change, options?.editSource ?? "user");
|
|
3408
|
+
this.#scheduleEditPrediction();
|
|
3409
|
+
this.#emitChange(change.changes, newLineAnnotations ?? this.#lineAnnotations);
|
|
2647
3410
|
if (options?.skipSearchRefresh !== true && this.#searchPanel !== void 0 && this.#matches !== void 0) this.#searchPanel.updateMatches({ syncSelection: false });
|
|
2648
|
-
if (newSelections
|
|
2649
|
-
this.#updateSelections(newSelections);
|
|
3411
|
+
if (newSelections != null) {
|
|
2650
3412
|
if (options?.skipFocus !== true) {
|
|
2651
3413
|
const revealTarget = newSelections.at(-1);
|
|
2652
3414
|
if (revealTarget !== void 0) this.#revealLineIfCollapsed(getCaretPosition(revealTarget).line);
|
|
@@ -2664,11 +3426,17 @@ var Editor = class {
|
|
|
2664
3426
|
}
|
|
2665
3427
|
}
|
|
2666
3428
|
}
|
|
3429
|
+
#emitChange(changes, lineAnnotations) {
|
|
3430
|
+
const file = this.getFile();
|
|
3431
|
+
const publishChange = this.#publishChange;
|
|
3432
|
+
if (file == null || publishChange == null) return;
|
|
3433
|
+
publishChange(changes, file, lineAnnotations);
|
|
3434
|
+
}
|
|
2667
3435
|
#applyChangeToLineAnnotations(change) {
|
|
2668
|
-
if (this.#lineAnnotations
|
|
3436
|
+
if (this.#lineAnnotations != null) {
|
|
2669
3437
|
const nextLineAnnotations = applyDocumentChangeToLineAnnotations(change, this.#lineAnnotations);
|
|
2670
|
-
if (nextLineAnnotations
|
|
2671
|
-
this.#
|
|
3438
|
+
if (nextLineAnnotations != null) {
|
|
3439
|
+
this.#editSession?.document?.setLastUndoLineAnnotations(this.#lineAnnotations, nextLineAnnotations);
|
|
2672
3440
|
return nextLineAnnotations;
|
|
2673
3441
|
}
|
|
2674
3442
|
}
|
|
@@ -2689,11 +3457,15 @@ var Editor = class {
|
|
|
2689
3457
|
}
|
|
2690
3458
|
return ranges;
|
|
2691
3459
|
}
|
|
3460
|
+
#isLineInRenderRange(line) {
|
|
3461
|
+
const renderRange = this.#renderRange;
|
|
3462
|
+
return renderRange == null || line >= renderRange.startingLine && line < renderRange.startingLine + renderRange.totalLines;
|
|
3463
|
+
}
|
|
2692
3464
|
#getLineElement(line) {
|
|
2693
3465
|
let lineElement = this.#lineElementsCache.get(line);
|
|
2694
3466
|
if (lineElement !== void 0) return lineElement ?? void 0;
|
|
2695
3467
|
const renderRange = this.#renderRange;
|
|
2696
|
-
if (
|
|
3468
|
+
if (!this.#isLineInRenderRange(line)) return;
|
|
2697
3469
|
const contentElement = this.#contentElement;
|
|
2698
3470
|
if (contentElement === void 0) return;
|
|
2699
3471
|
if (renderRange !== void 0) {
|
|
@@ -2744,7 +3516,7 @@ var Editor = class {
|
|
|
2744
3516
|
}
|
|
2745
3517
|
#getCharX(line, char) {
|
|
2746
3518
|
if (this.#lastAccessedCharX !== void 0 && this.#lastAccessedCharX[0] === line && this.#lastAccessedCharX[1] === char) return [this.#lastAccessedCharX[2], this.#lastAccessedCharX[3]];
|
|
2747
|
-
const lineText = this.#
|
|
3519
|
+
const lineText = this.#editSession?.document?.getLineText(line);
|
|
2748
3520
|
const offsetLeft = this.#getGutterWidth() + this.#metrics.ch;
|
|
2749
3521
|
if (lineText === void 0 || lineText.length === 0 || char <= 0) return [offsetLeft + (this.#activeContentOffset?.left ?? 0), 0];
|
|
2750
3522
|
const boundedCharacter = snapTextOffsetToUnicodeBoundary(lineText, Math.min(char, lineText.length));
|
|
@@ -2790,7 +3562,7 @@ var Editor = class {
|
|
|
2790
3562
|
const cachedOffsets = this.#wrapLineOffsetsCache.get(line);
|
|
2791
3563
|
if (cachedOffsets !== void 0) return cachedOffsets;
|
|
2792
3564
|
if (this.#wrapLineOffsetsCache.size >= MAX_WRAP_OFFSETS_CACHE_LINES) this.#wrapLineOffsetsCache.clear();
|
|
2793
|
-
const lineText = this.#
|
|
3565
|
+
const lineText = this.#editSession?.document?.getLineText(line);
|
|
2794
3566
|
if (lineText === void 0 || lineText.length === 0) {
|
|
2795
3567
|
const offsets = new Uint32Array([0]);
|
|
2796
3568
|
this.#wrapLineOffsetsCache.set(line, offsets);
|
|
@@ -2828,7 +3600,8 @@ var Editor = class {
|
|
|
2828
3600
|
const measureGrapheme = (index) => {
|
|
2829
3601
|
range.setStart(textNode, graphemeStart(index));
|
|
2830
3602
|
range.setEnd(textNode, graphemeStart(index + 1));
|
|
2831
|
-
|
|
3603
|
+
const clientRects = range.getClientRects();
|
|
3604
|
+
return clientRects.item(clientRects.length - 1) ?? range.getBoundingClientRect();
|
|
2832
3605
|
};
|
|
2833
3606
|
starts.push(0);
|
|
2834
3607
|
let lastTop = measureGrapheme(0).top;
|
|
@@ -2860,7 +3633,7 @@ var Editor = class {
|
|
|
2860
3633
|
#wrapLineTextOrWholeLine(line) {
|
|
2861
3634
|
const offsets = this.#wrapLineText(line);
|
|
2862
3635
|
if (offsets !== void 0) return offsets;
|
|
2863
|
-
const length = this.#
|
|
3636
|
+
const length = this.#editSession?.document?.getLineText(line)?.length ?? 0;
|
|
2864
3637
|
return Uint32Array.of(0, length);
|
|
2865
3638
|
}
|
|
2866
3639
|
#rangeBelongsToEditor({ startContainer, endContainer }) {
|
|
@@ -2869,11 +3642,31 @@ var Editor = class {
|
|
|
2869
3642
|
return contentEl.contains(startContainer) && contentEl.contains(endContainer);
|
|
2870
3643
|
}
|
|
2871
3644
|
#isLineVisible(line) {
|
|
2872
|
-
const lineCount = this.#
|
|
3645
|
+
const lineCount = this.#editSession?.document?.lineCount ?? 0;
|
|
2873
3646
|
if (line < 0 || line >= lineCount) return false;
|
|
2874
3647
|
return this.#getLineElement(line) !== void 0;
|
|
2875
3648
|
}
|
|
2876
3649
|
};
|
|
3650
|
+
function getEditSession({ type, editStateKey, owner, initialState, previousSession }) {
|
|
3651
|
+
if (initialState != null && initialState.type !== type) throw new TypeError(`Editor: initialState: a ${initialState.type} state cannot initialize a ${type} editor`);
|
|
3652
|
+
const initialSession = initialState;
|
|
3653
|
+
if (editStateKey != null) return EditStateManager.activate(type, editStateKey, owner, initialSession);
|
|
3654
|
+
if (initialSession != null) return initialSession;
|
|
3655
|
+
if (previousSession != null) return previousSession;
|
|
3656
|
+
return type === "file" ? { type: "file" } : { type: "file-diff" };
|
|
3657
|
+
}
|
|
3658
|
+
function gridTrackSpan(child) {
|
|
3659
|
+
if (!(child instanceof HTMLElement)) return 1;
|
|
3660
|
+
return Number(child.dataset.bufferSize ?? 1);
|
|
3661
|
+
}
|
|
3662
|
+
function isValidEditPredictionPosition(document, position) {
|
|
3663
|
+
return position !== void 0 && Number.isInteger(position.line) && Number.isInteger(position.character) && position.line >= 0 && position.line < document.lineCount && position.character >= 0 && position.character <= document.getLineLength(position.line);
|
|
3664
|
+
}
|
|
3665
|
+
function splitsSurrogatePair(text, offset) {
|
|
3666
|
+
const previous = text.charCodeAt(offset - 1);
|
|
3667
|
+
const next = text.charCodeAt(offset);
|
|
3668
|
+
return offset > 0 && offset < text.length && previous >= 55296 && previous <= 56319 && next >= 56320 && next <= 57343;
|
|
3669
|
+
}
|
|
2877
3670
|
//#endregion
|
|
2878
3671
|
export { Editor };
|
|
2879
3672
|
|