@pierre/diffs 1.3.6 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/CodeView.d.ts +115 -68
- package/dist/components/CodeView.d.ts.map +1 -1
- package/dist/components/CodeView.js +189 -59
- package/dist/components/CodeView.js.map +1 -1
- package/dist/components/File.d.ts +79 -15
- package/dist/components/File.d.ts.map +1 -1
- package/dist/components/File.js +244 -66
- package/dist/components/File.js.map +1 -1
- package/dist/components/FileDiff.d.ts +101 -21
- package/dist/components/FileDiff.d.ts.map +1 -1
- package/dist/components/FileDiff.js +432 -102
- package/dist/components/FileDiff.js.map +1 -1
- package/dist/components/FileStream.js +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 +17 -7
- package/dist/components/VirtualizedFile.d.ts.map +1 -1
- package/dist/components/VirtualizedFile.js +142 -53
- package/dist/components/VirtualizedFile.js.map +1 -1
- package/dist/components/VirtualizedFileDiff.d.ts +15 -8
- package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
- package/dist/components/VirtualizedFileDiff.js +186 -96
- 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 +1108 -384
- 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.js +1 -1
- package/dist/editor/searchPanel.js.map +1 -1
- package/dist/editor/selection.d.ts +32 -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.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/highlighter/shared_highlighter.d.ts +6 -2
- package/dist/highlighter/shared_highlighter.d.ts.map +1 -1
- package/dist/highlighter/shared_highlighter.js +7 -3
- package/dist/highlighter/shared_highlighter.js.map +1 -1
- package/dist/highlighter/themes/areThemesAttached.js +1 -1
- package/dist/index.d.ts +8 -6
- package/dist/index.js +22 -21
- 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 -109
- 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 +141 -67
- 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 +44 -6
- 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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editPrediction.js","names":[],"sources":["../../src/editor/editPrediction.ts"],"sourcesContent":["import type { TextDocumentChangeTransaction } from './textDocumentChangeTransaction';\nimport type { Position, ResolvedTextEdit, TextEdit } from './types';\n\nexport interface EditPredictRequest {\n /** Current file name/path as supplied to the File or FileDiff component. */\n readonly path: string;\n /** Document version. */\n readonly version: number;\n /** Document end-of-line sequence. */\n readonly eol: '\\n' | '\\r\\n' | '\\r';\n /** Bounded slice of the file around the cursor (not the whole file). */\n readonly excerptText: string;\n /** Zero-based document line where the excerpt starts. */\n readonly excerptStartLine: number;\n /** UTF-16 cursor offset relative to `excerptText`. */\n readonly cursorOffsetInExcerpt: number;\n /** Half-open UTF-16 range within `excerptText` that may be edited. */\n readonly editableRange: { readonly start: number; readonly end: number };\n /** Chronological, bounded edit history for this document. */\n readonly editHistory: ReadonlyArray<{\n /** Edit in unified-diff format. */\n readonly diff: string;\n /** Edit source. */\n readonly source: 'user' | 'prediction';\n }>;\n}\n\nexport interface EditPredictContext {\n /** Aborted when the document or cursor changes. */\n readonly signal: AbortSignal;\n}\n\nexport interface EditPredictResponse {\n /** Non-overlapping edits using absolute document positions. */\n readonly edits: readonly TextEdit[];\n /** Absolute post-edit cursor position. */\n readonly newCursor: Position;\n}\n\nexport interface EditPredictProvider {\n /** Predicts the next edit for the given request. */\n predict: (\n request: EditPredictRequest,\n context: EditPredictContext\n ) => Promise<EditPredictResponse>;\n}\n\nexport interface EditPredictionHistoryRecord {\n readonly path: string;\n readonly hunk: string;\n readonly start: number;\n readonly end: number;\n readonly at: number;\n readonly source: 'user' | 'prediction';\n readonly fragment?: EditPredictionHistoryFragment;\n}\n\ninterface EditPredictionDocument {\n readonly version: number;\n readonly eol: '\\n' | '\\r\\n' | '\\r';\n readonly lineCount: number;\n positionAt(offset: number): Position;\n positionsAt(offsets: readonly number[]): Position[];\n offsetAt(position: Position): number;\n getLineText(line: number): string;\n getLineLength(line: number): number;\n getTextSlice(start: number, end: number): string;\n charAt(offset: number): string;\n}\n\ninterface EditPredictionHistoryFragment {\n readonly baseText: string;\n readonly currentText: string;\n readonly currentStart: number;\n readonly currentEnd: number;\n readonly startLine: number;\n}\n\ninterface EditPredictionTransactionFragment {\n readonly beforeText: string;\n readonly afterText: string;\n readonly startOffset: number;\n readonly startLine: number;\n readonly bounds: LineDiffBounds;\n}\n\ninterface LineDiffBounds {\n readonly oldLineCount: number;\n readonly newLineCount: number;\n readonly prefixLines: number;\n readonly suffixLines: number;\n}\n\nconst EDITABLE_TOKENS = 350;\nconst CONTEXT_TOKENS = 150;\nconst MAX_EDITABLE_TOKENS = 512;\nconst MAX_CONTEXT_TOKENS = 662;\nconst MAX_REQUEST_BYTES = 128 * 1024;\nconst MAX_HISTORY_ENTRIES = 10;\nconst MAX_CAPTURE_BYTES = 6144;\nconst COALESCE_MS = 1000;\nconst COALESCE_LINES = 8;\nconst DIFF_CONTEXT_LINES = 3;\nconst CAPTURE_CONTEXT_LINES = DIFF_CONTEXT_LINES + COALESCE_LINES;\nconst CAPTURE_CONTEXT_OPTIONS = [\n CAPTURE_CONTEXT_LINES,\n DIFF_CONTEXT_LINES,\n] as const;\nconst textEncoder = new TextEncoder();\n\nfunction lineStarts(text: string): number[] {\n const starts = [0];\n for (let index = 0; index < text.length; index++) {\n if (text.charCodeAt(index) === 13 && text.charCodeAt(index + 1) === 10) {\n index++;\n }\n if (text.charCodeAt(index) === 10 || text.charCodeAt(index) === 13) {\n starts.push(index + 1);\n }\n }\n return starts;\n}\n\n// A line start at text.length is the boundary after a trailing terminator,\n// not an additional document line for unified-diff counts.\nfunction diffLineCount(text: string, starts: readonly number[]): number {\n if (text.length === 0) {\n return 0;\n }\n return starts.at(-1) === text.length ? starts.length - 1 : starts.length;\n}\n\nfunction lineEnd(\n text: string,\n starts: readonly number[],\n line: number\n): number {\n const next = starts[line + 1];\n return next === undefined\n ? text.length\n : next -\n (text.charCodeAt(next - 1) === 10 && text.charCodeAt(next - 2) === 13\n ? 2\n : 1);\n}\n\nfunction linesEqual(\n left: string,\n leftStarts: readonly number[],\n leftLine: number,\n right: string,\n rightStarts: readonly number[],\n rightLine: number\n): boolean {\n const leftStart = leftStarts[leftLine];\n const rightStart = rightStarts[rightLine];\n const length = lineEnd(left, leftStarts, leftLine) - leftStart;\n if (length !== lineEnd(right, rightStarts, rightLine) - rightStart) {\n return false;\n }\n for (let index = 0; index < length; index++) {\n if (\n left.charCodeAt(leftStart + index) !==\n right.charCodeAt(rightStart + index)\n ) {\n return false;\n }\n }\n return true;\n}\n\nfunction lineDiffBounds(\n oldText: string,\n oldStarts: readonly number[],\n newText: string,\n newStarts: readonly number[]\n): LineDiffBounds {\n const oldLineCount = diffLineCount(oldText, oldStarts);\n const newLineCount = diffLineCount(newText, newStarts);\n let prefixLines = 0;\n while (prefixLines < oldLineCount && prefixLines < newLineCount) {\n if (\n !linesEqual(\n oldText,\n oldStarts,\n prefixLines,\n newText,\n newStarts,\n prefixLines\n )\n ) {\n break;\n }\n prefixLines++;\n }\n\n let suffixLines = 0;\n while (\n suffixLines < oldLineCount - prefixLines &&\n suffixLines < newLineCount - prefixLines\n ) {\n const oldLine = oldLineCount - 1 - suffixLines;\n const newLine = newLineCount - 1 - suffixLines;\n if (!linesEqual(oldText, oldStarts, oldLine, newText, newStarts, newLine)) {\n break;\n }\n suffixLines++;\n }\n return { oldLineCount, newLineCount, prefixLines, suffixLines };\n}\n\nfunction formatEditHunk(\n path: string,\n oldText: string,\n newText: string,\n lineOffset = 0\n): { readonly hunk: string; readonly bounds: LineDiffBounds } | undefined {\n if (oldText === newText) {\n return;\n }\n const oldStarts = lineStarts(oldText);\n const newStarts = lineStarts(newText);\n const bounds = lineDiffBounds(oldText, oldStarts, newText, newStarts);\n if (\n bounds.prefixLines === bounds.oldLineCount &&\n bounds.prefixLines === bounds.newLineCount\n ) {\n return;\n }\n const oldChangedEnd = bounds.oldLineCount - bounds.suffixLines;\n const newChangedEnd = bounds.newLineCount - bounds.suffixLines;\n const oldChanged = oldText.slice(\n oldStarts[bounds.prefixLines] ?? oldText.length,\n oldStarts[oldChangedEnd] ?? oldText.length\n );\n const newChanged = newText.slice(\n newStarts[bounds.prefixLines] ?? newText.length,\n newStarts[newChangedEnd] ?? newText.length\n );\n if (\n textEncoder.encode(oldChanged).byteLength > MAX_CAPTURE_BYTES ||\n textEncoder.encode(newChanged).byteLength > MAX_CAPTURE_BYTES\n ) {\n return;\n }\n\n const start = Math.max(0, bounds.prefixLines - DIFF_CONTEXT_LINES);\n const oldEnd = Math.min(\n bounds.oldLineCount,\n oldChangedEnd + DIFF_CONTEXT_LINES\n );\n const newEnd = Math.min(\n bounds.newLineCount,\n newChangedEnd + DIFF_CONTEXT_LINES\n );\n const oldCount = oldEnd - start;\n const newCount = newEnd - start;\n const line = start + lineOffset;\n const output = [\n `--- a/${path}`,\n `+++ b/${path}`,\n `@@ -${oldCount === 0 ? line : line + 1},${oldCount} +${\n newCount === 0 ? line : line + 1\n },${newCount} @@`,\n ];\n for (let line = start; line < bounds.prefixLines; line++) {\n output.push(\n ` ${oldText.slice(oldStarts[line], lineEnd(oldText, oldStarts, line))}`\n );\n }\n for (let line = bounds.prefixLines; line < oldChangedEnd; line++) {\n output.push(\n `-${oldText.slice(oldStarts[line], lineEnd(oldText, oldStarts, line))}`\n );\n }\n for (let line = bounds.prefixLines; line < newChangedEnd; line++) {\n output.push(\n `+${newText.slice(newStarts[line], lineEnd(newText, newStarts, line))}`\n );\n }\n for (let line = oldChangedEnd; line < oldEnd; line++) {\n output.push(\n ` ${oldText.slice(oldStarts[line], lineEnd(oldText, oldStarts, line))}`\n );\n }\n const hunk = output.join('\\n');\n return textEncoder.encode(hunk).byteLength <= MAX_CAPTURE_BYTES\n ? { hunk, bounds }\n : undefined;\n}\n\n// Applies offset edits to a bounded document slice without materializing the\n// surrounding file. Returns undefined if the slice does not contain the edits.\nfunction applyEditsToSlice(\n text: string,\n sliceStart: number,\n edits: readonly ResolvedTextEdit[]\n): string | undefined {\n const chunks: string[] = [];\n let offset = 0;\n for (const edit of edits) {\n const start = edit.start - sliceStart;\n const end = edit.end - sliceStart;\n if (start < offset || end < start || end > text.length) {\n return;\n }\n chunks.push(text.slice(offset, start), edit.text);\n offset = end;\n }\n chunks.push(text.slice(offset));\n return chunks.join('');\n}\n\n// Captures a small post-edit window and reconstructs its pre-edit contents\n// from the inverse edits already stored by the undo transaction.\nfunction captureEditPredictionTransaction(\n document: EditPredictionDocument,\n transaction: TextDocumentChangeTransaction\n): EditPredictionTransactionFragment | undefined {\n const inverseEdits = transaction.inverseEdits;\n if (inverseEdits.length === 0) {\n return;\n }\n let changedStart = inverseEdits[0].start;\n let changedEnd = inverseEdits[0].end;\n for (let index = 1; index < inverseEdits.length; index++) {\n changedStart = Math.min(changedStart, inverseEdits[index].start);\n changedEnd = Math.max(changedEnd, inverseEdits[index].end);\n }\n const [startPosition, endPosition] = document.positionsAt([\n changedStart,\n changedEnd,\n ]);\n for (const contextLines of CAPTURE_CONTEXT_OPTIONS) {\n const startLine = Math.max(0, startPosition.line - contextLines);\n const endLine = Math.min(\n document.lineCount - 1,\n endPosition.line + contextLines\n );\n const afterStart = document.offsetAt({\n line: startLine,\n character: 0,\n });\n const afterEnd =\n endLine + 1 < document.lineCount\n ? document.offsetAt({ line: endLine + 1, character: 0 })\n : document.offsetAt({\n line: endLine,\n character: document.getLineLength(endLine),\n });\n if (afterEnd - afterStart > MAX_CAPTURE_BYTES) {\n continue;\n }\n const afterText = document.getTextSlice(afterStart, afterEnd);\n if (textEncoder.encode(afterText).byteLength > MAX_CAPTURE_BYTES) {\n continue;\n }\n const beforeText = applyEditsToSlice(afterText, afterStart, inverseEdits);\n if (\n beforeText === undefined ||\n beforeText.length > MAX_CAPTURE_BYTES ||\n textEncoder.encode(beforeText).byteLength > MAX_CAPTURE_BYTES\n ) {\n continue;\n }\n const bounds = lineDiffBounds(\n beforeText,\n lineStarts(beforeText),\n afterText,\n lineStarts(afterText)\n );\n return {\n beforeText,\n afterText,\n startOffset: afterStart,\n startLine,\n bounds,\n };\n }\n return undefined;\n}\n\nexport function recordEditPrediction(\n history: readonly EditPredictionHistoryRecord[],\n path: string,\n document: EditPredictionDocument,\n transaction: TextDocumentChangeTransaction,\n source: 'user' | 'prediction',\n at: number = Date.now()\n): EditPredictionHistoryRecord[] {\n const kept = history.slice(-MAX_HISTORY_ENTRIES);\n const fragment = captureEditPredictionTransaction(document, transaction);\n if (fragment === undefined) {\n const previous = kept.at(-1);\n if (previous?.fragment !== undefined) {\n kept[kept.length - 1] = { ...previous, fragment: undefined };\n }\n return kept;\n }\n if (fragment.beforeText === fragment.afterText) {\n return kept;\n }\n const changedStartLine = fragment.startLine + fragment.bounds.prefixLines;\n const beforeChangedEndLine =\n fragment.startLine +\n fragment.bounds.oldLineCount -\n fragment.bounds.suffixLines;\n const last = kept.at(-1);\n const gap =\n last !== undefined && changedStartLine > last.end\n ? changedStartLine - last.end\n : last !== undefined && last.start > beforeChangedEndLine\n ? last.start - beforeChangedEndLine\n : 0;\n const canMerge =\n last !== undefined &&\n last.fragment !== undefined &&\n last.path === path &&\n last.source === source &&\n at - last.at < COALESCE_MS &&\n gap <= COALESCE_LINES;\n\n if (canMerge) {\n const previous = last.fragment;\n const beforeEnd = fragment.startOffset + fragment.beforeText.length;\n const overlapStart = Math.max(previous.currentStart, fragment.startOffset);\n const overlapEnd = Math.min(previous.currentEnd, beforeEnd);\n if (\n overlapStart <= overlapEnd &&\n previous.currentText.slice(\n overlapStart - previous.currentStart,\n overlapEnd - previous.currentStart\n ) ===\n fragment.beforeText.slice(\n overlapStart - fragment.startOffset,\n overlapEnd - fragment.startOffset\n )\n ) {\n const unionStart = Math.min(previous.currentStart, fragment.startOffset);\n const currentText =\n previous.currentStart <= fragment.startOffset\n ? previous.currentText +\n fragment.beforeText.slice(\n Math.max(0, previous.currentEnd - fragment.startOffset)\n )\n : fragment.beforeText +\n previous.currentText.slice(\n Math.max(0, beforeEnd - previous.currentStart)\n );\n const prefix = currentText.slice(0, previous.currentStart - unionStart);\n const suffix = currentText.slice(previous.currentEnd - unionStart);\n const baseText = prefix + previous.baseText + suffix;\n const nextText = applyEditsToSlice(\n currentText,\n unionStart,\n transaction.appliedEdits\n );\n const startLine =\n previous.currentStart <= fragment.startOffset\n ? previous.startLine\n : fragment.startLine;\n if (\n nextText !== undefined &&\n baseText.length <= MAX_CAPTURE_BYTES &&\n nextText.length <= MAX_CAPTURE_BYTES &&\n textEncoder.encode(baseText).byteLength <= MAX_CAPTURE_BYTES &&\n textEncoder.encode(nextText).byteLength <= MAX_CAPTURE_BYTES\n ) {\n if (baseText === nextText) {\n kept.pop();\n return kept;\n }\n const formatted = formatEditHunk(path, baseText, nextText, startLine);\n if (formatted !== undefined) {\n kept[kept.length - 1] = {\n path,\n hunk: formatted.hunk,\n start: startLine + formatted.bounds.prefixLines,\n end:\n startLine +\n formatted.bounds.newLineCount -\n formatted.bounds.suffixLines,\n at,\n source,\n fragment: {\n baseText,\n currentText: nextText,\n currentStart: unionStart,\n currentEnd: unionStart + nextText.length,\n startLine,\n },\n };\n return kept;\n }\n }\n }\n }\n const previous = kept.at(-1);\n if (previous?.fragment !== undefined) {\n kept[kept.length - 1] = { ...previous, fragment: undefined };\n }\n const formatted = formatEditHunk(\n path,\n fragment.beforeText,\n fragment.afterText,\n fragment.startLine\n );\n if (formatted === undefined) {\n return kept;\n }\n kept.push({\n path,\n hunk: formatted.hunk,\n start: changedStartLine,\n end:\n fragment.startLine +\n fragment.bounds.newLineCount -\n fragment.bounds.suffixLines,\n at,\n source,\n fragment: {\n baseText: fragment.beforeText,\n currentText: fragment.afterText,\n currentStart: fragment.startOffset,\n currentEnd: fragment.startOffset + fragment.afterText.length,\n startLine: fragment.startLine,\n },\n });\n return kept.slice(-MAX_HISTORY_ENTRIES);\n}\n\n// Grows [first, last] one line at a time in both directions while the token\n// budget allows and `canExpandTo` accepts the next line on that side.\nfunction expandLinewise(\n lineCount: number,\n costForLine: (line: number) => number,\n canExpandTo: (line: number) => boolean,\n first: number,\n last: number,\n remaining: number\n): { first: number; last: number } {\n while (remaining > 0 && (first > 0 || last < lineCount - 1)) {\n let expanded = false;\n if (first > 0 && canExpandTo(first - 1)) {\n const cost = costForLine(first - 1);\n if (cost <= remaining) {\n first--;\n remaining -= cost;\n expanded = true;\n }\n }\n if (last < lineCount - 1 && canExpandTo(last + 1)) {\n const cost = costForLine(last + 1);\n if (cost <= remaining) {\n last++;\n remaining -= cost;\n expanded = true;\n }\n }\n if (!expanded) {\n break;\n }\n }\n return { first, last };\n}\n\n// Builds the request sent to the prediction provider. It carries a bounded\n// excerpt of the document around the cursor and marks the part of it the\n// provider may edit. The editable part grows outward from the cursor line and\n// stops at the first line `isLineEditable` rejects, so the provider never sees\n// an editable line the editor could not show a preview for. The rest of the\n// excerpt is read-only context and is not filtered. Returns undefined when the\n// cursor line itself is rejected.\nexport function buildEditPredictionRequest(\n path: string,\n document: EditPredictionDocument,\n cursorOffset: number,\n history: readonly EditPredictionHistoryRecord[],\n isLineEditable: (line: number) => boolean\n): EditPredictRequest | undefined {\n if (document.lineCount <= 0) {\n return;\n }\n const lastLine = document.lineCount - 1;\n const documentLength = document.offsetAt({\n line: lastLine,\n character: document.getLineLength(lastLine),\n });\n const normalizedCursor = Number.isFinite(cursorOffset)\n ? Math.trunc(cursorOffset)\n : 0;\n let cursor = Math.max(0, Math.min(normalizedCursor, documentLength));\n const previous = document.charAt(cursor - 1).charCodeAt(0);\n const next = document.charAt(cursor).charCodeAt(0);\n if (\n cursor > 0 &&\n cursor < documentLength &&\n ((previous === 13 && next === 10) ||\n (previous >= 0xd800 &&\n previous <= 0xdbff &&\n next >= 0xdc00 &&\n next <= 0xdfff))\n ) {\n cursor--;\n }\n const cursorLine = document.positionAt(cursor).line;\n // Cache whether each line may be edited. `isLineEditable` can be costly (a\n // diff has to walk its hunks to answer), and the loops below ask about the\n // same boundary lines over and over.\n const editableLines = new Map<number, boolean>();\n const canEdit = (line: number): boolean => {\n if (line < 0 || line >= document.lineCount) {\n return false;\n }\n let editable = editableLines.get(line);\n if (editable == null) {\n editable = isLineEditable(line);\n editableLines.set(line, editable);\n }\n return editable;\n };\n if (!canEdit(cursorLine)) {\n return;\n }\n const tokenCosts = new Map<number, number>();\n const costForLine = (line: number): number => {\n const cached = tokenCosts.get(line);\n if (cached !== undefined) {\n return cached;\n }\n const lineLength = document.getLineLength(line);\n if (Math.floor(lineLength / 3) > MAX_CONTEXT_TOKENS) {\n const cost = MAX_CONTEXT_TOKENS + 1;\n tokenCosts.set(line, cost);\n return cost;\n }\n const cost = Math.max(\n 1,\n Math.floor(textEncoder.encode(document.getLineText(line)).byteLength / 3)\n );\n tokenCosts.set(line, cost);\n return cost;\n };\n\n let editableFirst = cursorLine;\n let editableLast = cursorLine;\n const initialBudget = Math.floor((EDITABLE_TOKENS * 3) / 4);\n let remaining = Math.max(0, initialBudget - costForLine(cursorLine));\n while (\n remaining > 0 &&\n (canEdit(editableFirst - 1) || canEdit(editableLast + 1))\n ) {\n if (canEdit(editableLast + 1)) {\n const cost = costForLine(editableLast + 1);\n if (cost > remaining) {\n break;\n }\n editableLast++;\n remaining -= cost;\n }\n if (canEdit(editableFirst - 1) && remaining > 0) {\n const cost = costForLine(editableFirst - 1);\n if (cost > remaining) {\n break;\n }\n editableFirst--;\n remaining -= cost;\n }\n }\n remaining += EDITABLE_TOKENS - initialBudget;\n ({ first: editableFirst, last: editableLast } = expandLinewise(\n document.lineCount,\n costForLine,\n canEdit,\n editableFirst,\n editableLast,\n remaining\n ));\n\n let contextFirst = editableFirst;\n let contextLast = editableLast;\n ({ first: contextFirst, last: contextLast } = expandLinewise(\n document.lineCount,\n costForLine,\n () => true,\n contextFirst,\n contextLast,\n CONTEXT_TOKENS\n ));\n let editableTokens = 0;\n for (let line = editableFirst; line <= editableLast; line++) {\n editableTokens += costForLine(line);\n }\n let contextTokens = 0;\n for (let line = contextFirst; line <= contextLast; line++) {\n contextTokens += costForLine(line);\n }\n if (\n editableTokens > MAX_EDITABLE_TOKENS ||\n contextTokens > MAX_CONTEXT_TOKENS\n ) {\n return;\n }\n\n const contextStart = document.offsetAt({\n line: contextFirst,\n character: 0,\n });\n const contextEnd = document.offsetAt({\n line: contextLast,\n character: document.getLineLength(contextLast),\n });\n const excerptText = document.getTextSlice(contextStart, contextEnd);\n const request: EditPredictRequest = {\n path,\n version: document.version,\n eol: document.eol,\n excerptText,\n excerptStartLine: contextFirst,\n cursorOffsetInExcerpt: cursor - contextStart,\n editableRange: {\n start:\n document.offsetAt({ line: editableFirst, character: 0 }) - contextStart,\n end:\n document.offsetAt({\n line: editableLast,\n character: document.getLineLength(editableLast),\n }) - contextStart,\n },\n editHistory: history\n .slice(-MAX_HISTORY_ENTRIES)\n .map(({ hunk, source }) => ({\n diff: hunk,\n source,\n })),\n };\n return textEncoder.encode(JSON.stringify(request)).byteLength <=\n MAX_REQUEST_BYTES\n ? request\n : undefined;\n}\n\nexport function matchesEditPredictionPattern(\n path: string,\n pattern: string | RegExp\n): boolean {\n if (typeof pattern !== 'string') {\n return new RegExp(pattern.source, pattern.flags).test(path);\n }\n\n pattern = pattern.replaceAll('\\\\', '/');\n let source = '^';\n for (let index = 0; index < pattern.length; index++) {\n const character = pattern[index];\n if (character === '*') {\n if (pattern[index + 1] === '*') {\n index++;\n if (pattern[index + 1] === '/') {\n index++;\n source += '(?:.*/)?';\n } else {\n source += '.*';\n }\n } else {\n source += '[^/]*';\n }\n } else if (character === '?') {\n source += '[^/]';\n } else {\n source += /[\\\\^$.*+?()[\\]{}|]/.test(character)\n ? `\\\\${character}`\n : character;\n }\n }\n return new RegExp(`${source}$`).test(path);\n}\n"],"mappings":"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"}
|
|
@@ -1,76 +1,55 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { EditHistoryEntry, EditHistoryState, EditorLineAnnotation, EditorSelection, EditorType, ResolvedTextEdit } from "./types.js";
|
|
2
2
|
import { TextDocument } from "./textDocument.js";
|
|
3
3
|
|
|
4
4
|
//#region src/editor/editStack.d.ts
|
|
5
|
-
type
|
|
6
|
-
/** An entry in the edit stack. */
|
|
7
|
-
interface EditStackEntry<LAnnotation> {
|
|
8
|
-
/** Forward offset edits from the entry's base text to its final text. */
|
|
9
|
-
forwardEdits: ResolvedTextEdit[];
|
|
10
|
-
/** Inverse offset edits from the entry's final text back to its base text. */
|
|
11
|
-
inverseEdits: ResolvedTextEdit[];
|
|
12
|
-
/** Document version before the entry is applied. */
|
|
13
|
-
versionBefore: number;
|
|
14
|
-
/** Document version after the entry is applied. */
|
|
15
|
-
versionAfter: number;
|
|
16
|
-
/** Selection before the transaction. */
|
|
17
|
-
selectionsBefore?: EditorSelection[];
|
|
18
|
-
/** Selection after the transaction. */
|
|
19
|
-
selectionsAfter?: EditorSelection[];
|
|
20
|
-
/** Line annotations before the transaction. */
|
|
21
|
-
lineAnnotationsBefore?: DiffLineAnnotation<LAnnotation>[];
|
|
22
|
-
/** Line annotations after the transaction. */
|
|
23
|
-
lineAnnotationsAfter?: DiffLineAnnotation<LAnnotation>[];
|
|
24
|
-
/** Input mode inferred from the edit or retained by a coalesced run. */
|
|
25
|
-
coalescingMode?: EditStackCoalescingMode;
|
|
26
|
-
/**
|
|
27
|
-
* When `true`, this entry is its own undo step and never merges with the
|
|
28
|
-
* entry before or after it. Set for paste and cut, which otherwise look like
|
|
29
|
-
* typing and would merge into the previous keystroke.
|
|
30
|
-
*/
|
|
31
|
-
undoBoundary?: boolean;
|
|
32
|
-
}
|
|
5
|
+
type EditStackEntry<EType extends EditorType, LAnnotation = unknown> = EditHistoryEntry<EType, LAnnotation>;
|
|
33
6
|
/** Options for the edit stack. */
|
|
34
7
|
interface EditStackOptions {
|
|
35
8
|
/** The maximum number of entries to keep in the undo stack. */
|
|
36
9
|
maxEntries?: number;
|
|
37
10
|
}
|
|
38
11
|
/** A stack of edit entries. */
|
|
39
|
-
declare class EditStack<LAnnotation> {
|
|
12
|
+
declare class EditStack<EType extends EditorType, LAnnotation = unknown> {
|
|
40
13
|
#private;
|
|
41
14
|
constructor(options?: EditStackOptions);
|
|
42
15
|
get canUndo(): boolean;
|
|
43
16
|
get canRedo(): boolean;
|
|
17
|
+
/** Return an independent, developer-editable history snapshot. */
|
|
18
|
+
getState(): EditHistoryState<EType, LAnnotation>;
|
|
19
|
+
/** Return a live view over this stack without copying its entries. */
|
|
20
|
+
getLiveState(): EditHistoryState<EType, LAnnotation>;
|
|
21
|
+
/** Transfer developer-owned history into an edit stack. */
|
|
22
|
+
static fromState<EType extends EditorType, LAnnotation>(state: EditHistoryState<EType, LAnnotation>): EditStack<EType, LAnnotation>;
|
|
44
23
|
/** Clears both the undo and redo stacks. */
|
|
45
24
|
clear(): void;
|
|
46
25
|
/** Clears the redo stack. */
|
|
47
26
|
clearRedo(): void;
|
|
48
27
|
/** Pushes a new entry onto the undo stack. */
|
|
49
|
-
push(entry: EditStackEntry<LAnnotation>): void;
|
|
28
|
+
push(entry: EditStackEntry<EType, LAnnotation>): void;
|
|
50
29
|
/** Sets the selections after the last undo entry. */
|
|
51
30
|
setLastUndoSelectionsAfter(selections: EditorSelection[]): void;
|
|
52
31
|
/** Sets the line annotations after the last undo entry. */
|
|
53
|
-
setLastUndoLineAnnotations(lineAnnotationsBefore:
|
|
32
|
+
setLastUndoLineAnnotations(lineAnnotationsBefore: EditorLineAnnotation<EType, LAnnotation>[], lineAnnotationsAfter: EditorLineAnnotation<EType, LAnnotation>[]): void;
|
|
54
33
|
/** Returns the last undo entry, or `undefined` if empty. */
|
|
55
|
-
peekUndo(): EditStackEntry<LAnnotation> | undefined;
|
|
34
|
+
peekUndo(): EditStackEntry<EType, LAnnotation> | undefined;
|
|
56
35
|
/** Returns the last undo entry only while its coalescing group is open. */
|
|
57
|
-
peekUndoForCoalescing(): EditStackEntry<LAnnotation> | undefined;
|
|
36
|
+
peekUndoForCoalescing(): EditStackEntry<EType, LAnnotation> | undefined;
|
|
58
37
|
/** Replaces the last undo entry with the given entry. */
|
|
59
|
-
replaceLastUndo(entry: EditStackEntry<LAnnotation>): void;
|
|
38
|
+
replaceLastUndo(entry: EditStackEntry<EType, LAnnotation>): void;
|
|
60
39
|
/** Moves the latest undo entry to the redo stack and returns it, or `undefined` if empty. */
|
|
61
|
-
popUndoToRedo(): EditStackEntry<LAnnotation> | void;
|
|
40
|
+
popUndoToRedo(): EditStackEntry<EType, LAnnotation> | void;
|
|
62
41
|
/** Moves the latest redo entry back to the undo stack and returns it, or `undefined` if empty. */
|
|
63
|
-
popRedoToUndo(): EditStackEntry<LAnnotation> | void;
|
|
42
|
+
popRedoToUndo(): EditStackEntry<EType, LAnnotation> | void;
|
|
64
43
|
}
|
|
65
|
-
declare function createEditStackEntry<LAnnotation>(textDocument: TextDocument<LAnnotation>, resolvedEdits: ResolvedTextEdit[], versionBefore: number, versionAfter: number, selectionsBefore?: EditorSelection[], selectionsAfter?: EditorSelection[], lineAnnotationsBefore?:
|
|
44
|
+
declare function createEditStackEntry<EType extends EditorType, LAnnotation>(textDocument: TextDocument<EType, LAnnotation>, resolvedEdits: ResolvedTextEdit[], versionBefore: number, versionAfter: number, selectionsBefore?: EditorSelection[], selectionsAfter?: EditorSelection[], lineAnnotationsBefore?: EditorLineAnnotation<EType, LAnnotation>[], lineAnnotationsAfter?: EditorLineAnnotation<EType, LAnnotation>[]): EditStackEntry<EType, LAnnotation>;
|
|
66
45
|
/** Determines if the change matches following modes:
|
|
67
46
|
* - 'insert': simple typing
|
|
68
47
|
* - 'backspace': backward delete
|
|
69
48
|
* - 'delete': forward delete
|
|
70
49
|
*/
|
|
71
|
-
declare function shouldCoalesceEditStackEntry<LAnnotation>(previousEntry: EditStackEntry<LAnnotation> | undefined, nextEntry: EditStackEntry<LAnnotation>): boolean;
|
|
50
|
+
declare function shouldCoalesceEditStackEntry<EType extends EditorType, LAnnotation>(previousEntry: EditStackEntry<EType, LAnnotation> | undefined, nextEntry: EditStackEntry<EType, LAnnotation>): boolean;
|
|
72
51
|
/** Coalesce edit stack entries for simple typing and single-character deletes. */
|
|
73
|
-
declare function coalesceEditStackEntries<LAnnotation>(previousEntry: EditStackEntry<LAnnotation>, nextEntry: EditStackEntry<LAnnotation>): EditStackEntry<LAnnotation>;
|
|
52
|
+
declare function coalesceEditStackEntries<EType extends EditorType, LAnnotation>(previousEntry: EditStackEntry<EType, LAnnotation>, nextEntry: EditStackEntry<EType, LAnnotation>): EditStackEntry<EType, LAnnotation>;
|
|
74
53
|
//#endregion
|
|
75
54
|
export { EditStack, EditStackEntry, EditStackOptions, coalesceEditStackEntries, createEditStackEntry, shouldCoalesceEditStackEntry };
|
|
76
55
|
//# sourceMappingURL=editStack.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editStack.d.ts","names":[],"sources":["../../src/editor/editStack.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"editStack.d.ts","names":[],"sources":["../../src/editor/editStack.ts"],"mappings":";;;;KAkBY,cAAA,eACI,UAAA,2BAEZ,gBAAA,CAAiB,KAAA,EAAO,WAAA;;UAIX,gBAAA;EAPS;EASxB,UAAU;AAAA;;cAIC,SAAA,eAAwB,UAAA;EAAA;EAMnC,WAAA,CAAY,OAAA,GAAU,gBAAA;EAAA,IAOlB,OAAA;EAAA,IAIA,OAAA;EA7BU;EAkCd,QAAA,IAAY,gBAAA,CAAiB,KAAA,EAAO,WAAA;EAhClC;EA0CF,YAAA,IAAgB,gBAAA,CAAiB,KAAA,EAAO,WAAA;EA1Cd;EAAA,OAmEnB,SAAA,eAAwB,UAAA,eAC7B,KAAA,EAAO,gBAAA,CAAiB,KAAA,EAAO,WAAA,IAC9B,SAAA,CAAU,KAAA,EAAO,WAAA;EArEiB;EAgFrC,KAAA;EA5E+B;EAmF/B,SAAA;EAjFU;EAsFV,IAAA,CAAK,KAAA,EAAO,cAAA,CAAe,KAAA,EAAO,WAAA;EAlFvB;EA4FX,0BAAA,CAA2B,UAAA,EAAY,eAAA;EA5FnB;EAsGpB,0BAAA,CACE,qBAAA,EAAuB,oBAAA,CAAqB,KAAA,EAAO,WAAA,KACnD,oBAAA,EAAsB,oBAAA,CAAqB,KAAA,EAAO,WAAA;EAlG9B;EA4GtB,QAAA,IAAY,cAAA,CAAe,KAAA,EAAO,WAAA;EA5FE;EAiGpC,qBAAA,IAAyB,cAAA,CAAe,KAAA,EAAO,WAAA;EAvFd;EA4FjC,eAAA,CAAgB,KAAA,EAAO,cAAA,CAAe,KAAA,EAAO,WAAA;EA5F7B;EAuGhB,aAAA,IAAiB,cAAA,CAAe,KAAA,EAAO,WAAA;EA7Eb;EAuF1B,aAAA,IAAiB,cAAA,CAAe,KAAA,EAAO,WAAA;AAAA;AAAA,iBA8CzB,oBAAA,eAAmC,UAAA,eACjD,YAAA,EAAc,YAAA,CAAa,KAAA,EAAO,WAAA,GAClC,aAAA,EAAe,gBAAA,IACf,aAAA,UACA,YAAA,UACA,gBAAA,GAAmB,eAAA,IACnB,eAAA,GAAkB,eAAA,IAClB,qBAAA,GAAwB,oBAAA,CAAqB,KAAA,EAAO,WAAA,KACpD,oBAAA,GAAuB,oBAAA,CAAqB,KAAA,EAAO,WAAA,MAClD,cAAA,CAAe,KAAA,EAAO,WAAA;;;;;;iBAmET,4BAAA,eACA,UAAA,eAGd,aAAA,EAAe,cAAA,CAAe,KAAA,EAAO,WAAA,eACrC,SAAA,EAAW,cAAA,CAAe,KAAA,EAAO,WAAA;;iBA8FnB,wBAAA,eAAuC,UAAA,eACrD,aAAA,EAAe,cAAA,CAAe,KAAA,EAAO,WAAA,GACrC,SAAA,EAAW,cAAA,CAAe,KAAA,EAAO,WAAA,IAChC,cAAA,CAAe,KAAA,EAAO,WAAA"}
|
package/dist/editor/editStack.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
//#region src/editor/editStack.ts
|
|
2
2
|
/** Largest number of undo or redo entries kept; oldest entries drop first once exceeded. */
|
|
3
3
|
const DEFAULT_EDIT_STACK_MAX_ENTRIES = 100;
|
|
4
|
-
const COALESCING_MODE_INSERT =
|
|
5
|
-
const COALESCING_MODE_BACKSPACE =
|
|
6
|
-
const COALESCING_MODE_DELETE =
|
|
4
|
+
const COALESCING_MODE_INSERT = "insert";
|
|
5
|
+
const COALESCING_MODE_BACKSPACE = "backspace";
|
|
6
|
+
const COALESCING_MODE_DELETE = "delete";
|
|
7
7
|
/** A stack of edit entries. */
|
|
8
|
-
var EditStack = class {
|
|
8
|
+
var EditStack = class EditStack {
|
|
9
9
|
#undoStack = [];
|
|
10
10
|
#redoStack = [];
|
|
11
11
|
#maxEntries;
|
|
@@ -19,6 +19,44 @@ var EditStack = class {
|
|
|
19
19
|
get canRedo() {
|
|
20
20
|
return this.#redoStack.length > 0;
|
|
21
21
|
}
|
|
22
|
+
/** Return an independent, developer-editable history snapshot. */
|
|
23
|
+
getState() {
|
|
24
|
+
return {
|
|
25
|
+
undoStack: this.#undoStack.map(cloneEditStackEntryForState),
|
|
26
|
+
redoStack: this.#redoStack.map(cloneEditStackEntryForState),
|
|
27
|
+
maxEntries: this.#maxEntries,
|
|
28
|
+
canCoalesce: this.#canCoalesce
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/** Return a live view over this stack without copying its entries. */
|
|
32
|
+
getLiveState() {
|
|
33
|
+
return Object.defineProperties({}, {
|
|
34
|
+
undoStack: {
|
|
35
|
+
enumerable: true,
|
|
36
|
+
get: () => this.#undoStack
|
|
37
|
+
},
|
|
38
|
+
redoStack: {
|
|
39
|
+
enumerable: true,
|
|
40
|
+
get: () => this.#redoStack
|
|
41
|
+
},
|
|
42
|
+
maxEntries: {
|
|
43
|
+
enumerable: true,
|
|
44
|
+
get: () => this.#maxEntries
|
|
45
|
+
},
|
|
46
|
+
canCoalesce: {
|
|
47
|
+
enumerable: true,
|
|
48
|
+
get: () => this.#canCoalesce
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
/** Transfer developer-owned history into an edit stack. */
|
|
53
|
+
static fromState(state) {
|
|
54
|
+
const stack = new EditStack({ maxEntries: state.maxEntries });
|
|
55
|
+
stack.#undoStack = state.undoStack;
|
|
56
|
+
stack.#redoStack = state.redoStack;
|
|
57
|
+
stack.#canCoalesce = state.canCoalesce;
|
|
58
|
+
return stack;
|
|
59
|
+
}
|
|
22
60
|
/** Clears both the undo and redo stacks. */
|
|
23
61
|
clear() {
|
|
24
62
|
this.#undoStack.length = 0;
|
|
@@ -86,6 +124,31 @@ var EditStack = class {
|
|
|
86
124
|
}
|
|
87
125
|
}
|
|
88
126
|
};
|
|
127
|
+
function cloneEditStackEntry(entry) {
|
|
128
|
+
return {
|
|
129
|
+
...entry,
|
|
130
|
+
forwardEdits: entry.forwardEdits.map((edit) => ({ ...edit })),
|
|
131
|
+
inverseEdits: entry.inverseEdits.map((edit) => ({ ...edit })),
|
|
132
|
+
selectionsBefore: entry.selectionsBefore?.map(cloneSelection),
|
|
133
|
+
selectionsAfter: entry.selectionsAfter?.map(cloneSelection),
|
|
134
|
+
lineAnnotationsBefore: entry.lineAnnotationsBefore?.slice(),
|
|
135
|
+
lineAnnotationsAfter: entry.lineAnnotationsAfter?.slice()
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function cloneEditStackEntryForState(entry) {
|
|
139
|
+
return {
|
|
140
|
+
...cloneEditStackEntry(entry),
|
|
141
|
+
lineAnnotationsBefore: entry.lineAnnotationsBefore?.map((annotation) => ({ ...annotation })),
|
|
142
|
+
lineAnnotationsAfter: entry.lineAnnotationsAfter?.map((annotation) => ({ ...annotation }))
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function cloneSelection(selection) {
|
|
146
|
+
return {
|
|
147
|
+
...selection,
|
|
148
|
+
start: { ...selection.start },
|
|
149
|
+
end: { ...selection.end }
|
|
150
|
+
};
|
|
151
|
+
}
|
|
89
152
|
function createEditStackEntry(textDocument, resolvedEdits, versionBefore, versionAfter, selectionsBefore, selectionsAfter, lineAnnotationsBefore, lineAnnotationsAfter) {
|
|
90
153
|
const forwardEdits = [...resolvedEdits].sort((a, b) => a.start - b.start);
|
|
91
154
|
const inverseEdits = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editStack.js","names":["#maxEntries","#undoStack","#redoStack","#canCoalesce"],"sources":["../../src/editor/editStack.ts"],"sourcesContent":["import type {\n DiffLineAnnotation,\n EditorSelection,\n ResolvedTextEdit,\n} from '../types';\nimport type { TextDocument } from './textDocument';\n\n/** Largest number of undo or redo entries kept; oldest entries drop first once exceeded. */\nconst DEFAULT_EDIT_STACK_MAX_ENTRIES = 100;\n\nconst COALESCING_MODE_INSERT = 1;\nconst COALESCING_MODE_BACKSPACE = 2;\nconst COALESCING_MODE_DELETE = 3;\ntype EditStackCoalescingMode = 1 | 2 | 3;\n\n/** An entry in the edit stack. */\nexport interface EditStackEntry<LAnnotation> {\n /** Forward offset edits from the entry's base text to its final text. */\n forwardEdits: ResolvedTextEdit[];\n /** Inverse offset edits from the entry's final text back to its base text. */\n inverseEdits: ResolvedTextEdit[];\n /** Document version before the entry is applied. */\n versionBefore: number;\n /** Document version after the entry is applied. */\n versionAfter: number;\n /** Selection before the transaction. */\n selectionsBefore?: EditorSelection[];\n /** Selection after the transaction. */\n selectionsAfter?: EditorSelection[];\n /** Line annotations before the transaction. */\n lineAnnotationsBefore?: DiffLineAnnotation<LAnnotation>[];\n /** Line annotations after the transaction. */\n lineAnnotationsAfter?: DiffLineAnnotation<LAnnotation>[];\n /** Input mode inferred from the edit or retained by a coalesced run. */\n coalescingMode?: EditStackCoalescingMode;\n /**\n * When `true`, this entry is its own undo step and never merges with the\n * entry before or after it. Set for paste and cut, which otherwise look like\n * typing and would merge into the previous keystroke.\n */\n undoBoundary?: boolean;\n}\n\n/** Options for the edit stack. */\nexport interface EditStackOptions {\n /** The maximum number of entries to keep in the undo stack. */\n maxEntries?: number;\n}\n\n/** A stack of edit entries. */\nexport class EditStack<LAnnotation> {\n #undoStack: EditStackEntry<LAnnotation>[] = [];\n #redoStack: EditStackEntry<LAnnotation>[] = [];\n #maxEntries: number;\n #canCoalesce = false;\n\n constructor(options?: EditStackOptions) {\n this.#maxEntries = Math.max(\n 1,\n options?.maxEntries ?? DEFAULT_EDIT_STACK_MAX_ENTRIES\n );\n }\n\n get canUndo(): boolean {\n return this.#undoStack.length > 0;\n }\n\n get canRedo(): boolean {\n return this.#redoStack.length > 0;\n }\n\n /** Clears both the undo and redo stacks. */\n clear(): void {\n this.#undoStack.length = 0;\n this.#redoStack.length = 0;\n this.#canCoalesce = false;\n }\n\n /** Clears the redo stack. */\n clearRedo(): void {\n this.#redoStack.length = 0;\n }\n\n /** Pushes a new entry onto the undo stack. */\n push(entry: EditStackEntry<LAnnotation>): void {\n this.#undoStack.push(entry);\n this.clearRedo();\n this.#canCoalesce = true;\n if (this.#undoStack.length > this.#maxEntries) {\n this.#undoStack.shift();\n }\n }\n\n /** Sets the selections after the last undo entry. */\n setLastUndoSelectionsAfter(selections: EditorSelection[]): void {\n const lastEntry = this.#undoStack[this.#undoStack.length - 1];\n if (lastEntry !== undefined) {\n lastEntry.selectionsAfter = selections.map((selection) => ({\n ...selection,\n }));\n }\n }\n\n /** Sets the line annotations after the last undo entry. */\n setLastUndoLineAnnotations(\n lineAnnotationsBefore: DiffLineAnnotation<LAnnotation>[],\n lineAnnotationsAfter: DiffLineAnnotation<LAnnotation>[]\n ): void {\n const lastEntry = this.#undoStack[this.#undoStack.length - 1];\n if (lastEntry !== undefined) {\n lastEntry.lineAnnotationsBefore = lineAnnotationsBefore.slice();\n lastEntry.lineAnnotationsAfter = lineAnnotationsAfter.slice();\n }\n }\n\n /** Returns the last undo entry, or `undefined` if empty. */\n peekUndo(): EditStackEntry<LAnnotation> | undefined {\n return this.#undoStack[this.#undoStack.length - 1];\n }\n\n /** Returns the last undo entry only while its coalescing group is open. */\n peekUndoForCoalescing(): EditStackEntry<LAnnotation> | undefined {\n return this.#canCoalesce ? this.peekUndo() : undefined;\n }\n\n /** Replaces the last undo entry with the given entry. */\n replaceLastUndo(entry: EditStackEntry<LAnnotation>): void {\n if (this.#undoStack.length === 0) {\n this.push(entry);\n return;\n }\n this.#undoStack[this.#undoStack.length - 1] = entry;\n this.clearRedo();\n this.#canCoalesce = true;\n }\n\n /** Moves the latest undo entry to the redo stack and returns it, or `undefined` if empty. */\n popUndoToRedo(): EditStackEntry<LAnnotation> | void {\n const entry = this.#undoStack.pop();\n if (entry !== undefined) {\n this.#redoStack.push(entry);\n this.#canCoalesce = false;\n return entry;\n }\n }\n\n /** Moves the latest redo entry back to the undo stack and returns it, or `undefined` if empty. */\n popRedoToUndo(): EditStackEntry<LAnnotation> | void {\n const entry = this.#redoStack.pop();\n if (entry !== undefined) {\n this.#undoStack.push(entry);\n this.#canCoalesce = false;\n return entry;\n }\n }\n}\n\nexport function createEditStackEntry<LAnnotation>(\n textDocument: TextDocument<LAnnotation>,\n resolvedEdits: ResolvedTextEdit[],\n versionBefore: number,\n versionAfter: number,\n selectionsBefore?: EditorSelection[],\n selectionsAfter?: EditorSelection[],\n lineAnnotationsBefore?: DiffLineAnnotation<LAnnotation>[],\n lineAnnotationsAfter?: DiffLineAnnotation<LAnnotation>[]\n): EditStackEntry<LAnnotation> {\n const forwardEdits = [...resolvedEdits].sort((a, b) => a.start - b.start);\n const inverseEdits: ResolvedTextEdit[] = [];\n let coalescingMode: EditStackCoalescingMode | undefined;\n if (selectionsBefore?.length === forwardEdits.length) {\n const caretOffsets: number[] = [];\n for (const selection of selectionsBefore) {\n if (\n selection.start.line !== selection.end.line ||\n selection.start.character !== selection.end.character\n ) {\n break;\n }\n caretOffsets.push(textDocument.offsetAt(selection.start));\n }\n if (caretOffsets.length === forwardEdits.length) {\n caretOffsets.sort((a, b) => a - b);\n let isBackspace = true;\n let isDelete = true;\n for (let i = 0; i < forwardEdits.length; i++) {\n const edit = forwardEdits[i];\n if (edit.text.length > 0 || edit.start === edit.end) {\n isBackspace = false;\n isDelete = false;\n break;\n }\n isBackspace &&= caretOffsets[i] === edit.end;\n isDelete &&= caretOffsets[i] === edit.start;\n }\n coalescingMode = isBackspace\n ? COALESCING_MODE_BACKSPACE\n : isDelete\n ? COALESCING_MODE_DELETE\n : undefined;\n }\n }\n for (let i = 0, offsetDelta = 0; i < forwardEdits.length; i++) {\n const edit = forwardEdits[i];\n const replacedText = textDocument.getTextSlice(edit.start, edit.end);\n const startAfterEdit = edit.start + offsetDelta;\n inverseEdits.push({\n start: startAfterEdit,\n end: startAfterEdit + edit.text.length,\n text: replacedText,\n });\n offsetDelta += edit.text.length - (edit.end - edit.start);\n }\n return {\n forwardEdits: forwardEdits.map((edit) => ({ ...edit })),\n inverseEdits: inverseEdits,\n versionBefore,\n versionAfter,\n selectionsBefore: selectionsBefore?.map((selection) => ({\n ...selection,\n })),\n selectionsAfter: selectionsAfter?.map((selection) => ({ ...selection })),\n lineAnnotationsBefore: lineAnnotationsBefore?.slice(),\n lineAnnotationsAfter: lineAnnotationsAfter?.slice(),\n coalescingMode,\n };\n}\n\n/** Determines if the change matches following modes:\n * - 'insert': simple typing\n * - 'backspace': backward delete\n * - 'delete': forward delete\n */\nexport function shouldCoalesceEditStackEntry<LAnnotation>(\n previousEntry: EditStackEntry<LAnnotation> | undefined,\n nextEntry: EditStackEntry<LAnnotation>\n): boolean {\n if (\n previousEntry === undefined ||\n previousEntry.undoBoundary === true ||\n nextEntry.undoBoundary === true ||\n previousEntry.forwardEdits.length === 0 ||\n previousEntry.forwardEdits.length !== previousEntry.inverseEdits.length ||\n previousEntry.forwardEdits.length !== nextEntry.forwardEdits.length ||\n nextEntry.forwardEdits.length !== nextEntry.inverseEdits.length\n ) {\n return false;\n }\n let mode: EditStackCoalescingMode | undefined;\n for (let i = 0; i < previousEntry.forwardEdits.length; i++) {\n const previousForward = previousEntry.forwardEdits[i];\n const previousInverse = previousEntry.inverseEdits[i];\n const nextForward = nextEntry.forwardEdits[i];\n const nextInverse = nextEntry.inverseEdits[i];\n const mappedNextStart = mapOffsetAfterForwardBatchToBefore(\n nextForward.start,\n previousEntry.forwardEdits\n );\n const previousWasInsert =\n previousForward.start <= previousForward.end &&\n previousForward.text.length > 0 &&\n !previousForward.text.includes('\\n') &&\n !previousInverse.text.includes('\\n');\n const nextIsInsert =\n nextForward.start === nextForward.end &&\n nextForward.text.length > 0 &&\n !nextForward.text.includes('\\n') &&\n nextInverse.text.length === 0;\n if (previousWasInsert && nextIsInsert) {\n // Merge only when the next insert starts exactly where the previous\n // inserted text ends, in after-edit offsets. `previousInverse.end` marks\n // that point, since undo replaces exactly the inserted range. A\n // base-offset check can't tell this apart from a caret that jumped to the\n // left edge: both edges of a pure insert map back to the same base offset,\n // so typing \"a\" then \"b\" at the left edge would merge as \"ab\" while the\n // buffer holds \"ba\", corrupting redo.\n if (nextForward.start !== previousInverse.end) {\n return false;\n }\n mode ??= COALESCING_MODE_INSERT;\n if (\n mode !== COALESCING_MODE_INSERT ||\n (previousEntry.coalescingMode !== undefined &&\n previousEntry.coalescingMode !== COALESCING_MODE_INSERT) ||\n (nextEntry.coalescingMode !== undefined &&\n nextEntry.coalescingMode !== COALESCING_MODE_INSERT)\n ) {\n return false;\n }\n continue;\n }\n const previousWasDelete =\n previousForward.text.length === 0 &&\n previousForward.end > previousForward.start &&\n previousInverse.text.length > 0;\n const nextIsDelete =\n nextForward.text.length === 0 &&\n nextForward.end > nextForward.start &&\n nextInverse.text.length > 0;\n if (previousWasDelete && nextIsDelete) {\n let nextMode: EditStackCoalescingMode;\n if (mappedNextStart === previousForward.end) {\n nextMode = COALESCING_MODE_DELETE;\n } else if (\n mappedNextStart + (nextForward.end - nextForward.start) !==\n previousForward.start\n ) {\n return false;\n } else {\n nextMode = COALESCING_MODE_BACKSPACE;\n }\n mode ??= nextMode;\n if (\n mode !== nextMode ||\n (previousEntry.coalescingMode !== undefined &&\n previousEntry.coalescingMode !== nextMode) ||\n (nextEntry.coalescingMode !== undefined &&\n nextEntry.coalescingMode !== nextMode)\n ) {\n return false;\n }\n continue;\n }\n return false;\n }\n return mode !== undefined;\n}\n\n/** Coalesce edit stack entries for simple typing and single-character deletes. */\nexport function coalesceEditStackEntries<LAnnotation>(\n previousEntry: EditStackEntry<LAnnotation>,\n nextEntry: EditStackEntry<LAnnotation>\n): EditStackEntry<LAnnotation> {\n const forwardEdits: ResolvedTextEdit[] = [];\n const replacedTexts: string[] = [];\n let coalescingMode: EditStackCoalescingMode | undefined;\n for (let i = 0; i < previousEntry.forwardEdits.length; i++) {\n const previousForward = previousEntry.forwardEdits[i];\n const previousInverse = previousEntry.inverseEdits[i];\n const nextForward = nextEntry.forwardEdits[i];\n const nextInverse = nextEntry.inverseEdits[i];\n const mappedNextStart = mapOffsetAfterForwardBatchToBefore(\n nextForward.start,\n previousEntry.forwardEdits\n );\n\n if (previousForward.text.length > 0) {\n coalescingMode ??= COALESCING_MODE_INSERT;\n forwardEdits.push({\n start: previousForward.start,\n end: previousForward.end,\n text: previousForward.text + nextForward.text,\n });\n replacedTexts.push(previousInverse.text);\n continue;\n }\n\n if (mappedNextStart === previousForward.end) {\n coalescingMode ??= COALESCING_MODE_DELETE;\n forwardEdits.push({\n start: previousForward.start,\n end: mappedNextStart + (nextForward.end - nextForward.start),\n text: '',\n });\n replacedTexts.push(previousInverse.text + nextInverse.text);\n continue;\n }\n\n coalescingMode ??= COALESCING_MODE_BACKSPACE;\n forwardEdits.push({\n start: Math.min(previousForward.start, mappedNextStart),\n end: previousForward.end,\n text: '',\n });\n replacedTexts.push(nextInverse.text + previousInverse.text);\n }\n\n return {\n forwardEdits,\n inverseEdits: buildInverseEditsFromReplacedTexts(\n forwardEdits,\n replacedTexts\n ),\n versionBefore: previousEntry.versionBefore,\n versionAfter: nextEntry.versionAfter,\n selectionsBefore: previousEntry.selectionsBefore?.slice(),\n selectionsAfter: nextEntry.selectionsAfter?.slice(),\n lineAnnotationsBefore: previousEntry.lineAnnotationsBefore?.slice(),\n lineAnnotationsAfter: nextEntry.lineAnnotationsAfter?.slice(),\n coalescingMode,\n };\n}\n\nfunction buildInverseEditsFromReplacedTexts(\n forwardEdits: readonly ResolvedTextEdit[],\n replacedTexts: readonly string[]\n): ResolvedTextEdit[] {\n const inverseEdits: ResolvedTextEdit[] = [];\n for (let i = 0, offsetDelta = 0; i < forwardEdits.length; i++) {\n const edit = forwardEdits[i];\n const startAfterEdit = edit.start + offsetDelta;\n inverseEdits.push({\n start: startAfterEdit,\n end: startAfterEdit + edit.text.length,\n text: replacedTexts[i],\n });\n offsetDelta += edit.text.length - (edit.end - edit.start);\n }\n return inverseEdits;\n}\n\nfunction mapOffsetAfterForwardBatchToBefore(\n offsetAfter: number,\n forwardEdits: readonly ResolvedTextEdit[]\n): number {\n let offset = offsetAfter;\n for (const edit of forwardEdits) {\n const oldLength = edit.end - edit.start;\n const newLength = edit.text.length;\n const delta = newLength - oldLength;\n if (offset < edit.start) {\n continue;\n }\n if (offset >= edit.start + newLength) {\n offset -= delta;\n continue;\n }\n offset = edit.start + Math.min(offset - edit.start, oldLength);\n }\n return offset;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"editStack.js","names":["#maxEntries","#undoStack","#redoStack","#canCoalesce"],"sources":["../../src/editor/editStack.ts"],"sourcesContent":["import type { TextDocument } from './textDocument';\nimport type {\n EditHistoryCoalescingMode,\n EditHistoryEntry,\n EditHistoryState,\n EditorLineAnnotation,\n EditorSelection,\n EditorType,\n ResolvedTextEdit,\n} from './types';\n\n/** Largest number of undo or redo entries kept; oldest entries drop first once exceeded. */\nconst DEFAULT_EDIT_STACK_MAX_ENTRIES = 100;\n\nconst COALESCING_MODE_INSERT = 'insert';\nconst COALESCING_MODE_BACKSPACE = 'backspace';\nconst COALESCING_MODE_DELETE = 'delete';\n\nexport type EditStackEntry<\n EType extends EditorType,\n LAnnotation = unknown,\n> = EditHistoryEntry<EType, LAnnotation>;\ntype EditStackCoalescingMode = EditHistoryCoalescingMode;\n\n/** Options for the edit stack. */\nexport interface EditStackOptions {\n /** The maximum number of entries to keep in the undo stack. */\n maxEntries?: number;\n}\n\n/** A stack of edit entries. */\nexport class EditStack<EType extends EditorType, LAnnotation = unknown> {\n #undoStack: EditStackEntry<EType, LAnnotation>[] = [];\n #redoStack: EditStackEntry<EType, LAnnotation>[] = [];\n #maxEntries: number;\n #canCoalesce = false;\n\n constructor(options?: EditStackOptions) {\n this.#maxEntries = Math.max(\n 1,\n options?.maxEntries ?? DEFAULT_EDIT_STACK_MAX_ENTRIES\n );\n }\n\n get canUndo(): boolean {\n return this.#undoStack.length > 0;\n }\n\n get canRedo(): boolean {\n return this.#redoStack.length > 0;\n }\n\n /** Return an independent, developer-editable history snapshot. */\n getState(): EditHistoryState<EType, LAnnotation> {\n return {\n undoStack: this.#undoStack.map(cloneEditStackEntryForState),\n redoStack: this.#redoStack.map(cloneEditStackEntryForState),\n maxEntries: this.#maxEntries,\n canCoalesce: this.#canCoalesce,\n };\n }\n\n /** Return a live view over this stack without copying its entries. */\n getLiveState(): EditHistoryState<EType, LAnnotation> {\n return Object.defineProperties(\n {},\n {\n undoStack: {\n enumerable: true,\n get: () => this.#undoStack,\n },\n redoStack: {\n enumerable: true,\n get: () => this.#redoStack,\n },\n maxEntries: {\n enumerable: true,\n get: () => this.#maxEntries,\n },\n canCoalesce: {\n enumerable: true,\n get: () => this.#canCoalesce,\n },\n }\n ) as EditHistoryState<EType, LAnnotation>;\n }\n\n /** Transfer developer-owned history into an edit stack. */\n static fromState<EType extends EditorType, LAnnotation>(\n state: EditHistoryState<EType, LAnnotation>\n ): EditStack<EType, LAnnotation> {\n const stack = new EditStack<EType, LAnnotation>({\n maxEntries: state.maxEntries,\n });\n stack.#undoStack = state.undoStack;\n stack.#redoStack = state.redoStack;\n stack.#canCoalesce = state.canCoalesce;\n return stack;\n }\n\n /** Clears both the undo and redo stacks. */\n clear(): void {\n this.#undoStack.length = 0;\n this.#redoStack.length = 0;\n this.#canCoalesce = false;\n }\n\n /** Clears the redo stack. */\n clearRedo(): void {\n this.#redoStack.length = 0;\n }\n\n /** Pushes a new entry onto the undo stack. */\n push(entry: EditStackEntry<EType, LAnnotation>): void {\n this.#undoStack.push(entry);\n this.clearRedo();\n this.#canCoalesce = true;\n if (this.#undoStack.length > this.#maxEntries) {\n this.#undoStack.shift();\n }\n }\n\n /** Sets the selections after the last undo entry. */\n setLastUndoSelectionsAfter(selections: EditorSelection[]): void {\n const lastEntry = this.#undoStack[this.#undoStack.length - 1];\n if (lastEntry !== undefined) {\n lastEntry.selectionsAfter = selections.map((selection) => ({\n ...selection,\n }));\n }\n }\n\n /** Sets the line annotations after the last undo entry. */\n setLastUndoLineAnnotations(\n lineAnnotationsBefore: EditorLineAnnotation<EType, LAnnotation>[],\n lineAnnotationsAfter: EditorLineAnnotation<EType, LAnnotation>[]\n ): void {\n const lastEntry = this.#undoStack[this.#undoStack.length - 1];\n if (lastEntry !== undefined) {\n lastEntry.lineAnnotationsBefore = lineAnnotationsBefore.slice();\n lastEntry.lineAnnotationsAfter = lineAnnotationsAfter.slice();\n }\n }\n\n /** Returns the last undo entry, or `undefined` if empty. */\n peekUndo(): EditStackEntry<EType, LAnnotation> | undefined {\n return this.#undoStack[this.#undoStack.length - 1];\n }\n\n /** Returns the last undo entry only while its coalescing group is open. */\n peekUndoForCoalescing(): EditStackEntry<EType, LAnnotation> | undefined {\n return this.#canCoalesce ? this.peekUndo() : undefined;\n }\n\n /** Replaces the last undo entry with the given entry. */\n replaceLastUndo(entry: EditStackEntry<EType, LAnnotation>): void {\n if (this.#undoStack.length === 0) {\n this.push(entry);\n return;\n }\n this.#undoStack[this.#undoStack.length - 1] = entry;\n this.clearRedo();\n this.#canCoalesce = true;\n }\n\n /** Moves the latest undo entry to the redo stack and returns it, or `undefined` if empty. */\n popUndoToRedo(): EditStackEntry<EType, LAnnotation> | void {\n const entry = this.#undoStack.pop();\n if (entry !== undefined) {\n this.#redoStack.push(entry);\n this.#canCoalesce = false;\n return entry;\n }\n }\n\n /** Moves the latest redo entry back to the undo stack and returns it, or `undefined` if empty. */\n popRedoToUndo(): EditStackEntry<EType, LAnnotation> | void {\n const entry = this.#redoStack.pop();\n if (entry !== undefined) {\n this.#undoStack.push(entry);\n this.#canCoalesce = false;\n return entry;\n }\n }\n}\n\nfunction cloneEditStackEntry<EType extends EditorType, LAnnotation>(\n entry: EditStackEntry<EType, LAnnotation>\n): EditStackEntry<EType, LAnnotation> {\n return {\n ...entry,\n forwardEdits: entry.forwardEdits.map((edit) => ({ ...edit })),\n inverseEdits: entry.inverseEdits.map((edit) => ({ ...edit })),\n selectionsBefore: entry.selectionsBefore?.map(cloneSelection),\n selectionsAfter: entry.selectionsAfter?.map(cloneSelection),\n lineAnnotationsBefore: entry.lineAnnotationsBefore?.slice(),\n lineAnnotationsAfter: entry.lineAnnotationsAfter?.slice(),\n };\n}\n\nfunction cloneEditStackEntryForState<EType extends EditorType, LAnnotation>(\n entry: EditStackEntry<EType, LAnnotation>\n): EditStackEntry<EType, LAnnotation> {\n return {\n ...cloneEditStackEntry(entry),\n lineAnnotationsBefore: entry.lineAnnotationsBefore?.map((annotation) => ({\n ...annotation,\n })),\n lineAnnotationsAfter: entry.lineAnnotationsAfter?.map((annotation) => ({\n ...annotation,\n })),\n };\n}\n\nfunction cloneSelection(selection: EditorSelection): EditorSelection {\n return {\n ...selection,\n start: { ...selection.start },\n end: { ...selection.end },\n };\n}\n\nexport function createEditStackEntry<EType extends EditorType, LAnnotation>(\n textDocument: TextDocument<EType, LAnnotation>,\n resolvedEdits: ResolvedTextEdit[],\n versionBefore: number,\n versionAfter: number,\n selectionsBefore?: EditorSelection[],\n selectionsAfter?: EditorSelection[],\n lineAnnotationsBefore?: EditorLineAnnotation<EType, LAnnotation>[],\n lineAnnotationsAfter?: EditorLineAnnotation<EType, LAnnotation>[]\n): EditStackEntry<EType, LAnnotation> {\n const forwardEdits = [...resolvedEdits].sort((a, b) => a.start - b.start);\n const inverseEdits: ResolvedTextEdit[] = [];\n let coalescingMode: EditStackCoalescingMode | undefined;\n if (selectionsBefore?.length === forwardEdits.length) {\n const caretOffsets: number[] = [];\n for (const selection of selectionsBefore) {\n if (\n selection.start.line !== selection.end.line ||\n selection.start.character !== selection.end.character\n ) {\n break;\n }\n caretOffsets.push(textDocument.offsetAt(selection.start));\n }\n if (caretOffsets.length === forwardEdits.length) {\n caretOffsets.sort((a, b) => a - b);\n let isBackspace = true;\n let isDelete = true;\n for (let i = 0; i < forwardEdits.length; i++) {\n const edit = forwardEdits[i];\n if (edit.text.length > 0 || edit.start === edit.end) {\n isBackspace = false;\n isDelete = false;\n break;\n }\n isBackspace &&= caretOffsets[i] === edit.end;\n isDelete &&= caretOffsets[i] === edit.start;\n }\n coalescingMode = isBackspace\n ? COALESCING_MODE_BACKSPACE\n : isDelete\n ? COALESCING_MODE_DELETE\n : undefined;\n }\n }\n for (let i = 0, offsetDelta = 0; i < forwardEdits.length; i++) {\n const edit = forwardEdits[i];\n const replacedText = textDocument.getTextSlice(edit.start, edit.end);\n const startAfterEdit = edit.start + offsetDelta;\n inverseEdits.push({\n start: startAfterEdit,\n end: startAfterEdit + edit.text.length,\n text: replacedText,\n });\n offsetDelta += edit.text.length - (edit.end - edit.start);\n }\n return {\n forwardEdits: forwardEdits.map((edit) => ({ ...edit })),\n inverseEdits: inverseEdits,\n versionBefore,\n versionAfter,\n selectionsBefore: selectionsBefore?.map((selection) => ({\n ...selection,\n })),\n selectionsAfter: selectionsAfter?.map((selection) => ({ ...selection })),\n lineAnnotationsBefore: lineAnnotationsBefore?.slice(),\n lineAnnotationsAfter: lineAnnotationsAfter?.slice(),\n coalescingMode,\n };\n}\n\n/** Determines if the change matches following modes:\n * - 'insert': simple typing\n * - 'backspace': backward delete\n * - 'delete': forward delete\n */\nexport function shouldCoalesceEditStackEntry<\n EType extends EditorType,\n LAnnotation,\n>(\n previousEntry: EditStackEntry<EType, LAnnotation> | undefined,\n nextEntry: EditStackEntry<EType, LAnnotation>\n): boolean {\n if (\n previousEntry === undefined ||\n previousEntry.undoBoundary === true ||\n nextEntry.undoBoundary === true ||\n previousEntry.forwardEdits.length === 0 ||\n previousEntry.forwardEdits.length !== previousEntry.inverseEdits.length ||\n previousEntry.forwardEdits.length !== nextEntry.forwardEdits.length ||\n nextEntry.forwardEdits.length !== nextEntry.inverseEdits.length\n ) {\n return false;\n }\n let mode: EditStackCoalescingMode | undefined;\n for (let i = 0; i < previousEntry.forwardEdits.length; i++) {\n const previousForward = previousEntry.forwardEdits[i];\n const previousInverse = previousEntry.inverseEdits[i];\n const nextForward = nextEntry.forwardEdits[i];\n const nextInverse = nextEntry.inverseEdits[i];\n const mappedNextStart = mapOffsetAfterForwardBatchToBefore(\n nextForward.start,\n previousEntry.forwardEdits\n );\n const previousWasInsert =\n previousForward.start <= previousForward.end &&\n previousForward.text.length > 0 &&\n !previousForward.text.includes('\\n') &&\n !previousInverse.text.includes('\\n');\n const nextIsInsert =\n nextForward.start === nextForward.end &&\n nextForward.text.length > 0 &&\n !nextForward.text.includes('\\n') &&\n nextInverse.text.length === 0;\n if (previousWasInsert && nextIsInsert) {\n // Merge only when the next insert starts exactly where the previous\n // inserted text ends, in after-edit offsets. `previousInverse.end` marks\n // that point, since undo replaces exactly the inserted range. A\n // base-offset check can't tell this apart from a caret that jumped to the\n // left edge: both edges of a pure insert map back to the same base offset,\n // so typing \"a\" then \"b\" at the left edge would merge as \"ab\" while the\n // buffer holds \"ba\", corrupting redo.\n if (nextForward.start !== previousInverse.end) {\n return false;\n }\n mode ??= COALESCING_MODE_INSERT;\n if (\n mode !== COALESCING_MODE_INSERT ||\n (previousEntry.coalescingMode !== undefined &&\n previousEntry.coalescingMode !== COALESCING_MODE_INSERT) ||\n (nextEntry.coalescingMode !== undefined &&\n nextEntry.coalescingMode !== COALESCING_MODE_INSERT)\n ) {\n return false;\n }\n continue;\n }\n const previousWasDelete =\n previousForward.text.length === 0 &&\n previousForward.end > previousForward.start &&\n previousInverse.text.length > 0;\n const nextIsDelete =\n nextForward.text.length === 0 &&\n nextForward.end > nextForward.start &&\n nextInverse.text.length > 0;\n if (previousWasDelete && nextIsDelete) {\n let nextMode: EditStackCoalescingMode;\n if (mappedNextStart === previousForward.end) {\n nextMode = COALESCING_MODE_DELETE;\n } else if (\n mappedNextStart + (nextForward.end - nextForward.start) !==\n previousForward.start\n ) {\n return false;\n } else {\n nextMode = COALESCING_MODE_BACKSPACE;\n }\n mode ??= nextMode;\n if (\n mode !== nextMode ||\n (previousEntry.coalescingMode !== undefined &&\n previousEntry.coalescingMode !== nextMode) ||\n (nextEntry.coalescingMode !== undefined &&\n nextEntry.coalescingMode !== nextMode)\n ) {\n return false;\n }\n continue;\n }\n return false;\n }\n return mode !== undefined;\n}\n\n/** Coalesce edit stack entries for simple typing and single-character deletes. */\nexport function coalesceEditStackEntries<EType extends EditorType, LAnnotation>(\n previousEntry: EditStackEntry<EType, LAnnotation>,\n nextEntry: EditStackEntry<EType, LAnnotation>\n): EditStackEntry<EType, LAnnotation> {\n const forwardEdits: ResolvedTextEdit[] = [];\n const replacedTexts: string[] = [];\n let coalescingMode: EditStackCoalescingMode | undefined;\n for (let i = 0; i < previousEntry.forwardEdits.length; i++) {\n const previousForward = previousEntry.forwardEdits[i];\n const previousInverse = previousEntry.inverseEdits[i];\n const nextForward = nextEntry.forwardEdits[i];\n const nextInverse = nextEntry.inverseEdits[i];\n const mappedNextStart = mapOffsetAfterForwardBatchToBefore(\n nextForward.start,\n previousEntry.forwardEdits\n );\n\n if (previousForward.text.length > 0) {\n coalescingMode ??= COALESCING_MODE_INSERT;\n forwardEdits.push({\n start: previousForward.start,\n end: previousForward.end,\n text: previousForward.text + nextForward.text,\n });\n replacedTexts.push(previousInverse.text);\n continue;\n }\n\n if (mappedNextStart === previousForward.end) {\n coalescingMode ??= COALESCING_MODE_DELETE;\n forwardEdits.push({\n start: previousForward.start,\n end: mappedNextStart + (nextForward.end - nextForward.start),\n text: '',\n });\n replacedTexts.push(previousInverse.text + nextInverse.text);\n continue;\n }\n\n coalescingMode ??= COALESCING_MODE_BACKSPACE;\n forwardEdits.push({\n start: Math.min(previousForward.start, mappedNextStart),\n end: previousForward.end,\n text: '',\n });\n replacedTexts.push(nextInverse.text + previousInverse.text);\n }\n\n return {\n forwardEdits,\n inverseEdits: buildInverseEditsFromReplacedTexts(\n forwardEdits,\n replacedTexts\n ),\n versionBefore: previousEntry.versionBefore,\n versionAfter: nextEntry.versionAfter,\n selectionsBefore: previousEntry.selectionsBefore?.slice(),\n selectionsAfter: nextEntry.selectionsAfter?.slice(),\n lineAnnotationsBefore: previousEntry.lineAnnotationsBefore?.slice(),\n lineAnnotationsAfter: nextEntry.lineAnnotationsAfter?.slice(),\n coalescingMode,\n };\n}\n\nfunction buildInverseEditsFromReplacedTexts(\n forwardEdits: readonly ResolvedTextEdit[],\n replacedTexts: readonly string[]\n): ResolvedTextEdit[] {\n const inverseEdits: ResolvedTextEdit[] = [];\n for (let i = 0, offsetDelta = 0; i < forwardEdits.length; i++) {\n const edit = forwardEdits[i];\n const startAfterEdit = edit.start + offsetDelta;\n inverseEdits.push({\n start: startAfterEdit,\n end: startAfterEdit + edit.text.length,\n text: replacedTexts[i],\n });\n offsetDelta += edit.text.length - (edit.end - edit.start);\n }\n return inverseEdits;\n}\n\nfunction mapOffsetAfterForwardBatchToBefore(\n offsetAfter: number,\n forwardEdits: readonly ResolvedTextEdit[]\n): number {\n let offset = offsetAfter;\n for (const edit of forwardEdits) {\n const oldLength = edit.end - edit.start;\n const newLength = edit.text.length;\n const delta = newLength - oldLength;\n if (offset < edit.start) {\n continue;\n }\n if (offset >= edit.start + newLength) {\n offset -= delta;\n continue;\n }\n offset = edit.start + Math.min(offset - edit.start, oldLength);\n }\n return offset;\n}\n"],"mappings":"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"}
|
package/dist/editor/editor.d.ts
CHANGED
|
@@ -1,27 +1,53 @@
|
|
|
1
|
-
import { DiffLineAnnotation,
|
|
1
|
+
import { DiffLineAnnotation, DiffsHighlighter, FileContents, FileDiffMetadata, LineAnnotation, RenderRange } from "../types.js";
|
|
2
|
+
import { EditState, EditorCaret, EditorChangeEvent, EditorEditCompleteEvent, EditorInitialState, EditorType, EditorViewState, Range, RetainedDiffSessionSnapshot, TextEdit } from "./types.js";
|
|
3
|
+
import { File } from "../components/File.js";
|
|
4
|
+
import { FileDiff } from "../components/FileDiff.js";
|
|
2
5
|
import { EditorKeymap } from "./command.js";
|
|
6
|
+
import { EditPredictContext, EditPredictProvider, EditPredictRequest, EditPredictResponse } from "./editPrediction.js";
|
|
3
7
|
import { LanguageConfigMap } from "./languages.js";
|
|
4
8
|
import { Marker } from "./marker.js";
|
|
5
9
|
import { AutoSurround } from "./selection.js";
|
|
6
10
|
import { SelectionActionContext } from "./selectionAction.js";
|
|
7
|
-
import { PersistStateStorage } from "./stateStorage.js";
|
|
8
11
|
|
|
9
12
|
//#region src/editor/editor.d.ts
|
|
10
|
-
interface
|
|
13
|
+
interface SyncRenderViewBaseProps {
|
|
14
|
+
highlighter: DiffsHighlighter;
|
|
15
|
+
fileContainer: HTMLElement;
|
|
16
|
+
renderRange: RenderRange | undefined;
|
|
17
|
+
/** Start fresh history instead of retaining or extending the current history. */
|
|
18
|
+
resetHistory?: boolean;
|
|
19
|
+
}
|
|
20
|
+
interface SyncFileRenderViewProps<LAnnotation> extends SyncRenderViewBaseProps {
|
|
21
|
+
file: FileContents;
|
|
22
|
+
lineAnnotations: LineAnnotation<LAnnotation>[] | undefined;
|
|
23
|
+
/** Treat the supplied contents as an externally provided document update. */
|
|
24
|
+
externalDocument?: boolean;
|
|
25
|
+
}
|
|
26
|
+
interface SyncDiffRenderViewProps<LAnnotation> extends SyncRenderViewBaseProps {
|
|
27
|
+
fileDiff: FileDiffMetadata;
|
|
28
|
+
lineAnnotations: DiffLineAnnotation<LAnnotation>[] | undefined;
|
|
29
|
+
/** Treat the supplied contents as an externally provided document update. */
|
|
30
|
+
externalDocument?: boolean;
|
|
31
|
+
}
|
|
32
|
+
type SyncRenderViewProps<EType extends EditorType, LAnnotation> = EType extends 'file' ? SyncFileRenderViewProps<LAnnotation> : SyncDiffRenderViewProps<LAnnotation>;
|
|
33
|
+
type EditorComponent<EType extends EditorType, LAnnotation, Caret> = EType extends 'file' ? File<LAnnotation, Caret> : FileDiff<LAnnotation, Caret>;
|
|
34
|
+
interface EditorOptions<EType extends EditorType, LAnnotation, Caret> {
|
|
11
35
|
/** The maximum number of entries to keep in the undo stack. */
|
|
12
36
|
historyMaxEntries?: number;
|
|
13
|
-
/** Custom keymap groups checked before defaults; later groups take precedence. */
|
|
14
|
-
keymap?: EditorKeymap;
|
|
15
37
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
38
|
+
* Retain and restore the attached component's vertical viewport position.
|
|
39
|
+
* Defaults to false because scroll views generally contain multiple items.
|
|
40
|
+
* This option is captured when the editor is constructed.
|
|
18
41
|
*/
|
|
19
|
-
|
|
42
|
+
ownsVerticalViewport?: boolean;
|
|
20
43
|
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
44
|
+
* Document and editor state transferred to the first attachment. Missing
|
|
45
|
+
* fields are initialized from the attached component. The editor takes
|
|
46
|
+
* ownership and does not clone supplied objects.
|
|
23
47
|
*/
|
|
24
|
-
|
|
48
|
+
initialState?: EditorInitialState<EType, LAnnotation>;
|
|
49
|
+
/** Custom keymap groups checked before defaults; later groups take precedence. */
|
|
50
|
+
keymap?: EditorKeymap;
|
|
25
51
|
/** Render rounded corners for selection ranges, default is true. */
|
|
26
52
|
roundedSelection?: boolean;
|
|
27
53
|
/** Highlight matching brackets near the caret, default is true. */
|
|
@@ -34,10 +60,38 @@ interface EditorOptions<LAnnotation> {
|
|
|
34
60
|
/** Per-language comment tokens used by the comment commands. */
|
|
35
61
|
languageCommentConfig?: LanguageConfigMap;
|
|
36
62
|
/**
|
|
37
|
-
* Show a floating selection action popover after a user-created selection
|
|
38
|
-
*
|
|
63
|
+
* Show a floating selection action popover after a user-created selection.
|
|
64
|
+
* Defaults to disabled. Programmatic selection updates do not open it.
|
|
39
65
|
*/
|
|
40
66
|
enabledSelectionAction?: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Configuration for inline edit prediction.
|
|
69
|
+
*/
|
|
70
|
+
editPrediction?: {
|
|
71
|
+
/**
|
|
72
|
+
* The edit prediction mode.
|
|
73
|
+
* - 'eager': predictions appear inline when the user types.
|
|
74
|
+
* - 'subtle': pressing the `Alt` key toggles predictions inline.
|
|
75
|
+
* @default 'eager'
|
|
76
|
+
*/
|
|
77
|
+
mode?: 'eager' | 'subtle';
|
|
78
|
+
/**
|
|
79
|
+
* The edit prediction provider.
|
|
80
|
+
*/
|
|
81
|
+
provider: EditPredictProvider;
|
|
82
|
+
/**
|
|
83
|
+
* Glob or regular-expression patterns for files to include in prediction.
|
|
84
|
+
* String patterns support `?`, segment-local `*`, and cross-segment `**`.
|
|
85
|
+
* An empty array matches no files.
|
|
86
|
+
*/
|
|
87
|
+
include?: readonly (string | RegExp)[];
|
|
88
|
+
/**
|
|
89
|
+
* Glob or regular-expression patterns for files to exclude from prediction.
|
|
90
|
+
* String patterns support `?`, segment-local `*`, and cross-segment `**`.
|
|
91
|
+
* Exclusions take precedence over inclusions.
|
|
92
|
+
*/
|
|
93
|
+
exclude?: readonly (string | RegExp)[];
|
|
94
|
+
};
|
|
41
95
|
/**
|
|
42
96
|
* Custom clipboard provider.
|
|
43
97
|
* Highly recommended to use native clipboard API if you are building an electron app.
|
|
@@ -47,11 +101,25 @@ interface EditorOptions<LAnnotation> {
|
|
|
47
101
|
readText: (type?: string) => Promise<string> | string;
|
|
48
102
|
};
|
|
49
103
|
/** Render the selection action widget element. */
|
|
50
|
-
renderSelectionAction?: (context: SelectionActionContext<LAnnotation>) => HTMLElement;
|
|
104
|
+
renderSelectionAction?: (context: SelectionActionContext<EType, LAnnotation>) => HTMLElement;
|
|
105
|
+
/**
|
|
106
|
+
* Render an externally owned caret at its normalized document position.
|
|
107
|
+
*/
|
|
108
|
+
renderCaret?: (caret: EditorCaret<Caret>) => HTMLElement;
|
|
51
109
|
/** Callback when the editor is attached to a file. */
|
|
52
|
-
onAttach?: (editor: Editor<LAnnotation>, fileInstance:
|
|
53
|
-
/**
|
|
54
|
-
|
|
110
|
+
onAttach?: (editor: Editor<EType, LAnnotation, Caret>, fileInstance: EditorComponent<EType, LAnnotation, Caret>) => void;
|
|
111
|
+
/**
|
|
112
|
+
* Called with an `EditorChangeEvent` whenever the editor document changes.
|
|
113
|
+
* Treat this as a document notification; do not feed the changes back into
|
|
114
|
+
* the editor or you will create loops.
|
|
115
|
+
*/
|
|
116
|
+
onChange?: (event: EditorChangeEvent<EType, LAnnotation, Caret>) => void;
|
|
117
|
+
/**
|
|
118
|
+
* Observes completion with the same frozen event sent to the component. Runs
|
|
119
|
+
* before the component callback, including when the component callback is
|
|
120
|
+
* missing. There is no way to accept or reject from this API.
|
|
121
|
+
*/
|
|
122
|
+
onComplete?: (event: EditorEditCompleteEvent<EType, LAnnotation, Caret>) => void;
|
|
55
123
|
/** Callback when the editor gains focus. */
|
|
56
124
|
onFocus?: () => void;
|
|
57
125
|
/** Callback when the editor loses focus. */
|
|
@@ -66,11 +134,24 @@ interface EditorFocusOptions extends FocusOptions {
|
|
|
66
134
|
/** Non-negative CSS pixels below the viewport or sticky header. */
|
|
67
135
|
offset?: number;
|
|
68
136
|
}
|
|
69
|
-
declare class Editor<LAnnotation
|
|
137
|
+
declare class Editor<EType extends EditorType = EditorType, LAnnotation = undefined, Caret = undefined> {
|
|
70
138
|
#private;
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
139
|
+
readonly type: EType;
|
|
140
|
+
/**
|
|
141
|
+
* @param type The component surface this editor can attach to.
|
|
142
|
+
* @param options Configure editor behavior and lifecycle callbacks.
|
|
143
|
+
* @param editStateKey Retain this editable draft and its undo/redo history
|
|
144
|
+
* in memory so a later editor using the same type and key can resume them.
|
|
145
|
+
*/
|
|
146
|
+
constructor(type: EType, options?: EditorOptions<EType, LAnnotation, Caret>, editStateKey?: string);
|
|
147
|
+
setOptions(options: EditorOptions<EType, LAnnotation, Caret>): void;
|
|
148
|
+
__emitEditComplete(event: EditorEditCompleteEvent<EType, LAnnotation, Caret>): void;
|
|
149
|
+
/** @internal */
|
|
150
|
+
__getGhostTextRows(): ReadonlyMap<number, number>;
|
|
151
|
+
setCarets(carets: EditorCaret<Caret>[]): void;
|
|
152
|
+
edit<T extends EditorComponent<EType, LAnnotation, Caret>>(fileInstance: T extends {
|
|
153
|
+
readonly type: 'unresolved-file';
|
|
154
|
+
} ? never : T): () => void;
|
|
74
155
|
/**
|
|
75
156
|
* Apply edits to current attached file. Every edit joins the undo timeline:
|
|
76
157
|
* a programmatic edit must leave the document and its history exactly as
|
|
@@ -92,27 +173,35 @@ declare class Editor<LAnnotation> implements DiffsEditor<LAnnotation> {
|
|
|
92
173
|
redo(): void;
|
|
93
174
|
getFile(): FileContents | undefined;
|
|
94
175
|
getText(): string;
|
|
95
|
-
|
|
96
|
-
|
|
176
|
+
/** Return an isolated copy of selections and restorable view state. */
|
|
177
|
+
getViewState(): EditorViewState;
|
|
178
|
+
/**
|
|
179
|
+
* Return the objects that make up the active edit session, or undefined when
|
|
180
|
+
* no complete session exists.
|
|
181
|
+
*/
|
|
182
|
+
getEditState(): EditState<EType, LAnnotation> | undefined;
|
|
183
|
+
setViewState({
|
|
97
184
|
selections,
|
|
98
185
|
view
|
|
99
|
-
}:
|
|
186
|
+
}: EditorViewState): void;
|
|
100
187
|
setSelections(selections: (Range & {
|
|
101
188
|
direction: 'none' | 'backward' | 'forward';
|
|
102
189
|
})[]): void;
|
|
103
190
|
setMarkers(markers: Marker[]): void;
|
|
104
191
|
focus(options?: EditorFocusOptions): void;
|
|
105
192
|
blur(): void;
|
|
106
|
-
cleanUp(
|
|
107
|
-
/** @internal Capture outgoing state and substitute cached text before render. */
|
|
108
|
-
__prepareFile(file: FileContents): FileContents;
|
|
193
|
+
cleanUp(reason?: 'discard' | 'recycle' | 'complete'): void;
|
|
109
194
|
/** @internal */
|
|
110
195
|
__postponeBgTokenizeToNextFrame(): void;
|
|
111
196
|
/** @internal */
|
|
112
197
|
__captureFocusForDOMReplacement(): void;
|
|
113
198
|
/** @internal */
|
|
114
|
-
|
|
199
|
+
__getDocumentContents(fallbackFile?: FileContents): FileContents | undefined;
|
|
200
|
+
/** @internal */
|
|
201
|
+
__getDocumentSessionState(): RetainedDiffSessionSnapshot | undefined;
|
|
202
|
+
/** @internal */
|
|
203
|
+
__syncRenderView(props: SyncRenderViewProps<EType, LAnnotation>): void;
|
|
115
204
|
}
|
|
116
205
|
//#endregion
|
|
117
|
-
export { Editor, EditorFocusOptions, EditorOptions };
|
|
206
|
+
export { type EditPredictContext, type EditPredictProvider, type EditPredictRequest, type EditPredictResponse, Editor, EditorFocusOptions, EditorOptions };
|
|
118
207
|
//# sourceMappingURL=editor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editor.d.ts","names":[],"sources":["../../src/editor/editor.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"editor.d.ts","names":[],"sources":["../../src/editor/editor.ts"],"mappings":"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"}
|