@pierre/diffs 1.6.0-beta.1 → 1.6.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 +3 -2
- package/dist/components/CodeView.d.ts.map +1 -1
- package/dist/components/CodeView.js +18 -14
- package/dist/components/CodeView.js.map +1 -1
- package/dist/components/File.d.ts +31 -9
- package/dist/components/File.d.ts.map +1 -1
- package/dist/components/File.js +165 -84
- package/dist/components/File.js.map +1 -1
- package/dist/components/FileDiff.d.ts +32 -9
- package/dist/components/FileDiff.d.ts.map +1 -1
- package/dist/components/FileDiff.js +213 -124
- package/dist/components/FileDiff.js.map +1 -1
- package/dist/components/UnresolvedFile.d.ts +14 -4
- package/dist/components/UnresolvedFile.d.ts.map +1 -1
- package/dist/components/UnresolvedFile.js +35 -16
- package/dist/components/UnresolvedFile.js.map +1 -1
- package/dist/components/VirtualizedFile.d.ts +3 -2
- package/dist/components/VirtualizedFile.d.ts.map +1 -1
- package/dist/components/VirtualizedFile.js +28 -20
- package/dist/components/VirtualizedFile.js.map +1 -1
- package/dist/components/VirtualizedFileDiff.d.ts +3 -2
- package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
- package/dist/components/VirtualizedFileDiff.js +31 -24
- package/dist/components/VirtualizedFileDiff.js.map +1 -1
- package/dist/constants.d.ts +2 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +2 -1
- package/dist/constants.js.map +1 -1
- package/dist/editor/platform.d.ts +1 -1
- package/dist/editor/platform.js +5 -4
- package/dist/editor/platform.js.map +1 -1
- package/dist/editor/selection.d.ts +2 -2
- package/dist/editor/selection.d.ts.map +1 -1
- package/dist/editor/selection.js +31 -6
- package/dist/editor/selection.js.map +1 -1
- package/dist/highlighter/shared_highlighter.d.ts +2 -1
- package/dist/highlighter/shared_highlighter.d.ts.map +1 -1
- package/dist/highlighter/shared_highlighter.js +2 -2
- package/dist/highlighter/shared_highlighter.js.map +1 -1
- package/dist/index.d.ts +10 -5
- package/dist/index.js +8 -3
- package/dist/react/CodeView.d.ts +4 -3
- package/dist/react/CodeView.d.ts.map +1 -1
- package/dist/react/CodeView.js +48 -39
- package/dist/react/CodeView.js.map +1 -1
- package/dist/react/File.js +3 -3
- package/dist/react/File.js.map +1 -1
- package/dist/react/FileDiff.js +3 -3
- package/dist/react/FileDiff.js.map +1 -1
- package/dist/react/MultiFileDiff.js +2 -2
- package/dist/react/MultiFileDiff.js.map +1 -1
- package/dist/react/PatchDiff.js +3 -3
- package/dist/react/PatchDiff.js.map +1 -1
- package/dist/react/UnresolvedFile.js +2 -2
- package/dist/react/UnresolvedFile.js.map +1 -1
- package/dist/react/index.d.ts +2 -2
- package/dist/react/types.d.ts +4 -2
- package/dist/react/types.d.ts.map +1 -1
- package/dist/react/utils/renderDiffChildren.js +1 -1
- package/dist/react/utils/renderDiffChildren.js.map +1 -1
- package/dist/react/utils/renderFileChildren.js +1 -1
- package/dist/react/utils/renderFileChildren.js.map +1 -1
- package/dist/react/utils/useFileDiffInstance.d.ts +1 -0
- package/dist/react/utils/useFileDiffInstance.d.ts.map +1 -1
- package/dist/react/utils/useFileDiffInstance.js +29 -24
- package/dist/react/utils/useFileDiffInstance.js.map +1 -1
- package/dist/react/utils/useFileInstance.d.ts +2 -0
- package/dist/react/utils/useFileInstance.d.ts.map +1 -1
- package/dist/react/utils/useFileInstance.js +38 -28
- package/dist/react/utils/useFileInstance.js.map +1 -1
- package/dist/react/utils/useForceUpdate.d.ts +5 -0
- package/dist/react/utils/useForceUpdate.d.ts.map +1 -0
- package/dist/react/utils/useForceUpdate.js +27 -0
- package/dist/react/utils/useForceUpdate.js.map +1 -0
- package/dist/react/utils/useNextRenderData.d.ts +9 -0
- package/dist/react/utils/useNextRenderData.d.ts.map +1 -0
- package/dist/react/utils/useNextRenderData.js +9 -0
- package/dist/react/utils/useNextRenderData.js.map +1 -0
- package/dist/react/utils/useUnresolvedFileInstance.d.ts +1 -0
- package/dist/react/utils/useUnresolvedFileInstance.d.ts.map +1 -1
- package/dist/react/utils/useUnresolvedFileInstance.js +26 -11
- package/dist/react/utils/useUnresolvedFileInstance.js.map +1 -1
- package/dist/renderers/DiffHunksRenderer.d.ts +2 -1
- package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
- package/dist/renderers/DiffHunksRenderer.js +62 -32
- package/dist/renderers/DiffHunksRenderer.js.map +1 -1
- package/dist/renderers/FileRenderer.d.ts +4 -1
- package/dist/renderers/FileRenderer.d.ts.map +1 -1
- package/dist/renderers/FileRenderer.js +55 -30
- package/dist/renderers/FileRenderer.js.map +1 -1
- package/dist/renderers/UnresolvedFileHunksRenderer.d.ts.map +1 -1
- package/dist/renderers/UnresolvedFileHunksRenderer.js +1 -1
- package/dist/renderers/UnresolvedFileHunksRenderer.js.map +1 -1
- package/dist/ssr/FileDiffReact.js +1 -1
- package/dist/types.d.ts +10 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/canUseWASM.d.ts +13 -0
- package/dist/utils/canUseWASM.d.ts.map +1 -0
- package/dist/utils/canUseWASM.js +59 -0
- package/dist/utils/canUseWASM.js.map +1 -0
- package/dist/utils/getCodeViewItemRenderData.d.ts +10 -0
- package/dist/utils/getCodeViewItemRenderData.d.ts.map +1 -0
- package/dist/utils/getCodeViewItemRenderData.js +19 -0
- package/dist/utils/getCodeViewItemRenderData.js.map +1 -0
- package/dist/utils/hastToHtml.d.ts +2 -2
- package/dist/utils/hastToHtml.js +2 -2
- package/dist/utils/hastToHtml.js.map +1 -1
- package/dist/utils/hydratePartialDiff.js +4 -0
- package/dist/utils/hydratePartialDiff.js.map +1 -1
- package/dist/utils/parseMergeConflictDiffFromFile.d.ts.map +1 -1
- package/dist/utils/parseMergeConflictDiffFromFile.js +2 -0
- package/dist/utils/parseMergeConflictDiffFromFile.js.map +1 -1
- package/dist/utils/parsePatchFiles.d.ts.map +1 -1
- package/dist/utils/parsePatchFiles.js +24 -4
- package/dist/utils/parsePatchFiles.js.map +1 -1
- package/dist/utils/renderTokenLines.d.ts +6 -1
- package/dist/utils/renderTokenLines.d.ts.map +1 -1
- package/dist/utils/renderTokenLines.js +4 -0
- package/dist/utils/renderTokenLines.js.map +1 -1
- package/dist/utils/resolveRegion.js +20 -10
- package/dist/utils/resolveRegion.js.map +1 -1
- package/dist/utils/tokenStyle.d.ts +5 -1
- package/dist/utils/tokenStyle.d.ts.map +1 -1
- package/dist/utils/tokenStyle.js +5 -1
- package/dist/utils/tokenStyle.js.map +1 -1
- package/dist/utils/tokensToHtml.d.ts +5 -2
- package/dist/utils/tokensToHtml.d.ts.map +1 -1
- package/dist/utils/tokensToHtml.js +5 -2
- package/dist/utils/tokensToHtml.js.map +1 -1
- package/dist/utils/updateDiffHunks.d.ts +2 -2
- package/dist/utils/updateDiffHunks.d.ts.map +1 -1
- package/dist/utils/updateDiffHunks.js +7 -3
- package/dist/utils/updateDiffHunks.js.map +1 -1
- package/dist/worker/WorkerPoolManager.d.ts +12 -0
- package/dist/worker/WorkerPoolManager.d.ts.map +1 -1
- package/dist/worker/WorkerPoolManager.js +99 -21
- package/dist/worker/WorkerPoolManager.js.map +1 -1
- package/dist/worker/{highlights-sAHlxqlf.js → highlights-CpZm9DAR.js} +2 -2
- package/dist/worker/{highlights-sAHlxqlf.js.map → highlights-CpZm9DAR.js.map} +1 -1
- package/dist/worker/{shiki-Bx2JpdqZ.js → shiki-Ci4cdHsM.js} +2 -2
- package/dist/worker/{shiki-Bx2JpdqZ.js.map → shiki-Ci4cdHsM.js.map} +1 -1
- package/dist/worker/{stream-tokenizer-YZ6M1qSx.js → stream-tokenizer-DK9xp5M5.js} +8 -5
- package/dist/worker/stream-tokenizer-DK9xp5M5.js.map +1 -0
- package/dist/worker/types.d.ts +11 -0
- package/dist/worker/types.d.ts.map +1 -1
- package/dist/worker/worker-portable.js +4 -4
- package/dist/worker/worker-portable.js.map +1 -1
- package/dist/worker/worker.js +12 -3
- package/dist/worker/worker.js.map +1 -1
- package/package.json +28 -30
- package/dist/worker/stream-tokenizer-YZ6M1qSx.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selection.js","names":[],"sources":["../../src/editor/selection.ts"],"sourcesContent":["import { applyDocumentChangeToLineAnnotations } from './lineAnnotations';\nimport type { TextDocument, TextDocumentChange } from './textDocument';\nimport type {\n EditorLineAnnotation,\n EditorSelection,\n EditorType,\n Position,\n Range,\n ResolvedTextEdit,\n SelectionDirection,\n TextEdit,\n} from './types';\nimport {\n createSegmenter,\n endsWithLineBreak,\n getGraphemeSegmenter,\n} from './utils';\n\nexport const DirectionBackward = -1;\nexport const DirectionNone = 0;\nexport const DirectionForward = 1;\n\nconst SURROUNDING_PAIRS: Array<[openChar: string, closeChar: string]> = [\n [\"'\", \"'\"],\n ['\"', '\"'],\n ['`', '`'],\n ['{', '}'],\n ['[', ']'],\n ['<', '>'],\n ['(', ')'],\n];\n\nconst AUTO_SURROUND_CLOSE_CHARS = new Map(SURROUNDING_PAIRS);\nconst AUTO_SURROUND_QUOTE_CHARS = new Set([\"'\", '\"', '`']);\nconst AUTO_SURROUND_BRACKET_CHARS = new Set(['{', '[', '(', '<']);\n\nexport interface CursorMoveOptions {\n getSoftLineOffsets?: (line: number) => ArrayLike<number> | undefined;\n /**\n * Fold-skip resolver for vertical motion crossing document lines: the\n * nearest renderable line at or beyond the target in the move direction,\n * or undefined when everything that way is hidden inside a collapsed\n * region (the caret then stays put). Soft-line moves within one document\n * line never consult it.\n */\n resolveRenderableLine?: ResolveRenderableLine;\n}\n\ninterface SoftLineInfo {\n start: number;\n end: number;\n index: number;\n count: number;\n}\n\n/**\n * Converts a selection from a web selection to an editor selection.\n */\nexport function convertSelection(\n range: StaticRange,\n direction: SelectionDirection = DirectionNone\n): EditorSelection | undefined {\n const start = boundaryToPosition(range.startContainer, range.startOffset);\n const end = boundaryToPosition(range.endContainer, range.endOffset);\n if (start === null || end === null) {\n return undefined;\n }\n return {\n start,\n end,\n direction,\n };\n}\n\n/**\n * Resolves the indent edits for a selection.\n */\nexport function resolveIndentEdits(\n textDocument: TextDocument,\n selection: EditorSelection,\n tabSize: number,\n outdent: boolean\n): [edits: TextEdit[], nextSelection: EditorSelection] {\n if (textDocument === undefined) {\n return [[], selection];\n }\n const { start, end } = selection;\n const edits: TextEdit[] = [];\n let newSelection: EditorSelection = { ...selection };\n const blockIndent = start.line !== end.line;\n let endLine = end.line;\n if (start.line < end.line && end.character === 0) {\n endLine--;\n }\n for (let line = start.line; line <= endLine; line++) {\n const lineText = textDocument.getLineText(line);\n if (lineText === undefined) {\n continue;\n }\n if (blockIndent && lineText.trim().length === 0) {\n continue;\n }\n const indentUnit = lineText.startsWith('\\t') ? '\\t' : ' '.repeat(tabSize);\n let deleteLength = 0;\n let newText = indentUnit;\n if (outdent) {\n if (lineText.startsWith('\\t')) {\n deleteLength = 1;\n } else if (lineText.startsWith(' ')) {\n const leadingSpacesLength =\n lineText.length - lineText.trimStart().length;\n deleteLength = Math.min(indentUnit.length, leadingSpacesLength);\n }\n if (deleteLength === 0) {\n continue;\n }\n newText = '';\n }\n edits.push({\n range: {\n start: { line, character: 0 },\n end: { line, character: deleteLength },\n },\n newText,\n });\n const delta = newText.length - deleteLength;\n if (line === start.line) {\n newSelection = {\n ...newSelection,\n start: {\n ...start,\n character: Math.max(0, start.character + delta),\n },\n };\n }\n if (line === end.line) {\n newSelection = {\n ...newSelection,\n end: {\n ...end,\n character: Math.max(0, end.character + delta),\n },\n };\n }\n }\n return [edits, newSelection];\n}\n\n/**\n * The nearest zero-based document line at or beyond `line` in `direction`\n * that has a rendered row, or undefined when everything that way is hidden\n * inside a collapsed region. Vertical caret motion uses it to skip collapsed\n * regions atomically, like code folds.\n */\nexport type ResolveRenderableLine = (\n line: number,\n direction: 'up' | 'down'\n) => number | undefined;\n\n/**\n * Maps the cursor move to all selections.\n */\nexport function mapCursorMove(\n textDocument: TextDocument,\n selections: EditorSelection[],\n shortcut: 'textStart' | 'start' | 'end' | 'up' | 'down' | 'left' | 'right',\n options: CursorMoveOptions = {}\n): EditorSelection[] {\n const lineCount = textDocument.lineCount;\n return selections.map((selection) => {\n let { line, character } =\n shortcut === 'up' || shortcut === 'left'\n ? selection.start\n : selection.end;\n if (\n shortcut === 'textStart' ||\n shortcut === 'start' ||\n shortcut === 'end'\n ) {\n const caret = getCaretPosition(selection);\n line = caret.line;\n character = caret.character;\n const softLine = getSoftLineInfo(textDocument, line, character, options);\n if (shortcut === 'textStart') {\n const softLineText = textDocument\n .getLineText(line)\n .slice(softLine.start, softLine.end);\n const indent = softLine.start + getLeadingSpaces(softLineText);\n character = character === indent ? softLine.start : indent;\n } else {\n character = shortcut === 'start' ? softLine.start : softLine.end;\n }\n } else if (shortcut === 'up') {\n const moved = moveBySoftLine(textDocument, line, character, -1, options);\n if (moved !== undefined) {\n line = moved.line;\n character = moved.character;\n } else if (line > 0) {\n // Fold-skip: when the line above is collapsed, jump to the nearest\n // renderable line above it; stay put when nothing above renders.\n line =\n options.resolveRenderableLine == null\n ? line - 1\n : (options.resolveRenderableLine(line - 1, 'up') ?? line);\n }\n } else if (shortcut === 'down') {\n const moved = moveBySoftLine(textDocument, line, character, 1, options);\n if (moved !== undefined) {\n line = moved.line;\n character = moved.character;\n } else {\n const maxLine = Math.max(lineCount - 1, 0);\n if (line < maxLine) {\n line =\n options.resolveRenderableLine == null\n ? line + 1\n : Math.min(\n options.resolveRenderableLine(line + 1, 'down') ?? line,\n maxLine\n );\n }\n }\n } else if (isCollapsedSelection(selection)) {\n const lineLength = textDocument.getLineLength(line);\n character = Math.min(character, lineLength);\n if (shortcut === 'left') {\n if (character > 0) {\n // Step left by a whole grapheme so the caret never lands inside an\n // emoji or other multi-code-unit character.\n character = stepCharacterByGrapheme(\n textDocument,\n line,\n character,\n false\n );\n } else if (line > 0) {\n // Fold-skip: land at the end of the nearest renderable line above;\n // stay put when everything above is collapsed.\n const targetLine =\n options.resolveRenderableLine == null\n ? line - 1\n : options.resolveRenderableLine(line - 1, 'up');\n if (targetLine !== undefined) {\n line = targetLine;\n character = textDocument.getLineLength(line);\n }\n }\n } else if (character < lineLength) {\n character = stepCharacterByGrapheme(\n textDocument,\n line,\n character,\n true\n );\n } else if (line < lineCount - 1) {\n // Fold-skip: land at the start of the nearest renderable line below;\n // stay put when everything below is collapsed.\n const targetLine =\n options.resolveRenderableLine == null\n ? line + 1\n : options.resolveRenderableLine(line + 1, 'down');\n if (targetLine !== undefined) {\n line = Math.min(targetLine, lineCount - 1);\n character = 0;\n }\n }\n }\n const pos = { line, character };\n return {\n start: pos,\n end: pos,\n direction: DirectionNone,\n };\n });\n}\n\nfunction moveBySoftLine(\n textDocument: TextDocument,\n line: number,\n character: number,\n direction: -1 | 1,\n options: CursorMoveOptions\n): Position | undefined {\n if (options.getSoftLineOffsets === undefined) {\n return undefined;\n }\n\n const current = getSoftLineInfo(textDocument, line, character, options);\n const targetIndex = current.index + direction;\n let targetLine = line;\n let target: SoftLineInfo;\n\n if (targetIndex >= 0 && targetIndex < current.count) {\n target = getSoftLineInfoAtIndex(\n textDocument,\n targetLine,\n targetIndex,\n options\n );\n } else {\n const nextLine = line + direction;\n if (nextLine < 0 || nextLine >= textDocument.lineCount) {\n return { line, character };\n }\n\n // Fold-skip: crossing to another document line skips collapsed regions;\n // when nothing renders in that direction the caret stays put.\n const resolvedLine =\n options.resolveRenderableLine == null\n ? nextLine\n : options.resolveRenderableLine(\n nextLine,\n direction < 0 ? 'up' : 'down'\n );\n if (resolvedLine === undefined) {\n return { line, character };\n }\n\n targetLine = Math.min(resolvedLine, textDocument.lineCount - 1);\n const targetCount = getSoftLineCount(targetLine, options);\n target = getSoftLineInfoAtIndex(\n textDocument,\n targetLine,\n direction < 0 ? targetCount - 1 : 0,\n options\n );\n }\n\n const column = Math.max(0, character - current.start);\n const targetCharacter = target.start + column;\n const landedCharacter =\n target.index === target.count - 1\n ? targetCharacter\n : Math.min(targetCharacter, target.end);\n const targetLineText = textDocument.getLineText(targetLine);\n // Keep goal-column overshoots, but snap real offsets out of graphemes.\n return {\n line: targetLine,\n character:\n landedCharacter > targetLineText.length\n ? landedCharacter\n : snapCharacterToGraphemeBoundary(targetLineText, landedCharacter),\n };\n}\n\n// Snaps an editable position to the end of its grapheme so edits cannot split\n// a user-visible character. Stop once the containing cluster is resolved.\nexport function snapCharacterToGraphemeBoundary(\n lineText: string,\n character: number\n): number {\n if (character <= 0 || character >= lineText.length) {\n return character;\n }\n\n const segmenter = getGraphemeSegmenter();\n if (segmenter !== undefined) {\n for (const segment of segmenter.segment(lineText)) {\n if (character <= segment.index) {\n return character;\n }\n const segmentEnd = segment.index + segment.segment.length;\n if (character < segmentEnd) {\n return segmentEnd;\n }\n }\n return character;\n }\n\n // Degraded path for engines lacking Intl.Segmenter: preserve code points.\n let segmentStart = 0;\n for (const codePoint of lineText) {\n if (character <= segmentStart) {\n return character;\n }\n const segmentEnd = segmentStart + codePoint.length;\n if (character < segmentEnd) {\n return segmentEnd;\n }\n segmentStart = segmentEnd;\n }\n return character;\n}\n\nfunction getSoftLineInfo(\n textDocument: TextDocument,\n line: number,\n character: number,\n options: CursorMoveOptions\n): SoftLineInfo {\n const lineLength = textDocument.getLineLength(line);\n const offsets = options.getSoftLineOffsets?.(line);\n if (offsets === undefined || offsets.length < 2) {\n return { start: 0, end: lineLength, index: 0, count: 1 };\n }\n\n for (let index = 0; index + 1 < offsets.length; index++) {\n const softLine = getSoftLineInfoAtIndex(textDocument, line, index, options);\n if (character >= softLine.start && character <= softLine.end) {\n return softLine;\n }\n }\n\n return getSoftLineInfoAtIndex(\n textDocument,\n line,\n character < (offsets[0] ?? 0) ? 0 : offsets.length - 2,\n options\n );\n}\n\nfunction getSoftLineCount(line: number, options: CursorMoveOptions): number {\n const offsets = options.getSoftLineOffsets?.(line);\n return offsets === undefined || offsets.length < 2 ? 1 : offsets.length - 1;\n}\n\nfunction getSoftLineInfoAtIndex(\n textDocument: TextDocument,\n line: number,\n index: number,\n options: CursorMoveOptions\n): SoftLineInfo {\n const lineLength = textDocument.getLineLength(line);\n const offsets = options.getSoftLineOffsets?.(line);\n if (offsets === undefined || offsets.length < 2) {\n return { start: 0, end: lineLength, index: 0, count: 1 };\n }\n\n const count = offsets.length - 1;\n const boundedIndex = Math.max(0, Math.min(index, count - 1));\n const start = Math.max(0, Math.min(lineLength, offsets[boundedIndex] ?? 0));\n const end = Math.max(\n start,\n Math.min(lineLength, offsets[boundedIndex + 1] ?? lineLength)\n );\n return { start, end, index: boundedIndex, count };\n}\n\n/**\n * Same as mapCursorMove, but with shift key pressed.\n */\nexport function mapSelectionShift(\n textDocument: TextDocument,\n selections: EditorSelection[],\n shortcut: 'textStart' | 'start' | 'end' | 'up' | 'down' | 'left' | 'right',\n options: CursorMoveOptions = {}\n): EditorSelection[] {\n return selections.map((selection) => {\n const focusPosition =\n selection.direction === DirectionBackward\n ? selection.start\n : selection.end;\n const [movedFocusSelection] = mapCursorMove(\n textDocument,\n [\n {\n start: focusPosition,\n end: focusPosition,\n direction: DirectionNone,\n },\n ],\n shortcut,\n options\n );\n return createSelectionFrom(selection, movedFocusSelection);\n });\n}\n\n/**\n * Applies a text change to the given text document\n */\nexport function applyTextChangeToSelections<\n EType extends EditorType,\n LAnnotation,\n>(\n textDocument: TextDocument<EType, LAnnotation>,\n selections: EditorSelection[],\n edit: ResolvedTextEdit,\n lineAnnotations?: EditorLineAnnotation<EType, LAnnotation>[],\n tabSize = 2,\n undoBoundary = false\n): {\n nextSelections: EditorSelection[];\n change?: TextDocumentChange;\n} {\n const primarySelection = selections[selections.length - 1];\n if (primarySelection === undefined) {\n return { nextSelections: [] };\n }\n const selectionPositions: Position[] = [];\n for (const selection of selections) {\n selectionPositions.push(selection.start, selection.end);\n }\n const selectionOffsets = selectionPositions.map((position) =>\n textDocument.offsetAt(position)\n );\n const primaryStartOffset = selectionOffsets[(selections.length - 1) * 2];\n const primaryEndOffset = selectionOffsets[(selections.length - 1) * 2 + 1];\n const ordered: Array<{\n index: number;\n start: number;\n end: number;\n }> = [];\n let isAlreadyOrdered = true;\n for (let index = 0; index < selections.length; index++) {\n const entry = {\n index,\n start: selectionOffsets[index * 2],\n end: selectionOffsets[index * 2 + 1],\n };\n const previous = ordered[ordered.length - 1];\n if (\n previous !== undefined &&\n (entry.start < previous.start ||\n (entry.start === previous.start && entry.end < previous.end))\n ) {\n isAlreadyOrdered = false;\n }\n ordered.push(entry);\n }\n if (!isAlreadyOrdered) {\n ordered.sort((a, b) => {\n const startOrder = a.start - b.start;\n if (startOrder !== 0) {\n return startOrder;\n }\n const endOrder = a.end - b.end;\n if (endOrder !== 0) {\n return endOrder;\n }\n return a.index - b.index;\n });\n }\n const adjustedChange = normalizeLeadingIndentForChange(\n textDocument,\n edit,\n tabSize\n );\n const edits: ResolvedTextEdit[] = [];\n const nextSelectionOffsets: Array<[number, number] | undefined> = Array.from({\n length: selections.length,\n });\n let offsetDelta = 0;\n let mergedGroup:\n | {\n start: number;\n end: number;\n indices: number[];\n }\n | undefined;\n const finalizeMergedGroup = () => {\n if (mergedGroup === undefined) {\n return;\n }\n const perGroupChange = normalizeLeadingIndentForChange(\n textDocument,\n {\n start: mergedGroup.start,\n end: mergedGroup.end,\n text: adjustedChange.text,\n },\n tabSize\n );\n const newText = expandSingleNewlineInsert(\n textDocument,\n perGroupChange.text,\n perGroupChange.start\n );\n edits.push({\n start: perGroupChange.start,\n end: perGroupChange.end,\n text: newText,\n });\n const nextOffsets: [number, number] = [\n mergedGroup.start + offsetDelta + newText.length,\n mergedGroup.start + offsetDelta + newText.length,\n ];\n for (const index of mergedGroup.indices) {\n nextSelectionOffsets[index] = nextOffsets;\n }\n offsetDelta += newText.length - (perGroupChange.end - perGroupChange.start);\n mergedGroup = undefined;\n };\n for (const entry of ordered) {\n const startOffset = Math.max(\n 0,\n entry.start + (adjustedChange.start - primaryStartOffset)\n );\n const endOffset = Math.max(\n startOffset,\n entry.end + (adjustedChange.end - primaryEndOffset)\n );\n if (mergedGroup !== undefined && startOffset < mergedGroup.end) {\n mergedGroup.end = Math.max(mergedGroup.end, endOffset);\n mergedGroup.indices.push(entry.index);\n continue;\n }\n finalizeMergedGroup();\n mergedGroup = {\n start: startOffset,\n end: endOffset,\n indices: [entry.index],\n };\n }\n finalizeMergedGroup();\n\n const change = textDocument.applyResolvedEdits(\n edits,\n true,\n selections,\n undefined,\n undoBoundary\n );\n const nextSelections = createSelectionsFromOffsetPairs(\n textDocument,\n nextSelectionOffsets.map((offsets) => {\n if (offsets === undefined) {\n throw new Error('Missing next selection offsets');\n }\n return offsets;\n })\n );\n textDocument.setLastUndoSelectionsAfter(nextSelections);\n if (change !== undefined && lineAnnotations !== undefined) {\n const nextLineAnnotations = applyDocumentChangeToLineAnnotations(\n change,\n lineAnnotations\n );\n if (nextLineAnnotations !== undefined) {\n textDocument.setLastUndoLineAnnotations(\n lineAnnotations,\n nextLineAnnotations\n );\n }\n }\n return { nextSelections, change };\n}\n\n/**\n * Returns the next anchor/focus offsets after replacing a selection range.\n * When the inserted text still contains the original selection (auto-surround),\n * the inner range is reselected to match VS Code/CodeMirror behavior.\n */\n// Detect exact auto-surround replacements before a substring search can match\n// the newly inserted opening delimiter instead of the preserved selection.\nfunction getAutoSurroundPreservedOffset(\n originalText: string,\n newText: string\n): number | undefined {\n if (newText.length !== originalText.length + 2) {\n return undefined;\n }\n\n const closeChar = AUTO_SURROUND_CLOSE_CHARS.get(newText[0]);\n if (\n closeChar === undefined ||\n newText[newText.length - 1] !== closeChar ||\n newText.slice(1, -1) !== originalText\n ) {\n return undefined;\n }\n\n return 1;\n}\n\nfunction getNextSelectionOffsetPairAfterReplace(\n textDocument: TextDocument,\n entry: { start: number; end: number },\n offsetDelta: number,\n newText: string\n): [number, number] {\n const insertStart = entry.start + offsetDelta;\n const insertEnd = insertStart + newText.length;\n const originalLength = entry.end - entry.start;\n if (originalLength > 0) {\n const originalText = textDocument.getTextSlice(entry.start, entry.end);\n const preservedOffset =\n getAutoSurroundPreservedOffset(originalText, newText) ??\n newText.indexOf(originalText);\n if (\n preservedOffset !== -1 &&\n preservedOffset + originalText.length <= newText.length\n ) {\n const rangeStart = insertStart + preservedOffset;\n return [rangeStart, rangeStart + originalText.length];\n }\n }\n return [insertEnd, insertEnd];\n}\n\n/**\n * Applies text replacements to multiple selections. Texts pair by selection\n * index unless they are explicitly marked as document ordered.\n */\nexport function applyTextReplaceToSelections<\n EType extends EditorType,\n LAnnotation,\n>(\n textDocument: TextDocument<EType, LAnnotation>,\n selections: EditorSelection[],\n texts: string[],\n lineAnnotations?: EditorLineAnnotation<EType, LAnnotation>[],\n undoBoundary = false,\n textOrder: 'selection' | 'document' = 'selection'\n): {\n nextSelections: EditorSelection[];\n change?: TextDocumentChange;\n} {\n if (selections.length !== texts.length) {\n throw new Error(\n 'Selection text replacements must match the selection count'\n );\n }\n const selectionPositions: Position[] = [];\n for (const selection of selections) {\n selectionPositions.push(selection.start, selection.end);\n }\n const selectionOffsets = selectionPositions.map((position) =>\n textDocument.offsetAt(position)\n );\n const ordered: Array<{\n index: number;\n start: number;\n end: number;\n }> = [];\n let isAlreadyOrdered = true;\n for (let index = 0; index < selections.length; index++) {\n const entry = {\n index,\n start: selectionOffsets[index * 2],\n end: selectionOffsets[index * 2 + 1],\n };\n const previous = ordered[ordered.length - 1];\n if (\n previous !== undefined &&\n (entry.start < previous.start ||\n (entry.start === previous.start && entry.end < previous.end))\n ) {\n isAlreadyOrdered = false;\n }\n ordered.push(entry);\n }\n if (!isAlreadyOrdered) {\n ordered.sort((a, b) => {\n const startOrder = a.start - b.start;\n if (startOrder !== 0) {\n return startOrder;\n }\n const endOrder = a.end - b.end;\n if (endOrder !== 0) {\n return endOrder;\n }\n return a.index - b.index;\n });\n }\n const allDeletes = texts.every((text) => text === '');\n let edits: ResolvedTextEdit[];\n const nextSelectionOffsetPairs: Array<[number, number] | undefined> =\n Array.from({\n length: selections.length,\n });\n if (allDeletes) {\n edits = [];\n let hasEffect = false;\n for (const entry of ordered) {\n nextSelectionOffsetPairs[entry.index] = [entry.end, entry.end];\n if (entry.start >= entry.end) {\n continue;\n }\n hasEffect = true;\n const last = edits[edits.length - 1];\n if (last !== undefined && entry.start < last.end) {\n edits[edits.length - 1] = {\n start: last.start,\n end: Math.max(last.end, entry.end),\n text: '',\n };\n } else {\n edits.push({ start: entry.start, end: entry.end, text: '' });\n }\n }\n if (!hasEffect) {\n return { nextSelections: selections };\n }\n for (const entry of ordered) {\n const caret = entry.end;\n let delta = 0;\n let next = caret;\n for (const edit of edits) {\n if (caret <= edit.start) {\n break;\n }\n if (caret >= edit.end) {\n delta -= edit.end - edit.start;\n continue;\n }\n next = edit.start + delta;\n break;\n }\n if (next === caret) {\n next += delta;\n }\n nextSelectionOffsetPairs[entry.index] = [next, next];\n }\n } else {\n edits = [];\n let offsetDelta = 0;\n let previousEditEnd = -1;\n for (let index = 0; index < ordered.length; index++) {\n const entry = ordered[index];\n if (entry.start < previousEditEnd) {\n throw new Error('Overlapping multi-selection edits are not supported');\n }\n previousEditEnd = entry.end;\n const newText = expandSingleNewlineInsert(\n textDocument,\n texts[textOrder === 'document' ? index : entry.index],\n entry.start\n );\n edits.push({\n start: entry.start,\n end: entry.end,\n text: newText,\n });\n nextSelectionOffsetPairs[entry.index] =\n getNextSelectionOffsetPairAfterReplace(\n textDocument,\n entry,\n offsetDelta,\n newText\n );\n offsetDelta += newText.length - (entry.end - entry.start);\n }\n }\n\n const change = textDocument.applyResolvedEdits(\n edits,\n true,\n selections,\n undefined,\n undoBoundary\n );\n const nextSelections = createSelectionsFromOffsetPairs(\n textDocument,\n nextSelectionOffsetPairs.map((offsets) => {\n if (offsets === undefined) {\n throw new Error('Missing next selection offsets');\n }\n return offsets;\n })\n );\n textDocument.setLastUndoSelectionsAfter(nextSelections);\n if (change !== undefined && lineAnnotations !== undefined) {\n const nextLineAnnotations = applyDocumentChangeToLineAnnotations(\n change,\n lineAnnotations\n );\n if (nextLineAnnotations !== undefined) {\n textDocument.setLastUndoLineAnnotations(\n lineAnnotations,\n nextLineAnnotations\n );\n }\n }\n return { nextSelections, change };\n}\n\nexport type AutoSurround =\n | 'default'\n | 'never'\n | 'brackets'\n | 'quotes'\n | 'languageDefined';\n\nfunction shouldAutoSurroundChar(\n autoSurround: AutoSurround | undefined,\n char: string\n): boolean {\n if (autoSurround === 'never') {\n return false;\n }\n if (autoSurround === 'brackets') {\n return AUTO_SURROUND_BRACKET_CHARS.has(char);\n }\n if (autoSurround === 'quotes') {\n return AUTO_SURROUND_QUOTE_CHARS.has(char);\n }\n return true;\n}\n\n/**\n * Returns per-selection replacement text when typing a surround character over\n * non-collapsed selections, matching VS Code auto-surround behavior.\n */\nexport function getAutoSurroundReplacementTexts(\n textDocument: TextDocument,\n selections: EditorSelection[],\n char: string,\n autoSurround?: AutoSurround\n): string[] | undefined {\n if (char.length !== 1 || selections.length === 0) {\n return undefined;\n }\n const closeChar = AUTO_SURROUND_CLOSE_CHARS.get(char);\n if (closeChar === undefined || !shouldAutoSurroundChar(autoSurround, char)) {\n return undefined;\n }\n const replacements: string[] = [];\n for (const selection of selections) {\n if (isCollapsedSelection(selection)) {\n return undefined;\n }\n replacements.push(char + textDocument.getText(selection) + closeChar);\n }\n return replacements;\n}\n\n/**\n * Swaps the two characters adjacent to a collapsed selection, matching browser\n * insertTranspose (Ctrl+T) behavior.\n */\nexport function applyTransposeToSelections<\n EType extends EditorType,\n LAnnotation,\n>(\n textDocument: TextDocument<EType, LAnnotation>,\n selections: EditorSelection[],\n lineAnnotations?: EditorLineAnnotation<EType, LAnnotation>[]\n): {\n nextSelections: EditorSelection[];\n change?: TextDocumentChange;\n} {\n const edits: ResolvedTextEdit[] = [];\n const nextOffsetPairs: Array<[number, number]> = [];\n\n for (const selection of selections) {\n const [anchor, focus] = getSelectionAnchorAndFocusOffsets(\n textDocument,\n selection\n );\n if (!isCollapsedSelection(selection)) {\n nextOffsetPairs.push([anchor, focus]);\n continue;\n }\n\n const { line, character } = selection.start;\n const offset = anchor;\n const lineText = textDocument.getLineText(line);\n const lineLength = lineText.length;\n // Document offset of column 0 on this line, used to translate the\n // grapheme-cluster columns below back into document offsets.\n const lineStart = offset - character;\n const graphemeStarts = getLineGraphemeStarts(lineText);\n let edit: ResolvedTextEdit | undefined;\n\n if (character > 0 && character < lineLength) {\n // Swap the whole grapheme before the caret with the one after it so a\n // surrogate pair (emoji) on either side is moved intact.\n const before = findClusterBreak(\n lineText,\n character,\n false,\n graphemeStarts\n );\n const after = findClusterBreak(lineText, character, true, graphemeStarts);\n edit = {\n start: lineStart + before,\n end: lineStart + after,\n text:\n lineText.slice(character, after) + lineText.slice(before, character),\n };\n nextOffsetPairs.push([lineStart + after, lineStart + after]);\n } else if (character === lineLength && graphemeStarts.length >= 2) {\n // Swap the last two graphemes on the line.\n const lastStart = graphemeStarts[graphemeStarts.length - 1];\n const secondLastStart = graphemeStarts[graphemeStarts.length - 2];\n edit = {\n start: lineStart + secondLastStart,\n end: offset,\n text:\n lineText.slice(lastStart, lineLength) +\n lineText.slice(secondLastStart, lastStart),\n };\n nextOffsetPairs.push([offset, offset]);\n } else if (character === 0 && line > 0 && lineLength > 0) {\n // Carry the previous line's last grapheme and this line's first grapheme\n // across the line break, swapping their order.\n const prevLine = line - 1;\n const prevLineText = textDocument.getLineText(prevLine);\n const prevLength = prevLineText.length;\n const prevEnd = textDocument.offsetAt({\n line: prevLine,\n character: prevLength,\n });\n const prevGraphemeStart =\n prevLength > 0\n ? findClusterBreak(\n prevLineText,\n prevLength,\n false,\n getLineGraphemeStarts(prevLineText)\n )\n : prevLength;\n const firstEnd = findClusterBreak(lineText, 0, true, graphemeStarts);\n const prevStart = prevEnd - (prevLength - prevGraphemeStart);\n const newText =\n lineText.slice(0, firstEnd) +\n textDocument.getTextSlice(prevEnd, offset) +\n prevLineText.slice(prevGraphemeStart, prevLength);\n edit = {\n start: prevStart,\n end: offset + firstEnd,\n text: newText,\n };\n const caret = prevStart + newText.length;\n nextOffsetPairs.push([caret, caret]);\n } else {\n nextOffsetPairs.push([anchor, focus]);\n continue;\n }\n\n edits.push(edit);\n }\n\n if (edits.length === 0) {\n return { nextSelections: selections };\n }\n\n edits.sort((a, b) => a.start - b.start);\n for (let index = 1; index < edits.length; index++) {\n if (edits[index].start < edits[index - 1].end) {\n throw new Error('Overlapping multi-selection edits are not supported');\n }\n }\n\n const change = textDocument.applyResolvedEdits(edits, true, selections);\n const nextSelections = createSelectionsFromOffsetPairs(\n textDocument,\n nextOffsetPairs\n );\n textDocument.setLastUndoSelectionsAfter(nextSelections);\n if (change !== undefined && lineAnnotations !== undefined) {\n const nextLineAnnotations = applyDocumentChangeToLineAnnotations(\n change,\n lineAnnotations\n );\n if (nextLineAnnotations !== undefined) {\n textDocument.setLastUndoLineAnnotations(\n lineAnnotations,\n nextLineAnnotations\n );\n }\n }\n return { nextSelections, change };\n}\n\n/**\n * Deletes from each selection to the end of its line, including the line break\n * when the caret is already at the end of a non-final line. Non-collapsed\n * selections delete their selected text instead.\n */\nexport function applyDeleteHardLineForwardToSelections<\n EType extends EditorType,\n LAnnotation,\n>(\n textDocument: TextDocument<EType, LAnnotation>,\n selections: EditorSelection[],\n lineAnnotations?: EditorLineAnnotation<EType, LAnnotation>[]\n): {\n nextSelections: EditorSelection[];\n change?: TextDocumentChange;\n} {\n const deleteSelections: EditorSelection[] = selections.map((selection) => {\n const range = resolveDeleteHardLineForwardRange(textDocument, selection);\n return {\n start: range.start,\n end: range.end,\n direction: DirectionNone,\n };\n });\n return applyTextReplaceToSelections(\n textDocument,\n deleteSelections,\n deleteSelections.map(() => ''),\n lineAnnotations\n );\n}\n\n/**\n * Deletes from each selection back to the start of its soft (visual) line.\n * Non-collapsed selections delete their selected text instead.\n */\nexport function applyDeleteSoftLineBackwardToSelections<\n EType extends EditorType,\n LAnnotation,\n>(\n textDocument: TextDocument<EType, LAnnotation>,\n selections: EditorSelection[],\n getSoftLineStart?: (line: number, character: number) => number,\n lineAnnotations?: EditorLineAnnotation<EType, LAnnotation>[]\n): {\n nextSelections: EditorSelection[];\n change?: TextDocumentChange;\n} {\n const deleteSelections: EditorSelection[] = selections.map((selection) => {\n if (!isCollapsedSelection(selection)) {\n return {\n start: selection.start,\n end: selection.end,\n direction: DirectionNone,\n };\n }\n const caret = getCaretPosition(selection);\n const { line, character } = caret;\n const softLineStart = getSoftLineStart?.(line, character) ?? 0;\n if (character > softLineStart) {\n return {\n start: { line, character: softLineStart },\n end: { line, character },\n direction: DirectionNone,\n };\n }\n if (line === 0) {\n return {\n start: caret,\n end: caret,\n direction: DirectionNone,\n };\n }\n const prevLineLength = textDocument.getLineLength(line - 1);\n return {\n start: { line: line - 1, character: prevLineLength },\n end: { line, character: 0 },\n direction: DirectionNone,\n };\n });\n return applyTextReplaceToSelections(\n textDocument,\n deleteSelections,\n deleteSelections.map(() => ''),\n lineAnnotations\n );\n}\n\n/**\n * Deletes the word or separator group immediately before each selection.\n * Non-collapsed selections delete their selected text instead.\n */\nexport function applyDeleteWordBackwardToSelections<\n EType extends EditorType,\n LAnnotation,\n>(\n textDocument: TextDocument<EType, LAnnotation>,\n selections: EditorSelection[],\n lineAnnotations?: EditorLineAnnotation<EType, LAnnotation>[]\n): {\n nextSelections: EditorSelection[];\n change?: TextDocumentChange;\n} {\n const deleteSelections: EditorSelection[] = selections.map((selection) => {\n const [start, end] = resolveDeleteWordBackwardRange(\n textDocument,\n selection\n );\n return {\n start,\n end,\n direction: DirectionNone,\n };\n });\n return applyTextReplaceToSelections(\n textDocument,\n deleteSelections,\n deleteSelections.map(() => ''),\n lineAnnotations\n );\n}\n\n/**\n * Resolves the document range deleted by Backspace or Delete at a collapsed\n * caret. Non-collapsed selections delete their selected text instead.\n */\nexport function resolveDeleteCharacterRange(\n textDocument: TextDocument,\n selection: EditorSelection,\n forward: boolean\n): [start: Position, end: Position] {\n if (!isCollapsedSelection(selection)) {\n return [selection.start, selection.end];\n }\n\n const caret = getCaretPosition(selection);\n let { line, character } = caret;\n const lineLength = textDocument.getLineLength(line);\n const lineCount = textDocument.lineCount;\n\n // A preserved vertical-move goal column can overshoot a shorter line; clamp\n // before stepping so Backspace/Delete target the visible caret position.\n character = Math.min(character, lineLength);\n\n if (forward) {\n if (character < lineLength) {\n return [\n { line, character },\n {\n line,\n character: stepCharacterByGrapheme(\n textDocument,\n line,\n character,\n true\n ),\n },\n ];\n }\n if (line < lineCount - 1) {\n return [\n { line, character: lineLength },\n { line: line + 1, character: 0 },\n ];\n }\n return [caret, caret];\n }\n\n if (character > 0) {\n return [\n {\n line,\n character: stepCharacterByGrapheme(\n textDocument,\n line,\n character,\n false\n ),\n },\n { line, character },\n ];\n }\n if (line > 0) {\n const prevLineLength = textDocument.getLineLength(line - 1);\n return [\n { line: line - 1, character: prevLineLength },\n { line, character: 0 },\n ];\n }\n return [caret, caret];\n}\n\n/**\n * Deletes one grapheme (or selected text) at each selection.\n */\nexport function applyDeleteCharacterToSelections<\n EType extends EditorType,\n LAnnotation,\n>(\n textDocument: TextDocument<EType, LAnnotation>,\n selections: EditorSelection[],\n forward: boolean,\n lineAnnotations?: EditorLineAnnotation<EType, LAnnotation>[],\n tabSize = 2\n): {\n nextSelections: EditorSelection[];\n change?: TextDocumentChange;\n} {\n const deleteSelections: EditorSelection[] = selections.map((selection) => {\n let [start, end] = resolveDeleteCharacterRange(\n textDocument,\n selection,\n forward\n );\n // Only grow a Backspace into a full indent unit for a collapsed caret. When\n // the user has an explicit selection, Backspace must delete exactly that\n // selection rather than expanding it to a whole soft tab.\n if (!forward && isCollapsedSelection(selection)) {\n const normalized = normalizeLeadingIndentForChange(\n textDocument,\n {\n start: textDocument.offsetAt(start),\n end: textDocument.offsetAt(end),\n text: '',\n },\n tabSize\n );\n start = textDocument.positionAt(normalized.start);\n end = textDocument.positionAt(normalized.end);\n }\n return {\n start,\n end,\n direction: DirectionNone,\n };\n });\n return applyTextReplaceToSelections(\n textDocument,\n deleteSelections,\n deleteSelections.map(() => ''),\n lineAnnotations\n );\n}\n\n/**\n * Checks if a selection is collapsed.\n */\nexport function isCollapsedSelection(\n selection: EditorSelection | Range\n): boolean {\n return (\n selection.start.line === selection.end.line &&\n selection.start.character === selection.end.character\n );\n}\n\n/**\n * Returns the caret (focus) position for a selection.\n */\nexport function getCaretPosition(selection: EditorSelection): Position {\n const { start, end, direction } = selection;\n return direction === DirectionBackward ? start : end;\n}\n\n/**\n * Checks if a line is editable.\n */\nexport function isLineEditable(lineType: string): boolean {\n return (\n lineType === 'context' ||\n lineType === 'context-expanded' ||\n lineType === 'change-addition'\n );\n}\n\n/**\n * Checks whether selections `a` and `b` intersect.\n */\nexport function selectionIntersects(\n a: EditorSelection | Range,\n b: EditorSelection | Range\n): boolean {\n const aCollapsed = isCollapsedSelection(a);\n const bCollapsed = isCollapsedSelection(b);\n if (aCollapsed && bCollapsed) {\n return comparePosition(a.start, b.start) === 0;\n }\n if (aCollapsed) {\n return (\n comparePosition(b.start, a.start) <= 0 &&\n comparePosition(a.start, b.end) <= 0\n );\n }\n if (bCollapsed) {\n return (\n comparePosition(a.start, b.start) <= 0 &&\n comparePosition(b.start, a.end) <= 0\n );\n }\n return (\n comparePosition(a.start, b.end) < 0 && comparePosition(b.start, a.end) < 0\n );\n}\n\n/**\n * Compares two positions.\n */\nexport function comparePosition(a: Position, b: Position): number {\n if (a.line !== b.line) {\n return a.line - b.line;\n }\n return a.character - b.character;\n}\n\n/**\n * Creates a selection from anchor and focus offsets.\n */\nexport function createSelectionFromAnchorAndFocusOffsets(\n textDocument: TextDocument,\n anchorOffset: number,\n focusOffset: number\n): EditorSelection {\n const direction =\n anchorOffset === focusOffset\n ? DirectionNone\n : anchorOffset < focusOffset\n ? DirectionForward\n : DirectionBackward;\n const start = Math.min(anchorOffset, focusOffset);\n const end = Math.max(anchorOffset, focusOffset);\n return {\n start: textDocument.positionAt(start),\n end: textDocument.positionAt(end),\n direction,\n };\n}\n\n/**\n * Maps a single offset from the pre-edit document into the post-edit document.\n * `edits` are resolved edits in pre-edit offsets, sorted ascending and\n * non-overlapping. An offset at or after an edit's start shifts to the end of\n * that edit's replacement (right gravity), so text inserted at the caret pushes\n * the caret past it; an offset strictly before an edit is only shifted by the\n * net length change of the edits that precede it.\n */\nexport function remapOffsetThroughEdits(\n offset: number,\n edits: readonly ResolvedTextEdit[]\n): number {\n let delta = 0;\n for (const edit of edits) {\n if (offset < edit.start) {\n break;\n }\n if (offset >= edit.end) {\n delta += edit.text.length - (edit.end - edit.start);\n } else {\n return edit.start + delta + edit.text.length;\n }\n }\n return offset + delta;\n}\n\n/**\n * Re-anchors selections after a batch of text edits has been applied, so the\n * caret keeps pointing at the same logical location in the changed buffer.\n *\n * `selectionOffsets` (one `[start, end]` pair per selection) and `edits` are\n * measured in the PRE-edit document; the returned selections are built from\n * `textDocument`, which must already reflect the applied edits. Selection\n * direction is preserved by remapping each edge and re-deriving anchor/focus.\n */\nexport function remapSelectionsAfterEdits(\n textDocument: TextDocument,\n selections: readonly EditorSelection[],\n selectionOffsets: ReadonlyArray<readonly [number, number]>,\n edits: readonly ResolvedTextEdit[]\n): EditorSelection[] {\n return selections.map((selection, index) => {\n const [startOffset, endOffset] = selectionOffsets[index];\n const nextStart = remapOffsetThroughEdits(startOffset, edits);\n const nextEnd = remapOffsetThroughEdits(endOffset, edits);\n const anchorOffset =\n selection.direction === DirectionBackward ? nextEnd : nextStart;\n const focusOffset =\n selection.direction === DirectionBackward ? nextStart : nextEnd;\n return createSelectionFromAnchorAndFocusOffsets(\n textDocument,\n anchorOffset,\n focusOffset\n );\n });\n}\n\n/**\n * Creates a selection from a anchor and focus selection.\n */\nexport function createSelectionFrom(\n anchorSelection: EditorSelection,\n focusSelection: EditorSelection\n): EditorSelection {\n const anchor =\n anchorSelection.direction === DirectionBackward\n ? anchorSelection.end\n : anchorSelection.start;\n const currentStartOrder = comparePosition(anchor, focusSelection.start);\n const currentEndOrder = comparePosition(anchor, focusSelection.end);\n let focus = focusSelection.end;\n if (currentStartOrder <= 0) {\n focus = focusSelection.end;\n } else if (currentEndOrder >= 0) {\n focus = focusSelection.start;\n } else {\n // When the original anchor sits inside `current`, keep whichever edge\n // stayed at the anchor so drag direction remains stable.\n focus = currentStartOrder === 0 ? focusSelection.end : focusSelection.start;\n }\n const anchorVsFocus = comparePosition(anchor, focus);\n const direction: SelectionDirection =\n anchorVsFocus === 0\n ? DirectionNone\n : anchorVsFocus < 0\n ? DirectionForward\n : DirectionBackward;\n const selectionStart = anchorVsFocus <= 0 ? anchor : focus;\n const selectionEnd = anchorVsFocus <= 0 ? focus : anchor;\n return {\n start: selectionStart,\n end: selectionEnd,\n direction,\n };\n}\n\n/**\n * Extends or shrinks the selection `original` using the endpoints of `target`, \\\n * matching contenteditable shift + click extend behavior.\n */\nexport function extendSelection(\n original: EditorSelection,\n target: EditorSelection\n): EditorSelection {\n const leftExtended = comparePosition(target.start, original.start) < 0;\n const rightExtended = comparePosition(target.end, original.end) > 0;\n\n if (leftExtended && !rightExtended) {\n return {\n start: target.start,\n end: original.end,\n direction: DirectionBackward,\n };\n }\n\n if (rightExtended && !leftExtended) {\n return {\n start: original.start,\n end: target.end,\n direction: DirectionForward,\n };\n }\n\n if (original.direction === DirectionBackward) {\n return {\n start: target.start,\n end: original.end,\n direction:\n comparePosition(target.start, original.end) === 0\n ? DirectionNone\n : DirectionBackward,\n };\n }\n\n return {\n start: original.start,\n end: target.end,\n direction:\n comparePosition(original.start, target.end) === 0\n ? DirectionNone\n : DirectionForward,\n };\n}\n\n/**\n * Extends multiple selections.\n */\nexport function extendSelections(\n selections: EditorSelection[],\n target: EditorSelection\n): EditorSelection[] {\n const newSelections = selections.map((selection) => {\n return extendSelection(selection, target);\n });\n return mergeOverlappingSelections(newSelections);\n}\n\n/**\n * Merges overlapping selections.\n */\nexport function mergeOverlappingSelections(\n selections: EditorSelection[]\n): EditorSelection[] {\n if (selections.length <= 1) {\n return selections;\n }\n const ordered = selections\n .map((selection, index) => ({ index, selection }))\n .sort((a, b) => {\n const startOrder = comparePosition(a.selection.start, b.selection.start);\n if (startOrder !== 0) {\n return startOrder;\n }\n const endOrder = comparePosition(a.selection.end, b.selection.end);\n return endOrder !== 0 ? endOrder : a.index - b.index;\n });\n const merged: {\n index: number;\n selection: EditorSelection;\n }[] = [];\n\n let current = ordered[0];\n for (const entry of ordered.slice(1)) {\n if (selectionIntersects(current.selection, entry.selection)) {\n const latest = entry.index > current.index ? entry : current;\n const start =\n comparePosition(entry.selection.start, current.selection.start) < 0\n ? entry.selection.start\n : current.selection.start;\n const end =\n comparePosition(entry.selection.end, current.selection.end) > 0\n ? entry.selection.end\n : current.selection.end;\n let direction = latest.selection.direction;\n if (direction === DirectionNone && comparePosition(start, end) !== 0) {\n direction =\n comparePosition(latest.selection.start, start) === 0\n ? DirectionBackward\n : DirectionForward;\n }\n current = { index: latest.index, selection: { direction, end, start } };\n continue;\n }\n\n merged.push(current);\n current = entry;\n }\n merged.push(current);\n\n return merged\n .sort((a, b) => a.index - b.index)\n .map(({ selection }) => selection);\n}\n\n/**\n * Converts selections into merged line blocks for line-based commands.\n */\nexport function getSelectedLineBlocks(\n selections: EditorSelection[]\n): { startLine: number; endLine: number }[] {\n const blocks = selections\n .map((selection) => {\n let endLine = selection.end.line;\n if (\n selection.end.character === 0 &&\n comparePosition(selection.start, selection.end) !== 0\n ) {\n endLine--;\n }\n return {\n startLine: selection.start.line,\n endLine: Math.max(selection.start.line, endLine),\n };\n })\n .sort((a, b) => {\n const startOrder = a.startLine - b.startLine;\n return startOrder !== 0 ? startOrder : a.endLine - b.endLine;\n });\n\n const merged: { startLine: number; endLine: number }[] = [];\n for (const block of blocks) {\n const previous = merged.at(-1);\n if (previous !== undefined && block.startLine <= previous.endLine + 1) {\n previous.endLine = Math.max(previous.endLine, block.endLine);\n } else {\n merged.push({ ...block });\n }\n }\n return merged;\n}\n\n/**\n * Moves a selection's line positions after its lines are shifted, clamping to\n * the target document bounds.\n */\nexport function shiftSelectionLines(\n selection: EditorSelection,\n direction: -1 | 1,\n lineCount: number,\n getLineLength: (line: number) => number\n): EditorSelection {\n const shiftPosition = (position: Position): Position => {\n const line = position.line + direction;\n if (line >= lineCount) {\n const lastLine = Math.max(0, lineCount - 1);\n return {\n line: lastLine,\n character: getLineLength(lastLine),\n };\n }\n if (line < 0) {\n return { line: 0, character: 0 };\n }\n return {\n line,\n character: position.character,\n };\n };\n\n return {\n start: shiftPosition(selection.start),\n end: shiftPosition(selection.end),\n direction: selection.direction,\n };\n}\n\n/**\n * Finds the next matching word and updates the selections.\n */\nexport function findNextMatch(\n textDocument: TextDocument,\n selections: EditorSelection[]\n): EditorSelection[] | undefined {\n if (selections.length === 0) {\n return undefined;\n }\n\n const normalizedSelections = selections.map((selection) =>\n isCollapsedSelection(selection)\n ? expandCollapsedSelectionToWord(textDocument, selection)\n : selection\n );\n const texts = normalizedSelections.map((s) => textDocument.getText(s));\n const needle = texts[0];\n if (needle.length === 0 || texts.some((t) => t !== needle)) {\n return undefined;\n }\n\n const occupied = normalizedSelections.map(\n (s) =>\n [textDocument.offsetAt(s.start), textDocument.offsetAt(s.end)] as [\n number,\n number,\n ]\n );\n const nextOffset = textDocument.findNextNonOverlappingSubstring(\n needle,\n occupied\n );\n if (nextOffset === undefined) {\n return normalizedSelections.some((selection, index) => {\n const original = selections[index];\n return (\n comparePosition(selection.start, original.start) !== 0 ||\n comparePosition(selection.end, original.end) !== 0 ||\n selection.direction !== original.direction\n );\n })\n ? normalizedSelections\n : undefined;\n }\n const added = createSelectionFromAnchorAndFocusOffsets(\n textDocument,\n nextOffset,\n nextOffset + needle.length\n );\n return [...normalizedSelections, added];\n}\n\n/**\n * Get the full selection of the document.\n */\nexport function getDocumentFullSelection(\n textDocument: TextDocument\n): EditorSelection {\n const lastLine = textDocument.lineCount - 1;\n const lastCharacter = textDocument.getLineLength(lastLine);\n return {\n start: { line: 0, character: 0 },\n end: { line: lastLine, character: lastCharacter },\n direction: DirectionForward,\n };\n}\n\n/**\n * Get the boundary selection of the document.\n */\nexport function getDocumentBoundarySelection(\n textDocument: TextDocument,\n atEnd: boolean,\n trimmedEndNewLine?: boolean\n): EditorSelection {\n let line = 0;\n if (atEnd) {\n const lastLine = textDocument.lineCount - 1;\n const hasTrailingBlankLine =\n trimmedEndNewLine === true &&\n lastLine > 0 &&\n textDocument.getLineLength(lastLine) === 0;\n line = hasTrailingBlankLine ? lastLine - 1 : lastLine;\n }\n const character = atEnd ? textDocument.getLineLength(line) : 0;\n const start = { line, character };\n return {\n start: start,\n end: start,\n direction: DirectionForward,\n };\n}\n\ninterface ClipboardRegion {\n start: number;\n end: number;\n}\n\n/** Resolves the document offset range one selection contributes to a copy. */\nfunction resolveClipboardRegion(\n textDocument: TextDocument,\n selection: EditorSelection\n): ClipboardRegion {\n if (isCollapsedSelection(selection)) {\n const line = selection.start.line;\n const start = textDocument.offsetAt({ line, character: 0 });\n const end =\n line < textDocument.lineCount - 1\n ? textDocument.offsetAt({ line: line + 1, character: 0 })\n : textDocument.offsetAt({\n line,\n character: textDocument.getLineLength(line),\n });\n return { start, end };\n }\n const start = textDocument.offsetAt(selection.start);\n const end = textDocument.offsetAt(selection.end);\n return start <= end ? { start, end } : { start: end, end: start };\n}\n\n/**\n * Resolves the document offset range each selection contributes to the\n * clipboard, ordered by position. A collapsed selection contributes its whole\n * logical line including the trailing line break; the final line has no\n * trailing break to include. A ranged selection contributes the selected text.\n */\nfunction resolveClipboardRegions(\n textDocument: TextDocument,\n selections: EditorSelection[]\n): ClipboardRegion[] {\n return selections\n .map((selection) => resolveClipboardRegion(textDocument, selection))\n .sort((a, b) => {\n const startOrder = a.start - b.start;\n return startOrder !== 0 ? startOrder : a.end - b.end;\n });\n}\n\n/**\n * Gets the text contributed by each selection in document order, preserving\n * the pairing needed to paste the values into another set of selections.\n */\nexport function getSelectionClipboardTexts(\n textDocument: TextDocument,\n selections: EditorSelection[]\n): string[] {\n const regions = resolveClipboardRegions(textDocument, selections);\n return regions.map(({ start, end }) => textDocument.getTextSlice(start, end));\n}\n\n/**\n * Get the clipboard text of the selections for the given text document. Used by\n * both copy and cut so the two stay in sync. Overlapping regions (e.g. several\n * carets on one line) are merged so the same text is never emitted twice, and a\n * line-ending separator is inserted only between regions that aren't already\n * contiguous in the document.\n */\nexport function getSelectionText(\n textDocument: TextDocument,\n selections: EditorSelection[]\n): string {\n const regions = resolveClipboardRegions(textDocument, selections);\n const eol = textDocument.eol;\n let result = '';\n let prevEnd = -1;\n for (const region of regions) {\n if (region.end <= region.start) {\n continue;\n }\n if (region.start <= prevEnd) {\n // Contiguous with or overlapping the previous region: extend it rather\n // than repeat any shared text.\n if (region.end > prevEnd) {\n result += textDocument.getTextSlice(prevEnd, region.end);\n prevEnd = region.end;\n }\n continue;\n }\n if (result.length > 0 && !endsWithLineBreak(result)) {\n result += eol;\n }\n result += textDocument.getTextSlice(region.start, region.end);\n prevEnd = region.end;\n }\n return result;\n}\n\ninterface SelectionCut {\n index: number;\n edit: ResolvedTextEdit;\n}\n\n// Resolves the deletion an individual selection contributes to a cut: a\n// collapsed caret removes its whole logical line, while a ranged selection\n// removes only the selected text.\nfunction resolveSelectionCutEdit(\n textDocument: TextDocument,\n selection: EditorSelection\n): ResolvedTextEdit {\n if (isCollapsedSelection(selection)) {\n return resolveCollapsedSelectionCutEdit(textDocument, selection);\n }\n const [start, end] =\n comparePosition(selection.start, selection.end) <= 0\n ? [selection.start, selection.end]\n : [selection.end, selection.start];\n return {\n start: textDocument.offsetAt(start),\n end: textDocument.offsetAt(end),\n text: '',\n };\n}\n\n// A caret-only cut removes the whole logical line. Non-final lines delete\n// their trailing line break; the final line deletes the preceding break so\n// no empty line is left behind.\nfunction resolveCollapsedSelectionCutEdit(\n textDocument: TextDocument,\n selection: EditorSelection\n): ResolvedTextEdit {\n const line = selection.start.line;\n const lineStart = textDocument.offsetAt({ line, character: 0 });\n const lineEnd = textDocument.offsetAt({\n line,\n character: textDocument.getLineLength(line),\n });\n\n if (line < textDocument.lineCount - 1) {\n const nextLineStart = textDocument.offsetAt({\n line: line + 1,\n character: 0,\n });\n return { start: lineStart, end: nextLineStart, text: '' };\n }\n\n if (line > 0) {\n const previousLineEnd = textDocument.offsetAt({\n line: line - 1,\n character: textDocument.getLineLength(line - 1),\n });\n return { start: previousLineEnd, end: lineEnd, text: '' };\n }\n\n return { start: lineStart, end: lineEnd, text: '' };\n}\n\nfunction mergeCutEdits(orderedCuts: SelectionCut[]): ResolvedTextEdit[] {\n const edits: ResolvedTextEdit[] = [];\n for (const { edit } of orderedCuts) {\n if (edit.start >= edit.end) {\n continue;\n }\n const last = edits.at(-1);\n if (last !== undefined && edit.start <= last.end) {\n edits[edits.length - 1] = {\n start: last.start,\n end: Math.max(last.end, edit.end),\n text: '',\n };\n } else {\n edits.push(edit);\n }\n }\n return edits;\n}\n\nfunction mapCutSelectionOffsets(\n orderedCuts: SelectionCut[],\n edits: ResolvedTextEdit[]\n): number[] {\n const nextOffsets: number[] = Array.from({ length: orderedCuts.length });\n let editIndex = 0;\n let offsetDelta = 0;\n for (const cut of orderedCuts) {\n while (editIndex < edits.length && cut.edit.start > edits[editIndex].end) {\n const edit = edits[editIndex];\n offsetDelta -= edit.end - edit.start;\n editIndex++;\n }\n\n const edit = edits[editIndex];\n if (\n edit !== undefined &&\n cut.edit.start >= edit.start &&\n cut.edit.start <= edit.end\n ) {\n nextOffsets[cut.index] = edit.start + offsetDelta;\n } else {\n nextOffsets[cut.index] = cut.edit.start + offsetDelta;\n }\n }\n return nextOffsets;\n}\n\n// Resolves the clipboard text, merged deletions, and resulting caret offsets\n// for a cut. The clipboard text comes from the shared getSelectionText helper\n// so cut stays in sync with copy, while the deletions are computed per\n// selection and merged so overlapping cuts delete their shared text once.\nexport function resolveSelectionCut(\n textDocument: TextDocument,\n selections: EditorSelection[]\n): {\n text: string;\n edits: ResolvedTextEdit[];\n nextSelectionOffsets: number[];\n} {\n const cuts = selections.map<SelectionCut>((selection, index) => ({\n index,\n edit: resolveSelectionCutEdit(textDocument, selection),\n }));\n const orderedCuts = [...cuts].sort((a, b) => {\n const startOrder = a.edit.start - b.edit.start;\n if (startOrder !== 0) {\n return startOrder;\n }\n const endOrder = a.edit.end - b.edit.end;\n if (endOrder !== 0) {\n return endOrder;\n }\n return a.index - b.index;\n });\n const edits = mergeCutEdits(orderedCuts);\n return {\n text: getSelectionText(textDocument, selections),\n edits,\n nextSelectionOffsets: mapCutSelectionOffsets(orderedCuts, edits),\n };\n}\n\n/**\n * Get the anchor node and offset for a selection.\n */\nexport function getSelectionAnchor(\n lineElement: HTMLElement,\n character: number\n): [Node, number] {\n const ch = Math.max(0, character);\n const tokens = collectTokens(lineElement);\n\n let last: HTMLElement | null = null;\n for (const token of tokens) {\n last = token;\n const base = getCharacterIndex(token)!;\n const end = base + (token.textContent?.length ?? 0);\n if (ch <= end) {\n const anchor = textAt(token, ch < base ? 0 : ch - base);\n if (anchor !== null) {\n return anchor;\n }\n }\n }\n\n if (last !== null) {\n const anchor = textAt(last, last.textContent?.length ?? 0);\n if (anchor !== null) {\n return anchor;\n }\n return [last, 0];\n }\n\n let textOffset = 0;\n let lastTextNode: Text | null = null;\n for (const child of lineElement.childNodes) {\n if (child.nodeType === 1 && (child as HTMLElement).tagName === 'BR') {\n return [child, 0];\n }\n if (child.nodeType !== 3) {\n continue;\n }\n lastTextNode = child as Text;\n const len = getTextOffset(\n lastTextNode.textContent,\n lastTextNode.textContent?.length ?? 0\n );\n if (ch <= textOffset + len) {\n return [\n lastTextNode,\n getTextOffset(lastTextNode.textContent, ch - textOffset),\n ];\n }\n textOffset += len;\n }\n\n if (lastTextNode !== null) {\n return [\n lastTextNode,\n getTextOffset(\n lastTextNode.textContent,\n lastTextNode.textContent?.length ?? 0\n ),\n ];\n }\n return [lineElement, 0];\n}\n\n/**\n * Expands a zero-width selection to the word-like segment that contains the caret.\n */\nexport function expandCollapsedSelectionToWord(\n textDocument: TextDocument,\n selection: EditorSelection\n): EditorSelection {\n const { line, character } = selection.start;\n const lineText = textDocument.getLineText(line);\n const ch = Math.max(0, Math.min(character, lineText.length));\n const span = expandCollapsedLineWord(lineText, ch);\n if (span === undefined) {\n return selection;\n }\n return {\n start: { line, character: span.start },\n end: { line, character: span.end },\n direction: DirectionForward,\n };\n}\n\nfunction expandCollapsedLineWord(\n lineText: string,\n character: number\n): { start: number; end: number } | undefined {\n const segmenter = createSegmenter({ granularity: 'word' });\n if (segmenter !== undefined) {\n for (const seg of segmenter.segment(lineText)) {\n if (seg.isWordLike !== true) {\n continue;\n }\n const lo = seg.index;\n const hi = lo + seg.segment.length;\n // Match when the cursor is inside the word or immediately touching\n // one of its boundaries — not when separated by non-word characters.\n if (character >= lo && character <= hi) {\n return { start: lo, end: hi };\n }\n }\n return undefined;\n }\n // Degraded path for engines lacking Intl.Segmenter: treat runs of\n // alphanumeric/underscore characters as words.\n const wordRe = /[\\p{Alphabetic}\\p{Number}_]+/gu;\n let match: RegExpExecArray | null;\n while ((match = wordRe.exec(lineText)) !== null) {\n const lo = match.index;\n const hi = lo + match[0].length;\n if (character >= lo && character <= hi) {\n return { start: lo, end: hi };\n }\n }\n return undefined;\n}\n\n// Resolves the range removed by deleteWordBackward for one selection.\nfunction resolveDeleteWordBackwardRange(\n textDocument: TextDocument,\n selection: EditorSelection\n): [start: Position, end: Position] {\n if (!isCollapsedSelection(selection)) {\n return [selection.start, selection.end];\n }\n const caret = getCaretPosition(selection);\n const { line, character: head } = caret;\n if (head === 0) {\n if (line === 0) {\n return [caret, caret];\n }\n const prevLineLength = textDocument.getLineLength(line - 1);\n return [\n { line: line - 1, character: prevLineLength },\n { line, character: 0 },\n ];\n }\n const lineText = textDocument.getLineText(line);\n const graphemeStarts = getLineGraphemeStarts(lineText);\n let pos = head;\n let match: number | undefined;\n while (pos > 0) {\n const prev = findClusterBreak(lineText, pos, false, graphemeStarts);\n const nextChar = lineText.slice(prev, pos);\n const nextMatch = !/\\S/.test(nextChar)\n ? 0\n : /\\p{Alphabetic}|\\p{Number}|_/u.test(nextChar)\n ? 1\n : 2;\n if (match !== undefined && nextMatch !== match) {\n break;\n }\n if (nextMatch !== 0 || pos !== head) {\n match = nextMatch;\n }\n pos = prev;\n }\n return [\n { line, character: pos },\n { line, character: head },\n ];\n}\n\nfunction findClusterBreak(\n text: string,\n pos: number,\n forward: boolean,\n graphemeStarts: number[]\n): number {\n if (forward) {\n for (const start of graphemeStarts) {\n if (start > pos) {\n return start;\n }\n }\n return text.length;\n }\n for (let i = graphemeStarts.length - 1; i >= 0; i--) {\n const start = graphemeStarts[i];\n if (start < pos) {\n return start;\n }\n }\n return 0;\n}\n\n// Lists the start column of every grapheme cluster on a line (always starting\n// at 0). Used to step the caret and to transpose by whole graphemes so a\n// surrogate pair (emoji) or combining sequence is never split.\nfunction getLineGraphemeStarts(lineText: string): number[] {\n const graphemeStarts = [0];\n const segmenter = getGraphemeSegmenter();\n if (segmenter !== undefined) {\n for (const segment of segmenter.segment(lineText)) {\n if (segment.index > 0) {\n graphemeStarts.push(segment.index);\n }\n }\n return graphemeStarts;\n }\n // Degraded path for engines lacking Intl.Segmenter: step by code point\n // (keeps surrogate pairs intact, but not combining sequences).\n let index = 0;\n for (const codePoint of lineText) {\n if (index > 0) {\n graphemeStarts.push(index);\n }\n index += codePoint.length;\n }\n return graphemeStarts;\n}\n\n// Returns the character column one grapheme cluster to the left or right of\n// `character` on `line`. Stepping by grapheme rather than by a single UTF-16\n// code unit keeps the caret from landing inside an emoji or other multi-unit\n// character. Crossing a line boundary is left to the caller.\nfunction stepCharacterByGrapheme(\n textDocument: TextDocument,\n line: number,\n character: number,\n forward: boolean\n): number {\n const lineLength = textDocument.getLineLength(line);\n if (forward) {\n if (character >= lineLength) {\n return lineLength;\n }\n const lineStart = textDocument.offsetAt({ line, character: 0 });\n const suffix = textDocument.getTextSlice(\n lineStart + character,\n lineStart + lineLength\n );\n const segmenter = getGraphemeSegmenter();\n if (segmenter !== undefined) {\n for (const segment of segmenter.segment(suffix)) {\n return character + segment.segment.length;\n }\n return lineLength;\n }\n // Degraded path for engines lacking Intl.Segmenter: step one code point.\n for (const codePoint of suffix) {\n return character + codePoint.length;\n }\n return lineLength;\n }\n if (character <= 0) {\n return 0;\n }\n const lineStart = textDocument.offsetAt({ line, character: 0 });\n const prefix = textDocument.getTextSlice(lineStart, lineStart + character);\n let prevStart = 0;\n const segmenter = getGraphemeSegmenter();\n if (segmenter !== undefined) {\n for (const segment of segmenter.segment(prefix)) {\n prevStart = segment.index;\n }\n return prevStart;\n }\n // Degraded path for engines lacking Intl.Segmenter: step one code point.\n let index = 0;\n for (const codePoint of prefix) {\n prevStart = index;\n index += codePoint.length;\n }\n return prevStart;\n}\n\nfunction getSelectionAnchorAndFocusOffsets(\n textDocument: TextDocument,\n selection: EditorSelection\n): [anchorOffset: number, focusOffset: number] {\n const isBackward = selection.direction === DirectionBackward;\n return [\n textDocument.offsetAt(isBackward ? selection.end : selection.start),\n textDocument.offsetAt(getCaretPosition(selection)),\n ];\n}\n\n// Resolves the range removed by deleteHardLineForward for one selection.\nfunction resolveDeleteHardLineForwardRange(\n textDocument: TextDocument,\n selection: EditorSelection\n): Range {\n if (!isCollapsedSelection(selection)) {\n return { start: selection.start, end: selection.end };\n }\n const { line, character } = selection.start;\n const lineText = textDocument.getLineText(line);\n const lineLength = lineText.length;\n if (character < lineLength) {\n return {\n start: { line, character },\n end: { line, character: lineLength },\n };\n }\n if (line < textDocument.lineCount - 1) {\n return {\n start: { line, character },\n end: { line: line + 1, character: 0 },\n };\n }\n return {\n start: { line, character },\n end: { line, character },\n };\n}\n\n// When the user inserts a lone line break, copy the current line's indentation onto the new line.\nfunction expandSingleNewlineInsert(\n textDocument: TextDocument,\n insertText: string,\n insertStartOffset: number\n): string {\n if (insertText !== '\\n' && insertText !== '\\r' && insertText !== '\\r\\n') {\n return insertText;\n }\n const line = textDocument.positionAt(insertStartOffset).line;\n const lineText = textDocument.getLineText(line);\n const indentLen = getLeadingSpaces(lineText);\n if (indentLen === 0) {\n return insertText;\n }\n return insertText + lineText.slice(0, indentLen);\n}\n\nfunction getLeadingSpaces(text: string): number {\n let indent = 0;\n for (; indent < text.length; indent++) {\n const c = text.charCodeAt(indent);\n if (c !== /* space */ 32 && c !== /* tab */ 9) {\n break;\n }\n }\n return indent;\n}\n\nfunction createSelectionsFromOffsetPairs(\n textDocument: TextDocument,\n offsetPairs: readonly [anchorOffset: number, focusOffset: number][]\n): EditorSelection[] {\n const normalizedOffsets: number[] = [];\n for (const [anchorOffset, focusOffset] of offsetPairs) {\n normalizedOffsets.push(\n Math.min(anchorOffset, focusOffset),\n Math.max(anchorOffset, focusOffset)\n );\n }\n const positions = textDocument.positionsAt(normalizedOffsets);\n return offsetPairs.map(([anchorOffset, focusOffset], index) => {\n const direction =\n anchorOffset === focusOffset\n ? DirectionNone\n : anchorOffset < focusOffset\n ? DirectionForward\n : DirectionBackward;\n return {\n start: positions[index * 2],\n end: positions[index * 2 + 1],\n direction,\n };\n });\n}\n\n// Expands a backspace over leading spaces into one soft-tab width so mixed hard/soft indentation\n// behaves like the explicit outdent command.\nfunction normalizeLeadingIndentForChange(\n textDocument: TextDocument,\n change: ResolvedTextEdit,\n tabSize: number\n): ResolvedTextEdit {\n if (change.text !== '' || change.start !== change.end - 1) {\n return change;\n }\n const caretPosition = textDocument.positionAt(change.end);\n if (caretPosition.character === 0) {\n return change;\n }\n const lineText = textDocument.getLineText(caretPosition.line);\n const leadingText = lineText.slice(0, caretPosition.character);\n if (/[^ \\t]/.test(leadingText)) {\n return change;\n }\n if (lineText[caretPosition.character - 1] === '\\t') {\n return change;\n }\n const softTabStart = Math.max(0, caretPosition.character - tabSize);\n const softTabText = lineText.slice(softTabStart, caretPosition.character);\n if (softTabText.length === tabSize && /^ +$/.test(softTabText)) {\n return {\n ...change,\n start: change.end - softTabText.length,\n };\n }\n return change;\n}\n\nfunction boundaryToPosition(node: Node, offset: number): Position | null {\n const host = node.nodeType === 1 ? (node as HTMLElement) : node.parentElement;\n let lineEl: HTMLElement | null = host;\n while (lineEl !== null && getLineIndex(lineEl) === undefined) {\n lineEl = lineEl.parentElement;\n }\n if (lineEl === null) {\n return null;\n }\n const line = getLineIndex(lineEl);\n if (line === undefined) {\n return null;\n }\n\n if (node.nodeType === 3) {\n if (node.parentElement === null) {\n return null;\n }\n if (findTokenSpan(node.parentElement) !== null) {\n return { line, character: getLineChildEnd(node, offset) };\n }\n return {\n line,\n character:\n offsetBefore(lineEl, node) + getTextOffset(node.textContent, offset),\n };\n }\n\n if (node.nodeType === 1) {\n const el = node as HTMLElement;\n if (el.tagName === 'DIV') {\n let character = 0;\n for (let i = 0; i < offset; i++) {\n character = getLineChildEnd(el.childNodes[i]);\n }\n return { line, character };\n }\n if (el.tagName === 'BR') {\n return { line, character: 0 };\n }\n if (el.tagName === 'SPAN') {\n if (offset < el.childNodes.length) {\n const next = el.childNodes[offset];\n if (next?.nodeType === 1) {\n const nextBase = getCharacterIndex(next as HTMLElement);\n if (nextBase !== undefined) {\n return { line, character: nextBase };\n }\n const token = findTokenSpan(next as HTMLElement);\n const tokenBase =\n token === null ? undefined : getCharacterIndex(token);\n if (tokenBase !== undefined) {\n return { line, character: tokenBase };\n }\n }\n }\n return {\n line,\n character:\n offset > 0\n ? getLineChildEnd(el.childNodes[offset - 1])\n : offsetBefore(lineEl, el),\n };\n }\n return { line, character: offsetBefore(lineEl, el) };\n }\n return null;\n}\n\nfunction collectTokens(line: HTMLElement): HTMLElement[] {\n const tokens: HTMLElement[] = [];\n for (const child of line.childNodes) {\n if (child.nodeType !== 1) {\n continue;\n }\n const el = child as HTMLElement;\n if (el.tagName !== 'SPAN') {\n continue;\n }\n const base = getCharacterIndex(el);\n if (base !== undefined) {\n tokens.push(el);\n continue;\n }\n for (const nested of el.childNodes) {\n if (\n nested.nodeType === 1 &&\n getCharacterIndex(nested as HTMLElement) !== undefined\n ) {\n tokens.push(nested as HTMLElement);\n }\n }\n }\n return tokens;\n}\n\nfunction textAt(token: HTMLElement, offset: number): [Node, number] | null {\n let remaining = Math.max(0, offset);\n const stack: Array<{ container: Node; index: number }> = [\n { container: token, index: 0 },\n ];\n while (stack.length > 0) {\n const frame = stack[stack.length - 1];\n if (frame.index >= frame.container.childNodes.length) {\n stack.pop();\n continue;\n }\n const walkNode = frame.container.childNodes[frame.index];\n frame.index++;\n if (walkNode.nodeType === 3) {\n const len = getTextOffset(\n walkNode.textContent,\n walkNode.textContent?.length ?? 0\n );\n if (remaining <= len) {\n return [walkNode, remaining];\n }\n remaining -= len;\n } else if (walkNode.nodeType === 1) {\n stack.push({ container: walkNode, index: 0 });\n }\n }\n return null;\n}\n\nfunction textLengthBefore(root: Node, target: Node): number {\n let before = 0;\n const stack: Array<{ container: Node; index: number }> = [\n { container: root, index: 0 },\n ];\n while (stack.length > 0) {\n const frame = stack[stack.length - 1];\n if (frame.index >= frame.container.childNodes.length) {\n stack.pop();\n continue;\n }\n const walkNode = frame.container.childNodes[frame.index];\n if (walkNode === target) {\n return before;\n }\n frame.index++;\n if (walkNode.nodeType === 3) {\n before += getTextOffset(\n walkNode.textContent,\n walkNode.textContent?.length ?? 0\n );\n } else if (walkNode.nodeType === 1) {\n stack.push({ container: walkNode, index: 0 });\n }\n }\n return before;\n}\n\nfunction isInside(token: HTMLElement, node: Node): boolean {\n let current: Node | null = node;\n while (current !== null) {\n if (current === token) {\n return true;\n }\n current = current.parentElement;\n }\n return false;\n}\n\nfunction offsetBefore(line: HTMLElement, node: Node): number {\n if (node.parentElement === line) {\n let offset = 0;\n const index = Array.prototype.indexOf.call(line.childNodes, node);\n for (let i = 0; i < index; i++) {\n offset = getLineChildEnd(line.childNodes[i]);\n }\n return offset;\n }\n for (const token of collectTokens(line)) {\n if (isInside(token, node)) {\n const base = getCharacterIndex(token)!;\n return base + (node.nodeType === 3 ? textLengthBefore(token, node) : 0);\n }\n }\n let offset = 0;\n let target: HTMLElement | null =\n node.nodeType === 1 ? (node as HTMLElement) : node.parentElement;\n while (target !== null && target.parentElement !== null) {\n if (getLineIndex(target.parentElement) !== undefined) {\n break;\n }\n const parent = target.parentElement;\n const index = Array.prototype.indexOf.call(parent.childNodes, target);\n for (let i = 0; i < index; i++) {\n offset = getLineChildEnd(parent.childNodes[i]);\n }\n target = parent;\n }\n return offset;\n}\n\nfunction findTokenSpan(el: HTMLElement): HTMLElement | null {\n let current: HTMLElement | null = el;\n while (current !== null) {\n if (getLineIndex(current) !== undefined) {\n return null;\n }\n if (getCharacterIndex(current) !== undefined) {\n return current;\n }\n current = current.parentElement;\n }\n return null;\n}\n\nfunction getLineChildEnd(\n child: Node | undefined,\n textOffsetInChild?: number\n): number {\n if (child === undefined) {\n return 0;\n }\n if (child.nodeType === 3) {\n const parent = child.parentElement;\n if (parent === null) {\n return 0;\n }\n const token = findTokenSpan(parent);\n if (token === null) {\n return 0;\n }\n const base = getCharacterIndex(token);\n if (base === undefined) {\n return 0;\n }\n const length =\n textOffsetInChild === undefined\n ? getTextOffset(child.textContent, child.textContent?.length ?? 0)\n : getTextOffset(child.textContent, textOffsetInChild);\n return base + textLengthBefore(token, child) + length;\n }\n if (child.nodeType !== 1) {\n return 0;\n }\n const el = child as HTMLElement;\n if (el.tagName !== 'SPAN' && el.tagName !== 'BR') {\n return 0;\n }\n const base = getCharacterIndex(el);\n if (base !== undefined) {\n return base + (el.textContent?.length ?? 0);\n }\n let end = 0;\n for (const token of el.childNodes) {\n end = Math.max(end, getLineChildEnd(token));\n }\n return end;\n}\n\nfunction getLineIndex(el: HTMLElement): number | undefined {\n const { line, lineType } = el.dataset;\n if (line !== undefined && lineType !== 'change-deletion') {\n const lineNumber = parseInt(line, 10);\n if (!Number.isNaN(lineNumber)) {\n return lineNumber - 1;\n }\n }\n return undefined;\n}\n\nfunction getCharacterIndex(el: HTMLElement): number | undefined {\n const { char } = el.dataset;\n if (char !== undefined) {\n const charIndex = parseInt(char, 10);\n if (!Number.isNaN(charIndex)) {\n return charIndex;\n }\n }\n return undefined;\n}\n\nfunction getTextOffset(\n text: string | null | undefined,\n offset: number\n): number {\n const value = text ?? '';\n const lineBreakIndex = value.search(/[\\r\\n]/);\n return Math.min(\n offset,\n lineBreakIndex === -1 ? value.length : lineBreakIndex\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"selection.js","names":[],"sources":["../../src/editor/selection.ts"],"sourcesContent":["import { applyDocumentChangeToLineAnnotations } from './lineAnnotations';\nimport type { TextDocument, TextDocumentChange } from './textDocument';\nimport type {\n EditorLineAnnotation,\n EditorSelection,\n EditorType,\n Position,\n Range,\n ResolvedTextEdit,\n SelectionDirection,\n TextEdit,\n} from './types';\nimport {\n createSegmenter,\n endsWithLineBreak,\n getGraphemeSegmenter,\n} from './utils';\n\nexport const DirectionBackward = -1;\nexport const DirectionNone = 0;\nexport const DirectionForward = 1;\n\nconst SURROUNDING_PAIRS: Array<[openChar: string, closeChar: string]> = [\n [\"'\", \"'\"],\n ['\"', '\"'],\n ['`', '`'],\n ['{', '}'],\n ['[', ']'],\n ['<', '>'],\n ['(', ')'],\n];\n\nconst AUTO_SURROUND_CLOSE_CHARS = new Map(SURROUNDING_PAIRS);\nconst AUTO_SURROUND_QUOTE_CHARS = new Set([\"'\", '\"', '`']);\nconst AUTO_SURROUND_BRACKET_CHARS = new Set(['{', '[', '(', '<']);\n\nexport interface CursorMoveOptions {\n getSoftLineOffsets?: (line: number) => ArrayLike<number> | undefined;\n /**\n * Fold-skip resolver for vertical motion crossing document lines: the\n * nearest renderable line at or beyond the target in the move direction,\n * or undefined when everything that way is hidden inside a collapsed\n * region (the caret then stays put). Soft-line moves within one document\n * line never consult it.\n */\n resolveRenderableLine?: ResolveRenderableLine;\n}\n\ninterface SoftLineInfo {\n start: number;\n end: number;\n index: number;\n count: number;\n}\n\n/**\n * Converts a selection from a web selection to an editor selection.\n */\nexport function convertSelection(\n range: StaticRange,\n direction: SelectionDirection = DirectionNone\n): EditorSelection | undefined {\n const start = boundaryToPosition(range.startContainer, range.startOffset);\n const end = boundaryToPosition(range.endContainer, range.endOffset);\n if (start === null || end === null) {\n return undefined;\n }\n return {\n start,\n end,\n direction,\n };\n}\n\n/**\n * Resolves the indent edits for a selection.\n */\nexport function resolveIndentEdits(\n textDocument: TextDocument,\n selection: EditorSelection,\n tabSize: number,\n outdent: boolean\n): [edits: TextEdit[], nextSelection: EditorSelection] {\n if (textDocument === undefined) {\n return [[], selection];\n }\n const { start, end } = selection;\n const edits: TextEdit[] = [];\n let newSelection: EditorSelection = { ...selection };\n const blockIndent = start.line !== end.line;\n let endLine = end.line;\n if (start.line < end.line && end.character === 0) {\n endLine--;\n }\n for (let line = start.line; line <= endLine; line++) {\n const lineText = textDocument.getLineText(line);\n if (lineText === undefined) {\n continue;\n }\n if (blockIndent && lineText.trim().length === 0) {\n continue;\n }\n const indentUnit = lineText.startsWith('\\t') ? '\\t' : ' '.repeat(tabSize);\n let deleteLength = 0;\n let newText = indentUnit;\n if (outdent) {\n if (lineText.startsWith('\\t')) {\n deleteLength = 1;\n } else if (lineText.startsWith(' ')) {\n const leadingSpacesLength =\n lineText.length - lineText.trimStart().length;\n deleteLength = Math.min(indentUnit.length, leadingSpacesLength);\n }\n if (deleteLength === 0) {\n continue;\n }\n newText = '';\n }\n edits.push({\n range: {\n start: { line, character: 0 },\n end: { line, character: deleteLength },\n },\n newText,\n });\n const delta = newText.length - deleteLength;\n if (line === start.line) {\n newSelection = {\n ...newSelection,\n start: {\n ...start,\n character: Math.max(0, start.character + delta),\n },\n };\n }\n if (line === end.line) {\n newSelection = {\n ...newSelection,\n end: {\n ...end,\n character: Math.max(0, end.character + delta),\n },\n };\n }\n }\n return [edits, newSelection];\n}\n\n/**\n * The nearest zero-based document line at or beyond `line` in `direction`\n * that has a rendered row, or undefined when everything that way is hidden\n * inside a collapsed region. Vertical caret motion uses it to skip collapsed\n * regions atomically, like code folds.\n */\nexport type ResolveRenderableLine = (\n line: number,\n direction: 'up' | 'down'\n) => number | undefined;\n\n/**\n * Maps the cursor move to all selections.\n */\nexport function mapCursorMove(\n textDocument: TextDocument,\n selections: EditorSelection[],\n shortcut:\n | 'textStart'\n | 'start'\n | 'end'\n | 'up'\n | 'down'\n | 'left'\n | 'right'\n | 'wordLeft'\n | 'wordRight',\n options: CursorMoveOptions = {}\n): EditorSelection[] {\n const lineCount = textDocument.lineCount;\n return selections.map((selection) => {\n let { line, character } =\n shortcut === 'up' || shortcut === 'left' || shortcut === 'wordLeft'\n ? selection.start\n : selection.end;\n if (\n shortcut === 'textStart' ||\n shortcut === 'start' ||\n shortcut === 'end'\n ) {\n const caret = getCaretPosition(selection);\n line = caret.line;\n character = caret.character;\n const softLine = getSoftLineInfo(textDocument, line, character, options);\n if (shortcut === 'textStart') {\n const softLineText = textDocument\n .getLineText(line)\n .slice(softLine.start, softLine.end);\n const indent = softLine.start + getLeadingSpaces(softLineText);\n character = character === indent ? softLine.start : indent;\n } else {\n character = shortcut === 'start' ? softLine.start : softLine.end;\n }\n } else if (shortcut === 'up') {\n const moved = moveBySoftLine(textDocument, line, character, -1, options);\n if (moved !== undefined) {\n line = moved.line;\n character = moved.character;\n } else if (line > 0) {\n // Fold-skip: when the line above is collapsed, jump to the nearest\n // renderable line above it; stay put when nothing above renders.\n line =\n options.resolveRenderableLine == null\n ? line - 1\n : (options.resolveRenderableLine(line - 1, 'up') ?? line);\n }\n } else if (shortcut === 'down') {\n const moved = moveBySoftLine(textDocument, line, character, 1, options);\n if (moved !== undefined) {\n line = moved.line;\n character = moved.character;\n } else {\n const maxLine = Math.max(lineCount - 1, 0);\n if (line < maxLine) {\n line =\n options.resolveRenderableLine == null\n ? line + 1\n : Math.min(\n options.resolveRenderableLine(line + 1, 'down') ?? line,\n maxLine\n );\n }\n }\n } else if (isCollapsedSelection(selection)) {\n const lineLength = textDocument.getLineLength(line);\n character = Math.min(character, lineLength);\n if (shortcut === 'left' || shortcut === 'wordLeft') {\n if (character > 0) {\n // Step left by a whole grapheme so the caret never lands inside an\n // emoji or other multi-code-unit character.\n character =\n shortcut === 'left'\n ? stepCharacterByGrapheme(textDocument, line, character, false)\n : findWordBoundary(\n textDocument.getLineText(line),\n character,\n false\n );\n } else if (line > 0) {\n // Fold-skip: land at the end of the nearest renderable line above;\n // stay put when everything above is collapsed.\n const targetLine =\n options.resolveRenderableLine == null\n ? line - 1\n : options.resolveRenderableLine(line - 1, 'up');\n if (targetLine !== undefined) {\n line = targetLine;\n character = textDocument.getLineLength(line);\n }\n }\n } else if (character < lineLength) {\n character =\n shortcut === 'right'\n ? stepCharacterByGrapheme(textDocument, line, character, true)\n : findWordBoundary(textDocument.getLineText(line), character, true);\n } else if (line < lineCount - 1) {\n // Fold-skip: land at the start of the nearest renderable line below;\n // stay put when everything below is collapsed.\n const targetLine =\n options.resolveRenderableLine == null\n ? line + 1\n : options.resolveRenderableLine(line + 1, 'down');\n if (targetLine !== undefined) {\n line = Math.min(targetLine, lineCount - 1);\n character = 0;\n }\n }\n }\n const pos = { line, character };\n return {\n start: pos,\n end: pos,\n direction: DirectionNone,\n };\n });\n}\n\nfunction moveBySoftLine(\n textDocument: TextDocument,\n line: number,\n character: number,\n direction: -1 | 1,\n options: CursorMoveOptions\n): Position | undefined {\n if (options.getSoftLineOffsets === undefined) {\n return undefined;\n }\n\n const current = getSoftLineInfo(textDocument, line, character, options);\n const targetIndex = current.index + direction;\n let targetLine = line;\n let target: SoftLineInfo;\n\n if (targetIndex >= 0 && targetIndex < current.count) {\n target = getSoftLineInfoAtIndex(\n textDocument,\n targetLine,\n targetIndex,\n options\n );\n } else {\n const nextLine = line + direction;\n if (nextLine < 0 || nextLine >= textDocument.lineCount) {\n return { line, character };\n }\n\n // Fold-skip: crossing to another document line skips collapsed regions;\n // when nothing renders in that direction the caret stays put.\n const resolvedLine =\n options.resolveRenderableLine == null\n ? nextLine\n : options.resolveRenderableLine(\n nextLine,\n direction < 0 ? 'up' : 'down'\n );\n if (resolvedLine === undefined) {\n return { line, character };\n }\n\n targetLine = Math.min(resolvedLine, textDocument.lineCount - 1);\n const targetCount = getSoftLineCount(targetLine, options);\n target = getSoftLineInfoAtIndex(\n textDocument,\n targetLine,\n direction < 0 ? targetCount - 1 : 0,\n options\n );\n }\n\n const column = Math.max(0, character - current.start);\n const targetCharacter = target.start + column;\n const landedCharacter =\n target.index === target.count - 1\n ? targetCharacter\n : Math.min(targetCharacter, target.end);\n const targetLineText = textDocument.getLineText(targetLine);\n // Keep goal-column overshoots, but snap real offsets out of graphemes.\n return {\n line: targetLine,\n character:\n landedCharacter > targetLineText.length\n ? landedCharacter\n : snapCharacterToGraphemeBoundary(targetLineText, landedCharacter),\n };\n}\n\n// Snaps an editable position to the end of its grapheme so edits cannot split\n// a user-visible character. Stop once the containing cluster is resolved.\nexport function snapCharacterToGraphemeBoundary(\n lineText: string,\n character: number\n): number {\n if (character <= 0 || character >= lineText.length) {\n return character;\n }\n\n const segmenter = getGraphemeSegmenter();\n if (segmenter !== undefined) {\n for (const segment of segmenter.segment(lineText)) {\n if (character <= segment.index) {\n return character;\n }\n const segmentEnd = segment.index + segment.segment.length;\n if (character < segmentEnd) {\n return segmentEnd;\n }\n }\n return character;\n }\n\n // Degraded path for engines lacking Intl.Segmenter: preserve code points.\n let segmentStart = 0;\n for (const codePoint of lineText) {\n if (character <= segmentStart) {\n return character;\n }\n const segmentEnd = segmentStart + codePoint.length;\n if (character < segmentEnd) {\n return segmentEnd;\n }\n segmentStart = segmentEnd;\n }\n return character;\n}\n\nfunction getSoftLineInfo(\n textDocument: TextDocument,\n line: number,\n character: number,\n options: CursorMoveOptions\n): SoftLineInfo {\n const lineLength = textDocument.getLineLength(line);\n const offsets = options.getSoftLineOffsets?.(line);\n if (offsets === undefined || offsets.length < 2) {\n return { start: 0, end: lineLength, index: 0, count: 1 };\n }\n\n for (let index = 0; index + 1 < offsets.length; index++) {\n const softLine = getSoftLineInfoAtIndex(textDocument, line, index, options);\n if (character >= softLine.start && character <= softLine.end) {\n return softLine;\n }\n }\n\n return getSoftLineInfoAtIndex(\n textDocument,\n line,\n character < (offsets[0] ?? 0) ? 0 : offsets.length - 2,\n options\n );\n}\n\nfunction getSoftLineCount(line: number, options: CursorMoveOptions): number {\n const offsets = options.getSoftLineOffsets?.(line);\n return offsets === undefined || offsets.length < 2 ? 1 : offsets.length - 1;\n}\n\nfunction getSoftLineInfoAtIndex(\n textDocument: TextDocument,\n line: number,\n index: number,\n options: CursorMoveOptions\n): SoftLineInfo {\n const lineLength = textDocument.getLineLength(line);\n const offsets = options.getSoftLineOffsets?.(line);\n if (offsets === undefined || offsets.length < 2) {\n return { start: 0, end: lineLength, index: 0, count: 1 };\n }\n\n const count = offsets.length - 1;\n const boundedIndex = Math.max(0, Math.min(index, count - 1));\n const start = Math.max(0, Math.min(lineLength, offsets[boundedIndex] ?? 0));\n const end = Math.max(\n start,\n Math.min(lineLength, offsets[boundedIndex + 1] ?? lineLength)\n );\n return { start, end, index: boundedIndex, count };\n}\n\n/**\n * Same as mapCursorMove, but with shift key pressed.\n */\nexport function mapSelectionShift(\n textDocument: TextDocument,\n selections: EditorSelection[],\n shortcut:\n | 'textStart'\n | 'start'\n | 'end'\n | 'up'\n | 'down'\n | 'left'\n | 'right'\n | 'wordLeft'\n | 'wordRight',\n options: CursorMoveOptions = {}\n): EditorSelection[] {\n return selections.map((selection) => {\n const focusPosition =\n selection.direction === DirectionBackward\n ? selection.start\n : selection.end;\n const [movedFocusSelection] = mapCursorMove(\n textDocument,\n [\n {\n start: focusPosition,\n end: focusPosition,\n direction: DirectionNone,\n },\n ],\n shortcut,\n options\n );\n return createSelectionFrom(selection, movedFocusSelection);\n });\n}\n\n/**\n * Applies a text change to the given text document\n */\nexport function applyTextChangeToSelections<\n EType extends EditorType,\n LAnnotation,\n>(\n textDocument: TextDocument<EType, LAnnotation>,\n selections: EditorSelection[],\n edit: ResolvedTextEdit,\n lineAnnotations?: EditorLineAnnotation<EType, LAnnotation>[],\n tabSize = 2,\n undoBoundary = false\n): {\n nextSelections: EditorSelection[];\n change?: TextDocumentChange;\n} {\n const primarySelection = selections[selections.length - 1];\n if (primarySelection === undefined) {\n return { nextSelections: [] };\n }\n const selectionPositions: Position[] = [];\n for (const selection of selections) {\n selectionPositions.push(selection.start, selection.end);\n }\n const selectionOffsets = selectionPositions.map((position) =>\n textDocument.offsetAt(position)\n );\n const primaryStartOffset = selectionOffsets[(selections.length - 1) * 2];\n const primaryEndOffset = selectionOffsets[(selections.length - 1) * 2 + 1];\n const ordered: Array<{\n index: number;\n start: number;\n end: number;\n }> = [];\n let isAlreadyOrdered = true;\n for (let index = 0; index < selections.length; index++) {\n const entry = {\n index,\n start: selectionOffsets[index * 2],\n end: selectionOffsets[index * 2 + 1],\n };\n const previous = ordered[ordered.length - 1];\n if (\n previous !== undefined &&\n (entry.start < previous.start ||\n (entry.start === previous.start && entry.end < previous.end))\n ) {\n isAlreadyOrdered = false;\n }\n ordered.push(entry);\n }\n if (!isAlreadyOrdered) {\n ordered.sort((a, b) => {\n const startOrder = a.start - b.start;\n if (startOrder !== 0) {\n return startOrder;\n }\n const endOrder = a.end - b.end;\n if (endOrder !== 0) {\n return endOrder;\n }\n return a.index - b.index;\n });\n }\n const adjustedChange = normalizeLeadingIndentForChange(\n textDocument,\n edit,\n tabSize\n );\n const edits: ResolvedTextEdit[] = [];\n const nextSelectionOffsets: Array<[number, number] | undefined> = Array.from({\n length: selections.length,\n });\n let offsetDelta = 0;\n let mergedGroup:\n | {\n start: number;\n end: number;\n indices: number[];\n }\n | undefined;\n const finalizeMergedGroup = () => {\n if (mergedGroup === undefined) {\n return;\n }\n const perGroupChange = normalizeLeadingIndentForChange(\n textDocument,\n {\n start: mergedGroup.start,\n end: mergedGroup.end,\n text: adjustedChange.text,\n },\n tabSize\n );\n const newText = expandSingleNewlineInsert(\n textDocument,\n perGroupChange.text,\n perGroupChange.start\n );\n edits.push({\n start: perGroupChange.start,\n end: perGroupChange.end,\n text: newText,\n });\n const nextOffsets: [number, number] = [\n mergedGroup.start + offsetDelta + newText.length,\n mergedGroup.start + offsetDelta + newText.length,\n ];\n for (const index of mergedGroup.indices) {\n nextSelectionOffsets[index] = nextOffsets;\n }\n offsetDelta += newText.length - (perGroupChange.end - perGroupChange.start);\n mergedGroup = undefined;\n };\n for (const entry of ordered) {\n const startOffset = Math.max(\n 0,\n entry.start + (adjustedChange.start - primaryStartOffset)\n );\n const endOffset = Math.max(\n startOffset,\n entry.end + (adjustedChange.end - primaryEndOffset)\n );\n if (mergedGroup !== undefined && startOffset < mergedGroup.end) {\n mergedGroup.end = Math.max(mergedGroup.end, endOffset);\n mergedGroup.indices.push(entry.index);\n continue;\n }\n finalizeMergedGroup();\n mergedGroup = {\n start: startOffset,\n end: endOffset,\n indices: [entry.index],\n };\n }\n finalizeMergedGroup();\n\n const change = textDocument.applyResolvedEdits(\n edits,\n true,\n selections,\n undefined,\n undoBoundary\n );\n const nextSelections = createSelectionsFromOffsetPairs(\n textDocument,\n nextSelectionOffsets.map((offsets) => {\n if (offsets === undefined) {\n throw new Error('Missing next selection offsets');\n }\n return offsets;\n })\n );\n textDocument.setLastUndoSelectionsAfter(nextSelections);\n if (change !== undefined && lineAnnotations !== undefined) {\n const nextLineAnnotations = applyDocumentChangeToLineAnnotations(\n change,\n lineAnnotations\n );\n if (nextLineAnnotations !== undefined) {\n textDocument.setLastUndoLineAnnotations(\n lineAnnotations,\n nextLineAnnotations\n );\n }\n }\n return { nextSelections, change };\n}\n\n/**\n * Returns the next anchor/focus offsets after replacing a selection range.\n * When the inserted text still contains the original selection (auto-surround),\n * the inner range is reselected to match VS Code/CodeMirror behavior.\n */\n// Detect exact auto-surround replacements before a substring search can match\n// the newly inserted opening delimiter instead of the preserved selection.\nfunction getAutoSurroundPreservedOffset(\n originalText: string,\n newText: string\n): number | undefined {\n if (newText.length !== originalText.length + 2) {\n return undefined;\n }\n\n const closeChar = AUTO_SURROUND_CLOSE_CHARS.get(newText[0]);\n if (\n closeChar === undefined ||\n newText[newText.length - 1] !== closeChar ||\n newText.slice(1, -1) !== originalText\n ) {\n return undefined;\n }\n\n return 1;\n}\n\nfunction getNextSelectionOffsetPairAfterReplace(\n textDocument: TextDocument,\n entry: { start: number; end: number },\n offsetDelta: number,\n newText: string\n): [number, number] {\n const insertStart = entry.start + offsetDelta;\n const insertEnd = insertStart + newText.length;\n const originalLength = entry.end - entry.start;\n if (originalLength > 0) {\n const originalText = textDocument.getTextSlice(entry.start, entry.end);\n const preservedOffset =\n getAutoSurroundPreservedOffset(originalText, newText) ??\n newText.indexOf(originalText);\n if (\n preservedOffset !== -1 &&\n preservedOffset + originalText.length <= newText.length\n ) {\n const rangeStart = insertStart + preservedOffset;\n return [rangeStart, rangeStart + originalText.length];\n }\n }\n return [insertEnd, insertEnd];\n}\n\n/**\n * Applies text replacements to multiple selections. Texts pair by selection\n * index unless they are explicitly marked as document ordered.\n */\nexport function applyTextReplaceToSelections<\n EType extends EditorType,\n LAnnotation,\n>(\n textDocument: TextDocument<EType, LAnnotation>,\n selections: EditorSelection[],\n texts: string[],\n lineAnnotations?: EditorLineAnnotation<EType, LAnnotation>[],\n undoBoundary = false,\n textOrder: 'selection' | 'document' = 'selection'\n): {\n nextSelections: EditorSelection[];\n change?: TextDocumentChange;\n} {\n if (selections.length !== texts.length) {\n throw new Error(\n 'Selection text replacements must match the selection count'\n );\n }\n const selectionPositions: Position[] = [];\n for (const selection of selections) {\n selectionPositions.push(selection.start, selection.end);\n }\n const selectionOffsets = selectionPositions.map((position) =>\n textDocument.offsetAt(position)\n );\n const ordered: Array<{\n index: number;\n start: number;\n end: number;\n }> = [];\n let isAlreadyOrdered = true;\n for (let index = 0; index < selections.length; index++) {\n const entry = {\n index,\n start: selectionOffsets[index * 2],\n end: selectionOffsets[index * 2 + 1],\n };\n const previous = ordered[ordered.length - 1];\n if (\n previous !== undefined &&\n (entry.start < previous.start ||\n (entry.start === previous.start && entry.end < previous.end))\n ) {\n isAlreadyOrdered = false;\n }\n ordered.push(entry);\n }\n if (!isAlreadyOrdered) {\n ordered.sort((a, b) => {\n const startOrder = a.start - b.start;\n if (startOrder !== 0) {\n return startOrder;\n }\n const endOrder = a.end - b.end;\n if (endOrder !== 0) {\n return endOrder;\n }\n return a.index - b.index;\n });\n }\n const allDeletes = texts.every((text) => text === '');\n let edits: ResolvedTextEdit[];\n const nextSelectionOffsetPairs: Array<[number, number] | undefined> =\n Array.from({\n length: selections.length,\n });\n if (allDeletes) {\n edits = [];\n let hasEffect = false;\n for (const entry of ordered) {\n nextSelectionOffsetPairs[entry.index] = [entry.end, entry.end];\n if (entry.start >= entry.end) {\n continue;\n }\n hasEffect = true;\n const last = edits[edits.length - 1];\n if (last !== undefined && entry.start < last.end) {\n edits[edits.length - 1] = {\n start: last.start,\n end: Math.max(last.end, entry.end),\n text: '',\n };\n } else {\n edits.push({ start: entry.start, end: entry.end, text: '' });\n }\n }\n if (!hasEffect) {\n return { nextSelections: selections };\n }\n for (const entry of ordered) {\n const caret = entry.end;\n let delta = 0;\n let next = caret;\n for (const edit of edits) {\n if (caret <= edit.start) {\n break;\n }\n if (caret >= edit.end) {\n delta -= edit.end - edit.start;\n continue;\n }\n next = edit.start + delta;\n break;\n }\n if (next === caret) {\n next += delta;\n }\n nextSelectionOffsetPairs[entry.index] = [next, next];\n }\n } else {\n edits = [];\n let offsetDelta = 0;\n let previousEditEnd = -1;\n for (let index = 0; index < ordered.length; index++) {\n const entry = ordered[index];\n if (entry.start < previousEditEnd) {\n throw new Error('Overlapping multi-selection edits are not supported');\n }\n previousEditEnd = entry.end;\n const newText = expandSingleNewlineInsert(\n textDocument,\n texts[textOrder === 'document' ? index : entry.index],\n entry.start\n );\n edits.push({\n start: entry.start,\n end: entry.end,\n text: newText,\n });\n nextSelectionOffsetPairs[entry.index] =\n getNextSelectionOffsetPairAfterReplace(\n textDocument,\n entry,\n offsetDelta,\n newText\n );\n offsetDelta += newText.length - (entry.end - entry.start);\n }\n }\n\n const change = textDocument.applyResolvedEdits(\n edits,\n true,\n selections,\n undefined,\n undoBoundary\n );\n const nextSelections = createSelectionsFromOffsetPairs(\n textDocument,\n nextSelectionOffsetPairs.map((offsets) => {\n if (offsets === undefined) {\n throw new Error('Missing next selection offsets');\n }\n return offsets;\n })\n );\n textDocument.setLastUndoSelectionsAfter(nextSelections);\n if (change !== undefined && lineAnnotations !== undefined) {\n const nextLineAnnotations = applyDocumentChangeToLineAnnotations(\n change,\n lineAnnotations\n );\n if (nextLineAnnotations !== undefined) {\n textDocument.setLastUndoLineAnnotations(\n lineAnnotations,\n nextLineAnnotations\n );\n }\n }\n return { nextSelections, change };\n}\n\nexport type AutoSurround =\n | 'default'\n | 'never'\n | 'brackets'\n | 'quotes'\n | 'languageDefined';\n\nfunction shouldAutoSurroundChar(\n autoSurround: AutoSurround | undefined,\n char: string\n): boolean {\n if (autoSurround === 'never') {\n return false;\n }\n if (autoSurround === 'brackets') {\n return AUTO_SURROUND_BRACKET_CHARS.has(char);\n }\n if (autoSurround === 'quotes') {\n return AUTO_SURROUND_QUOTE_CHARS.has(char);\n }\n return true;\n}\n\n/**\n * Returns per-selection replacement text when typing a surround character over\n * non-collapsed selections, matching VS Code auto-surround behavior.\n */\nexport function getAutoSurroundReplacementTexts(\n textDocument: TextDocument,\n selections: EditorSelection[],\n char: string,\n autoSurround?: AutoSurround\n): string[] | undefined {\n if (char.length !== 1 || selections.length === 0) {\n return undefined;\n }\n const closeChar = AUTO_SURROUND_CLOSE_CHARS.get(char);\n if (closeChar === undefined || !shouldAutoSurroundChar(autoSurround, char)) {\n return undefined;\n }\n const replacements: string[] = [];\n for (const selection of selections) {\n if (isCollapsedSelection(selection)) {\n return undefined;\n }\n replacements.push(char + textDocument.getText(selection) + closeChar);\n }\n return replacements;\n}\n\n/**\n * Swaps the two characters adjacent to a collapsed selection, matching browser\n * insertTranspose (Ctrl+T) behavior.\n */\nexport function applyTransposeToSelections<\n EType extends EditorType,\n LAnnotation,\n>(\n textDocument: TextDocument<EType, LAnnotation>,\n selections: EditorSelection[],\n lineAnnotations?: EditorLineAnnotation<EType, LAnnotation>[]\n): {\n nextSelections: EditorSelection[];\n change?: TextDocumentChange;\n} {\n const edits: ResolvedTextEdit[] = [];\n const nextOffsetPairs: Array<[number, number]> = [];\n\n for (const selection of selections) {\n const [anchor, focus] = getSelectionAnchorAndFocusOffsets(\n textDocument,\n selection\n );\n if (!isCollapsedSelection(selection)) {\n nextOffsetPairs.push([anchor, focus]);\n continue;\n }\n\n const { line, character } = selection.start;\n const offset = anchor;\n const lineText = textDocument.getLineText(line);\n const lineLength = lineText.length;\n // Document offset of column 0 on this line, used to translate the\n // grapheme-cluster columns below back into document offsets.\n const lineStart = offset - character;\n const graphemeStarts = getLineGraphemeStarts(lineText);\n let edit: ResolvedTextEdit | undefined;\n\n if (character > 0 && character < lineLength) {\n // Swap the whole grapheme before the caret with the one after it so a\n // surrogate pair (emoji) on either side is moved intact.\n const before = findClusterBreak(\n lineText,\n character,\n false,\n graphemeStarts\n );\n const after = findClusterBreak(lineText, character, true, graphemeStarts);\n edit = {\n start: lineStart + before,\n end: lineStart + after,\n text:\n lineText.slice(character, after) + lineText.slice(before, character),\n };\n nextOffsetPairs.push([lineStart + after, lineStart + after]);\n } else if (character === lineLength && graphemeStarts.length >= 2) {\n // Swap the last two graphemes on the line.\n const lastStart = graphemeStarts[graphemeStarts.length - 1];\n const secondLastStart = graphemeStarts[graphemeStarts.length - 2];\n edit = {\n start: lineStart + secondLastStart,\n end: offset,\n text:\n lineText.slice(lastStart, lineLength) +\n lineText.slice(secondLastStart, lastStart),\n };\n nextOffsetPairs.push([offset, offset]);\n } else if (character === 0 && line > 0 && lineLength > 0) {\n // Carry the previous line's last grapheme and this line's first grapheme\n // across the line break, swapping their order.\n const prevLine = line - 1;\n const prevLineText = textDocument.getLineText(prevLine);\n const prevLength = prevLineText.length;\n const prevEnd = textDocument.offsetAt({\n line: prevLine,\n character: prevLength,\n });\n const prevGraphemeStart =\n prevLength > 0\n ? findClusterBreak(\n prevLineText,\n prevLength,\n false,\n getLineGraphemeStarts(prevLineText)\n )\n : prevLength;\n const firstEnd = findClusterBreak(lineText, 0, true, graphemeStarts);\n const prevStart = prevEnd - (prevLength - prevGraphemeStart);\n const newText =\n lineText.slice(0, firstEnd) +\n textDocument.getTextSlice(prevEnd, offset) +\n prevLineText.slice(prevGraphemeStart, prevLength);\n edit = {\n start: prevStart,\n end: offset + firstEnd,\n text: newText,\n };\n const caret = prevStart + newText.length;\n nextOffsetPairs.push([caret, caret]);\n } else {\n nextOffsetPairs.push([anchor, focus]);\n continue;\n }\n\n edits.push(edit);\n }\n\n if (edits.length === 0) {\n return { nextSelections: selections };\n }\n\n edits.sort((a, b) => a.start - b.start);\n for (let index = 1; index < edits.length; index++) {\n if (edits[index].start < edits[index - 1].end) {\n throw new Error('Overlapping multi-selection edits are not supported');\n }\n }\n\n const change = textDocument.applyResolvedEdits(edits, true, selections);\n const nextSelections = createSelectionsFromOffsetPairs(\n textDocument,\n nextOffsetPairs\n );\n textDocument.setLastUndoSelectionsAfter(nextSelections);\n if (change !== undefined && lineAnnotations !== undefined) {\n const nextLineAnnotations = applyDocumentChangeToLineAnnotations(\n change,\n lineAnnotations\n );\n if (nextLineAnnotations !== undefined) {\n textDocument.setLastUndoLineAnnotations(\n lineAnnotations,\n nextLineAnnotations\n );\n }\n }\n return { nextSelections, change };\n}\n\n/**\n * Deletes from each selection to the end of its line, including the line break\n * when the caret is already at the end of a non-final line. Non-collapsed\n * selections delete their selected text instead.\n */\nexport function applyDeleteHardLineForwardToSelections<\n EType extends EditorType,\n LAnnotation,\n>(\n textDocument: TextDocument<EType, LAnnotation>,\n selections: EditorSelection[],\n lineAnnotations?: EditorLineAnnotation<EType, LAnnotation>[]\n): {\n nextSelections: EditorSelection[];\n change?: TextDocumentChange;\n} {\n const deleteSelections: EditorSelection[] = selections.map((selection) => {\n const range = resolveDeleteHardLineForwardRange(textDocument, selection);\n return {\n start: range.start,\n end: range.end,\n direction: DirectionNone,\n };\n });\n return applyTextReplaceToSelections(\n textDocument,\n deleteSelections,\n deleteSelections.map(() => ''),\n lineAnnotations\n );\n}\n\n/**\n * Deletes from each selection back to the start of its soft (visual) line.\n * Non-collapsed selections delete their selected text instead.\n */\nexport function applyDeleteSoftLineBackwardToSelections<\n EType extends EditorType,\n LAnnotation,\n>(\n textDocument: TextDocument<EType, LAnnotation>,\n selections: EditorSelection[],\n getSoftLineStart?: (line: number, character: number) => number,\n lineAnnotations?: EditorLineAnnotation<EType, LAnnotation>[]\n): {\n nextSelections: EditorSelection[];\n change?: TextDocumentChange;\n} {\n const deleteSelections: EditorSelection[] = selections.map((selection) => {\n if (!isCollapsedSelection(selection)) {\n return {\n start: selection.start,\n end: selection.end,\n direction: DirectionNone,\n };\n }\n const caret = getCaretPosition(selection);\n const { line, character } = caret;\n const softLineStart = getSoftLineStart?.(line, character) ?? 0;\n if (character > softLineStart) {\n return {\n start: { line, character: softLineStart },\n end: { line, character },\n direction: DirectionNone,\n };\n }\n if (line === 0) {\n return {\n start: caret,\n end: caret,\n direction: DirectionNone,\n };\n }\n const prevLineLength = textDocument.getLineLength(line - 1);\n return {\n start: { line: line - 1, character: prevLineLength },\n end: { line, character: 0 },\n direction: DirectionNone,\n };\n });\n return applyTextReplaceToSelections(\n textDocument,\n deleteSelections,\n deleteSelections.map(() => ''),\n lineAnnotations\n );\n}\n\n/**\n * Deletes the word or separator group immediately before each selection.\n * Non-collapsed selections delete their selected text instead.\n */\nexport function applyDeleteWordBackwardToSelections<\n EType extends EditorType,\n LAnnotation,\n>(\n textDocument: TextDocument<EType, LAnnotation>,\n selections: EditorSelection[],\n lineAnnotations?: EditorLineAnnotation<EType, LAnnotation>[]\n): {\n nextSelections: EditorSelection[];\n change?: TextDocumentChange;\n} {\n const deleteSelections: EditorSelection[] = selections.map((selection) => {\n const [start, end] = resolveDeleteWordBackwardRange(\n textDocument,\n selection\n );\n return {\n start,\n end,\n direction: DirectionNone,\n };\n });\n return applyTextReplaceToSelections(\n textDocument,\n deleteSelections,\n deleteSelections.map(() => ''),\n lineAnnotations\n );\n}\n\n/**\n * Resolves the document range deleted by Backspace or Delete at a collapsed\n * caret. Non-collapsed selections delete their selected text instead.\n */\nexport function resolveDeleteCharacterRange(\n textDocument: TextDocument,\n selection: EditorSelection,\n forward: boolean\n): [start: Position, end: Position] {\n if (!isCollapsedSelection(selection)) {\n return [selection.start, selection.end];\n }\n\n const caret = getCaretPosition(selection);\n let { line, character } = caret;\n const lineLength = textDocument.getLineLength(line);\n const lineCount = textDocument.lineCount;\n\n // A preserved vertical-move goal column can overshoot a shorter line; clamp\n // before stepping so Backspace/Delete target the visible caret position.\n character = Math.min(character, lineLength);\n\n if (forward) {\n if (character < lineLength) {\n return [\n { line, character },\n {\n line,\n character: stepCharacterByGrapheme(\n textDocument,\n line,\n character,\n true\n ),\n },\n ];\n }\n if (line < lineCount - 1) {\n return [\n { line, character: lineLength },\n { line: line + 1, character: 0 },\n ];\n }\n return [caret, caret];\n }\n\n if (character > 0) {\n return [\n {\n line,\n character: stepCharacterByGrapheme(\n textDocument,\n line,\n character,\n false\n ),\n },\n { line, character },\n ];\n }\n if (line > 0) {\n const prevLineLength = textDocument.getLineLength(line - 1);\n return [\n { line: line - 1, character: prevLineLength },\n { line, character: 0 },\n ];\n }\n return [caret, caret];\n}\n\n/**\n * Deletes one grapheme (or selected text) at each selection.\n */\nexport function applyDeleteCharacterToSelections<\n EType extends EditorType,\n LAnnotation,\n>(\n textDocument: TextDocument<EType, LAnnotation>,\n selections: EditorSelection[],\n forward: boolean,\n lineAnnotations?: EditorLineAnnotation<EType, LAnnotation>[],\n tabSize = 2\n): {\n nextSelections: EditorSelection[];\n change?: TextDocumentChange;\n} {\n const deleteSelections: EditorSelection[] = selections.map((selection) => {\n let [start, end] = resolveDeleteCharacterRange(\n textDocument,\n selection,\n forward\n );\n // Only grow a Backspace into a full indent unit for a collapsed caret. When\n // the user has an explicit selection, Backspace must delete exactly that\n // selection rather than expanding it to a whole soft tab.\n if (!forward && isCollapsedSelection(selection)) {\n const normalized = normalizeLeadingIndentForChange(\n textDocument,\n {\n start: textDocument.offsetAt(start),\n end: textDocument.offsetAt(end),\n text: '',\n },\n tabSize\n );\n start = textDocument.positionAt(normalized.start);\n end = textDocument.positionAt(normalized.end);\n }\n return {\n start,\n end,\n direction: DirectionNone,\n };\n });\n return applyTextReplaceToSelections(\n textDocument,\n deleteSelections,\n deleteSelections.map(() => ''),\n lineAnnotations\n );\n}\n\n/**\n * Checks if a selection is collapsed.\n */\nexport function isCollapsedSelection(\n selection: EditorSelection | Range\n): boolean {\n return (\n selection.start.line === selection.end.line &&\n selection.start.character === selection.end.character\n );\n}\n\n/**\n * Returns the caret (focus) position for a selection.\n */\nexport function getCaretPosition(selection: EditorSelection): Position {\n const { start, end, direction } = selection;\n return direction === DirectionBackward ? start : end;\n}\n\n/**\n * Checks if a line is editable.\n */\nexport function isLineEditable(lineType: string): boolean {\n return (\n lineType === 'context' ||\n lineType === 'context-expanded' ||\n lineType === 'change-addition'\n );\n}\n\n/**\n * Checks whether selections `a` and `b` intersect.\n */\nexport function selectionIntersects(\n a: EditorSelection | Range,\n b: EditorSelection | Range\n): boolean {\n const aCollapsed = isCollapsedSelection(a);\n const bCollapsed = isCollapsedSelection(b);\n if (aCollapsed && bCollapsed) {\n return comparePosition(a.start, b.start) === 0;\n }\n if (aCollapsed) {\n return (\n comparePosition(b.start, a.start) <= 0 &&\n comparePosition(a.start, b.end) <= 0\n );\n }\n if (bCollapsed) {\n return (\n comparePosition(a.start, b.start) <= 0 &&\n comparePosition(b.start, a.end) <= 0\n );\n }\n return (\n comparePosition(a.start, b.end) < 0 && comparePosition(b.start, a.end) < 0\n );\n}\n\n/**\n * Compares two positions.\n */\nexport function comparePosition(a: Position, b: Position): number {\n if (a.line !== b.line) {\n return a.line - b.line;\n }\n return a.character - b.character;\n}\n\n/**\n * Creates a selection from anchor and focus offsets.\n */\nexport function createSelectionFromAnchorAndFocusOffsets(\n textDocument: TextDocument,\n anchorOffset: number,\n focusOffset: number\n): EditorSelection {\n const direction =\n anchorOffset === focusOffset\n ? DirectionNone\n : anchorOffset < focusOffset\n ? DirectionForward\n : DirectionBackward;\n const start = Math.min(anchorOffset, focusOffset);\n const end = Math.max(anchorOffset, focusOffset);\n return {\n start: textDocument.positionAt(start),\n end: textDocument.positionAt(end),\n direction,\n };\n}\n\n/**\n * Maps a single offset from the pre-edit document into the post-edit document.\n * `edits` are resolved edits in pre-edit offsets, sorted ascending and\n * non-overlapping. An offset at or after an edit's start shifts to the end of\n * that edit's replacement (right gravity), so text inserted at the caret pushes\n * the caret past it; an offset strictly before an edit is only shifted by the\n * net length change of the edits that precede it.\n */\nexport function remapOffsetThroughEdits(\n offset: number,\n edits: readonly ResolvedTextEdit[]\n): number {\n let delta = 0;\n for (const edit of edits) {\n if (offset < edit.start) {\n break;\n }\n if (offset >= edit.end) {\n delta += edit.text.length - (edit.end - edit.start);\n } else {\n return edit.start + delta + edit.text.length;\n }\n }\n return offset + delta;\n}\n\n/**\n * Re-anchors selections after a batch of text edits has been applied, so the\n * caret keeps pointing at the same logical location in the changed buffer.\n *\n * `selectionOffsets` (one `[start, end]` pair per selection) and `edits` are\n * measured in the PRE-edit document; the returned selections are built from\n * `textDocument`, which must already reflect the applied edits. Selection\n * direction is preserved by remapping each edge and re-deriving anchor/focus.\n */\nexport function remapSelectionsAfterEdits(\n textDocument: TextDocument,\n selections: readonly EditorSelection[],\n selectionOffsets: ReadonlyArray<readonly [number, number]>,\n edits: readonly ResolvedTextEdit[]\n): EditorSelection[] {\n return selections.map((selection, index) => {\n const [startOffset, endOffset] = selectionOffsets[index];\n const nextStart = remapOffsetThroughEdits(startOffset, edits);\n const nextEnd = remapOffsetThroughEdits(endOffset, edits);\n const anchorOffset =\n selection.direction === DirectionBackward ? nextEnd : nextStart;\n const focusOffset =\n selection.direction === DirectionBackward ? nextStart : nextEnd;\n return createSelectionFromAnchorAndFocusOffsets(\n textDocument,\n anchorOffset,\n focusOffset\n );\n });\n}\n\n/**\n * Creates a selection from a anchor and focus selection.\n */\nexport function createSelectionFrom(\n anchorSelection: EditorSelection,\n focusSelection: EditorSelection\n): EditorSelection {\n const anchor =\n anchorSelection.direction === DirectionBackward\n ? anchorSelection.end\n : anchorSelection.start;\n const currentStartOrder = comparePosition(anchor, focusSelection.start);\n const currentEndOrder = comparePosition(anchor, focusSelection.end);\n let focus = focusSelection.end;\n if (currentStartOrder <= 0) {\n focus = focusSelection.end;\n } else if (currentEndOrder >= 0) {\n focus = focusSelection.start;\n } else {\n // When the original anchor sits inside `current`, keep whichever edge\n // stayed at the anchor so drag direction remains stable.\n focus = currentStartOrder === 0 ? focusSelection.end : focusSelection.start;\n }\n const anchorVsFocus = comparePosition(anchor, focus);\n const direction: SelectionDirection =\n anchorVsFocus === 0\n ? DirectionNone\n : anchorVsFocus < 0\n ? DirectionForward\n : DirectionBackward;\n const selectionStart = anchorVsFocus <= 0 ? anchor : focus;\n const selectionEnd = anchorVsFocus <= 0 ? focus : anchor;\n return {\n start: selectionStart,\n end: selectionEnd,\n direction,\n };\n}\n\n/**\n * Extends or shrinks the selection `original` using the endpoints of `target`, \\\n * matching contenteditable shift + click extend behavior.\n */\nexport function extendSelection(\n original: EditorSelection,\n target: EditorSelection\n): EditorSelection {\n const leftExtended = comparePosition(target.start, original.start) < 0;\n const rightExtended = comparePosition(target.end, original.end) > 0;\n\n if (leftExtended && !rightExtended) {\n return {\n start: target.start,\n end: original.end,\n direction: DirectionBackward,\n };\n }\n\n if (rightExtended && !leftExtended) {\n return {\n start: original.start,\n end: target.end,\n direction: DirectionForward,\n };\n }\n\n if (original.direction === DirectionBackward) {\n return {\n start: target.start,\n end: original.end,\n direction:\n comparePosition(target.start, original.end) === 0\n ? DirectionNone\n : DirectionBackward,\n };\n }\n\n return {\n start: original.start,\n end: target.end,\n direction:\n comparePosition(original.start, target.end) === 0\n ? DirectionNone\n : DirectionForward,\n };\n}\n\n/**\n * Extends multiple selections.\n */\nexport function extendSelections(\n selections: EditorSelection[],\n target: EditorSelection\n): EditorSelection[] {\n const newSelections = selections.map((selection) => {\n return extendSelection(selection, target);\n });\n return mergeOverlappingSelections(newSelections);\n}\n\n/**\n * Merges overlapping selections.\n */\nexport function mergeOverlappingSelections(\n selections: EditorSelection[]\n): EditorSelection[] {\n if (selections.length <= 1) {\n return selections;\n }\n const ordered = selections\n .map((selection, index) => ({ index, selection }))\n .sort((a, b) => {\n const startOrder = comparePosition(a.selection.start, b.selection.start);\n if (startOrder !== 0) {\n return startOrder;\n }\n const endOrder = comparePosition(a.selection.end, b.selection.end);\n return endOrder !== 0 ? endOrder : a.index - b.index;\n });\n const merged: {\n index: number;\n selection: EditorSelection;\n }[] = [];\n\n let current = ordered[0];\n for (const entry of ordered.slice(1)) {\n if (selectionIntersects(current.selection, entry.selection)) {\n const latest = entry.index > current.index ? entry : current;\n const start =\n comparePosition(entry.selection.start, current.selection.start) < 0\n ? entry.selection.start\n : current.selection.start;\n const end =\n comparePosition(entry.selection.end, current.selection.end) > 0\n ? entry.selection.end\n : current.selection.end;\n let direction = latest.selection.direction;\n if (direction === DirectionNone && comparePosition(start, end) !== 0) {\n direction =\n comparePosition(latest.selection.start, start) === 0\n ? DirectionBackward\n : DirectionForward;\n }\n current = { index: latest.index, selection: { direction, end, start } };\n continue;\n }\n\n merged.push(current);\n current = entry;\n }\n merged.push(current);\n\n return merged\n .sort((a, b) => a.index - b.index)\n .map(({ selection }) => selection);\n}\n\n/**\n * Converts selections into merged line blocks for line-based commands.\n */\nexport function getSelectedLineBlocks(\n selections: EditorSelection[]\n): { startLine: number; endLine: number }[] {\n const blocks = selections\n .map((selection) => {\n let endLine = selection.end.line;\n if (\n selection.end.character === 0 &&\n comparePosition(selection.start, selection.end) !== 0\n ) {\n endLine--;\n }\n return {\n startLine: selection.start.line,\n endLine: Math.max(selection.start.line, endLine),\n };\n })\n .sort((a, b) => {\n const startOrder = a.startLine - b.startLine;\n return startOrder !== 0 ? startOrder : a.endLine - b.endLine;\n });\n\n const merged: { startLine: number; endLine: number }[] = [];\n for (const block of blocks) {\n const previous = merged.at(-1);\n if (previous !== undefined && block.startLine <= previous.endLine + 1) {\n previous.endLine = Math.max(previous.endLine, block.endLine);\n } else {\n merged.push({ ...block });\n }\n }\n return merged;\n}\n\n/**\n * Moves a selection's line positions after its lines are shifted, clamping to\n * the target document bounds.\n */\nexport function shiftSelectionLines(\n selection: EditorSelection,\n direction: -1 | 1,\n lineCount: number,\n getLineLength: (line: number) => number\n): EditorSelection {\n const shiftPosition = (position: Position): Position => {\n const line = position.line + direction;\n if (line >= lineCount) {\n const lastLine = Math.max(0, lineCount - 1);\n return {\n line: lastLine,\n character: getLineLength(lastLine),\n };\n }\n if (line < 0) {\n return { line: 0, character: 0 };\n }\n return {\n line,\n character: position.character,\n };\n };\n\n return {\n start: shiftPosition(selection.start),\n end: shiftPosition(selection.end),\n direction: selection.direction,\n };\n}\n\n/**\n * Finds the next matching word and updates the selections.\n */\nexport function findNextMatch(\n textDocument: TextDocument,\n selections: EditorSelection[]\n): EditorSelection[] | undefined {\n if (selections.length === 0) {\n return undefined;\n }\n\n const normalizedSelections = selections.map((selection) =>\n isCollapsedSelection(selection)\n ? expandCollapsedSelectionToWord(textDocument, selection)\n : selection\n );\n const texts = normalizedSelections.map((s) => textDocument.getText(s));\n const needle = texts[0];\n if (needle.length === 0 || texts.some((t) => t !== needle)) {\n return undefined;\n }\n\n const occupied = normalizedSelections.map(\n (s) =>\n [textDocument.offsetAt(s.start), textDocument.offsetAt(s.end)] as [\n number,\n number,\n ]\n );\n const nextOffset = textDocument.findNextNonOverlappingSubstring(\n needle,\n occupied\n );\n if (nextOffset === undefined) {\n return normalizedSelections.some((selection, index) => {\n const original = selections[index];\n return (\n comparePosition(selection.start, original.start) !== 0 ||\n comparePosition(selection.end, original.end) !== 0 ||\n selection.direction !== original.direction\n );\n })\n ? normalizedSelections\n : undefined;\n }\n const added = createSelectionFromAnchorAndFocusOffsets(\n textDocument,\n nextOffset,\n nextOffset + needle.length\n );\n return [...normalizedSelections, added];\n}\n\n/**\n * Get the full selection of the document.\n */\nexport function getDocumentFullSelection(\n textDocument: TextDocument\n): EditorSelection {\n const lastLine = textDocument.lineCount - 1;\n const lastCharacter = textDocument.getLineLength(lastLine);\n return {\n start: { line: 0, character: 0 },\n end: { line: lastLine, character: lastCharacter },\n direction: DirectionForward,\n };\n}\n\n/**\n * Get the boundary selection of the document.\n */\nexport function getDocumentBoundarySelection(\n textDocument: TextDocument,\n atEnd: boolean,\n trimmedEndNewLine?: boolean\n): EditorSelection {\n let line = 0;\n if (atEnd) {\n const lastLine = textDocument.lineCount - 1;\n const hasTrailingBlankLine =\n trimmedEndNewLine === true &&\n lastLine > 0 &&\n textDocument.getLineLength(lastLine) === 0;\n line = hasTrailingBlankLine ? lastLine - 1 : lastLine;\n }\n const character = atEnd ? textDocument.getLineLength(line) : 0;\n const start = { line, character };\n return {\n start: start,\n end: start,\n direction: DirectionForward,\n };\n}\n\ninterface ClipboardRegion {\n start: number;\n end: number;\n}\n\n/** Resolves the document offset range one selection contributes to a copy. */\nfunction resolveClipboardRegion(\n textDocument: TextDocument,\n selection: EditorSelection\n): ClipboardRegion {\n if (isCollapsedSelection(selection)) {\n const line = selection.start.line;\n const start = textDocument.offsetAt({ line, character: 0 });\n const end =\n line < textDocument.lineCount - 1\n ? textDocument.offsetAt({ line: line + 1, character: 0 })\n : textDocument.offsetAt({\n line,\n character: textDocument.getLineLength(line),\n });\n return { start, end };\n }\n const start = textDocument.offsetAt(selection.start);\n const end = textDocument.offsetAt(selection.end);\n return start <= end ? { start, end } : { start: end, end: start };\n}\n\n/**\n * Resolves the document offset range each selection contributes to the\n * clipboard, ordered by position. A collapsed selection contributes its whole\n * logical line including the trailing line break; the final line has no\n * trailing break to include. A ranged selection contributes the selected text.\n */\nfunction resolveClipboardRegions(\n textDocument: TextDocument,\n selections: EditorSelection[]\n): ClipboardRegion[] {\n return selections\n .map((selection) => resolveClipboardRegion(textDocument, selection))\n .sort((a, b) => {\n const startOrder = a.start - b.start;\n return startOrder !== 0 ? startOrder : a.end - b.end;\n });\n}\n\n/**\n * Gets the text contributed by each selection in document order, preserving\n * the pairing needed to paste the values into another set of selections.\n */\nexport function getSelectionClipboardTexts(\n textDocument: TextDocument,\n selections: EditorSelection[]\n): string[] {\n const regions = resolveClipboardRegions(textDocument, selections);\n return regions.map(({ start, end }) => textDocument.getTextSlice(start, end));\n}\n\n/**\n * Get the clipboard text of the selections for the given text document. Used by\n * both copy and cut so the two stay in sync. Overlapping regions (e.g. several\n * carets on one line) are merged so the same text is never emitted twice, and a\n * line-ending separator is inserted only between regions that aren't already\n * contiguous in the document.\n */\nexport function getSelectionText(\n textDocument: TextDocument,\n selections: EditorSelection[]\n): string {\n const regions = resolveClipboardRegions(textDocument, selections);\n const eol = textDocument.eol;\n let result = '';\n let prevEnd = -1;\n for (const region of regions) {\n if (region.end <= region.start) {\n continue;\n }\n if (region.start <= prevEnd) {\n // Contiguous with or overlapping the previous region: extend it rather\n // than repeat any shared text.\n if (region.end > prevEnd) {\n result += textDocument.getTextSlice(prevEnd, region.end);\n prevEnd = region.end;\n }\n continue;\n }\n if (result.length > 0 && !endsWithLineBreak(result)) {\n result += eol;\n }\n result += textDocument.getTextSlice(region.start, region.end);\n prevEnd = region.end;\n }\n return result;\n}\n\ninterface SelectionCut {\n index: number;\n edit: ResolvedTextEdit;\n}\n\n// Resolves the deletion an individual selection contributes to a cut: a\n// collapsed caret removes its whole logical line, while a ranged selection\n// removes only the selected text.\nfunction resolveSelectionCutEdit(\n textDocument: TextDocument,\n selection: EditorSelection\n): ResolvedTextEdit {\n if (isCollapsedSelection(selection)) {\n return resolveCollapsedSelectionCutEdit(textDocument, selection);\n }\n const [start, end] =\n comparePosition(selection.start, selection.end) <= 0\n ? [selection.start, selection.end]\n : [selection.end, selection.start];\n return {\n start: textDocument.offsetAt(start),\n end: textDocument.offsetAt(end),\n text: '',\n };\n}\n\n// A caret-only cut removes the whole logical line. Non-final lines delete\n// their trailing line break; the final line deletes the preceding break so\n// no empty line is left behind.\nfunction resolveCollapsedSelectionCutEdit(\n textDocument: TextDocument,\n selection: EditorSelection\n): ResolvedTextEdit {\n const line = selection.start.line;\n const lineStart = textDocument.offsetAt({ line, character: 0 });\n const lineEnd = textDocument.offsetAt({\n line,\n character: textDocument.getLineLength(line),\n });\n\n if (line < textDocument.lineCount - 1) {\n const nextLineStart = textDocument.offsetAt({\n line: line + 1,\n character: 0,\n });\n return { start: lineStart, end: nextLineStart, text: '' };\n }\n\n if (line > 0) {\n const previousLineEnd = textDocument.offsetAt({\n line: line - 1,\n character: textDocument.getLineLength(line - 1),\n });\n return { start: previousLineEnd, end: lineEnd, text: '' };\n }\n\n return { start: lineStart, end: lineEnd, text: '' };\n}\n\nfunction mergeCutEdits(orderedCuts: SelectionCut[]): ResolvedTextEdit[] {\n const edits: ResolvedTextEdit[] = [];\n for (const { edit } of orderedCuts) {\n if (edit.start >= edit.end) {\n continue;\n }\n const last = edits.at(-1);\n if (last !== undefined && edit.start <= last.end) {\n edits[edits.length - 1] = {\n start: last.start,\n end: Math.max(last.end, edit.end),\n text: '',\n };\n } else {\n edits.push(edit);\n }\n }\n return edits;\n}\n\nfunction mapCutSelectionOffsets(\n orderedCuts: SelectionCut[],\n edits: ResolvedTextEdit[]\n): number[] {\n const nextOffsets: number[] = Array.from({ length: orderedCuts.length });\n let editIndex = 0;\n let offsetDelta = 0;\n for (const cut of orderedCuts) {\n while (editIndex < edits.length && cut.edit.start > edits[editIndex].end) {\n const edit = edits[editIndex];\n offsetDelta -= edit.end - edit.start;\n editIndex++;\n }\n\n const edit = edits[editIndex];\n if (\n edit !== undefined &&\n cut.edit.start >= edit.start &&\n cut.edit.start <= edit.end\n ) {\n nextOffsets[cut.index] = edit.start + offsetDelta;\n } else {\n nextOffsets[cut.index] = cut.edit.start + offsetDelta;\n }\n }\n return nextOffsets;\n}\n\n// Resolves the clipboard text, merged deletions, and resulting caret offsets\n// for a cut. The clipboard text comes from the shared getSelectionText helper\n// so cut stays in sync with copy, while the deletions are computed per\n// selection and merged so overlapping cuts delete their shared text once.\nexport function resolveSelectionCut(\n textDocument: TextDocument,\n selections: EditorSelection[]\n): {\n text: string;\n edits: ResolvedTextEdit[];\n nextSelectionOffsets: number[];\n} {\n const cuts = selections.map<SelectionCut>((selection, index) => ({\n index,\n edit: resolveSelectionCutEdit(textDocument, selection),\n }));\n const orderedCuts = [...cuts].sort((a, b) => {\n const startOrder = a.edit.start - b.edit.start;\n if (startOrder !== 0) {\n return startOrder;\n }\n const endOrder = a.edit.end - b.edit.end;\n if (endOrder !== 0) {\n return endOrder;\n }\n return a.index - b.index;\n });\n const edits = mergeCutEdits(orderedCuts);\n return {\n text: getSelectionText(textDocument, selections),\n edits,\n nextSelectionOffsets: mapCutSelectionOffsets(orderedCuts, edits),\n };\n}\n\n/**\n * Get the anchor node and offset for a selection.\n */\nexport function getSelectionAnchor(\n lineElement: HTMLElement,\n character: number\n): [Node, number] {\n const ch = Math.max(0, character);\n const tokens = collectTokens(lineElement);\n\n let last: HTMLElement | null = null;\n for (const token of tokens) {\n last = token;\n const base = getCharacterIndex(token)!;\n const end = base + (token.textContent?.length ?? 0);\n if (ch <= end) {\n const anchor = textAt(token, ch < base ? 0 : ch - base);\n if (anchor !== null) {\n return anchor;\n }\n }\n }\n\n if (last !== null) {\n const anchor = textAt(last, last.textContent?.length ?? 0);\n if (anchor !== null) {\n return anchor;\n }\n return [last, 0];\n }\n\n let textOffset = 0;\n let lastTextNode: Text | null = null;\n for (const child of lineElement.childNodes) {\n if (child.nodeType === 1 && (child as HTMLElement).tagName === 'BR') {\n return [child, 0];\n }\n if (child.nodeType !== 3) {\n continue;\n }\n lastTextNode = child as Text;\n const len = getTextOffset(\n lastTextNode.textContent,\n lastTextNode.textContent?.length ?? 0\n );\n if (ch <= textOffset + len) {\n return [\n lastTextNode,\n getTextOffset(lastTextNode.textContent, ch - textOffset),\n ];\n }\n textOffset += len;\n }\n\n if (lastTextNode !== null) {\n return [\n lastTextNode,\n getTextOffset(\n lastTextNode.textContent,\n lastTextNode.textContent?.length ?? 0\n ),\n ];\n }\n return [lineElement, 0];\n}\n\n/**\n * Expands a zero-width selection to the word-like segment that contains the caret.\n */\nexport function expandCollapsedSelectionToWord(\n textDocument: TextDocument,\n selection: EditorSelection\n): EditorSelection {\n const { line, character } = selection.start;\n const lineText = textDocument.getLineText(line);\n const ch = Math.max(0, Math.min(character, lineText.length));\n const span = expandCollapsedLineWord(lineText, ch);\n if (span === undefined) {\n return selection;\n }\n return {\n start: { line, character: span.start },\n end: { line, character: span.end },\n direction: DirectionForward,\n };\n}\n\nfunction expandCollapsedLineWord(\n lineText: string,\n character: number\n): { start: number; end: number } | undefined {\n const segmenter = createSegmenter({ granularity: 'word' });\n if (segmenter !== undefined) {\n for (const seg of segmenter.segment(lineText)) {\n if (seg.isWordLike !== true) {\n continue;\n }\n const lo = seg.index;\n const hi = lo + seg.segment.length;\n // Match when the cursor is inside the word or immediately touching\n // one of its boundaries — not when separated by non-word characters.\n if (character >= lo && character <= hi) {\n return { start: lo, end: hi };\n }\n }\n return undefined;\n }\n // Degraded path for engines lacking Intl.Segmenter: treat runs of\n // alphanumeric/underscore characters as words.\n const wordRe = /[\\p{Alphabetic}\\p{Number}_]+/gu;\n let match: RegExpExecArray | null;\n while ((match = wordRe.exec(lineText)) !== null) {\n const lo = match.index;\n const hi = lo + match[0].length;\n if (character >= lo && character <= hi) {\n return { start: lo, end: hi };\n }\n }\n return undefined;\n}\n\n// Resolves the range removed by deleteWordBackward for one selection.\nfunction resolveDeleteWordBackwardRange(\n textDocument: TextDocument,\n selection: EditorSelection\n): [start: Position, end: Position] {\n if (!isCollapsedSelection(selection)) {\n return [selection.start, selection.end];\n }\n const caret = getCaretPosition(selection);\n const { line, character: head } = caret;\n if (head === 0) {\n if (line === 0) {\n return [caret, caret];\n }\n const prevLineLength = textDocument.getLineLength(line - 1);\n return [\n { line: line - 1, character: prevLineLength },\n { line, character: 0 },\n ];\n }\n const lineText = textDocument.getLineText(line);\n const graphemeStarts = getLineGraphemeStarts(lineText);\n let pos = head;\n let match: number | undefined;\n while (pos > 0) {\n const prev = findClusterBreak(lineText, pos, false, graphemeStarts);\n const nextMatch = getWordCharKind(lineText.slice(prev, pos));\n if (match !== undefined && nextMatch !== match) {\n break;\n }\n if (nextMatch !== 0 || pos !== head) {\n match = nextMatch;\n }\n pos = prev;\n }\n return [\n { line, character: pos },\n { line, character: head },\n ];\n}\n\n// Groups text for word motion and deletion: 0 is whitespace, 1 is word\n// characters, 2 is punctuation and symbols.\nfunction getWordCharKind(text: string): 0 | 1 | 2 {\n return !/\\S/.test(text)\n ? 0\n : /\\p{Alphabetic}|\\p{Number}|_/u.test(text)\n ? 1\n : 2;\n}\n\n// Finds where Ctrl+Arrow word motion stops on one line: past any whitespace,\n// then past one run of word characters or one run of punctuation. Steps by\n// whole graphemes so the caret never lands inside an emoji, and only visits\n// the graphemes it crosses, so long lines stay cheap.\nfunction findWordBoundary(\n lineText: string,\n character: number,\n forward: boolean\n): number {\n const segments = getGraphemeSegmenter()?.segment(lineText);\n let pos = character;\n let kind = 0;\n while (forward ? pos < lineText.length : pos > 0) {\n let text: string;\n let next: number;\n const segment = segments?.containing(forward ? pos : pos - 1);\n if (segment !== undefined) {\n text = segment.segment;\n next = forward ? segment.index + text.length : segment.index;\n } else {\n // Degraded path for engines lacking Intl.Segmenter: step by code point.\n const start = forward\n ? pos\n : (lineText.codePointAt(pos - 2) ?? 0) > 0xffff\n ? pos - 2\n : pos - 1;\n text = String.fromCodePoint(lineText.codePointAt(start) ?? 0);\n next = forward ? pos + text.length : start;\n }\n const nextKind = getWordCharKind(text);\n if (kind !== 0 && nextKind !== kind) {\n break;\n }\n kind = nextKind;\n pos = next;\n }\n return pos;\n}\n\nfunction findClusterBreak(\n text: string,\n pos: number,\n forward: boolean,\n graphemeStarts: number[]\n): number {\n if (forward) {\n for (const start of graphemeStarts) {\n if (start > pos) {\n return start;\n }\n }\n return text.length;\n }\n for (let i = graphemeStarts.length - 1; i >= 0; i--) {\n const start = graphemeStarts[i];\n if (start < pos) {\n return start;\n }\n }\n return 0;\n}\n\n// Lists the start column of every grapheme cluster on a line (always starting\n// at 0). Used to step the caret and to transpose by whole graphemes so a\n// surrogate pair (emoji) or combining sequence is never split.\nfunction getLineGraphemeStarts(lineText: string): number[] {\n const graphemeStarts = [0];\n const segmenter = getGraphemeSegmenter();\n if (segmenter !== undefined) {\n for (const segment of segmenter.segment(lineText)) {\n if (segment.index > 0) {\n graphemeStarts.push(segment.index);\n }\n }\n return graphemeStarts;\n }\n // Degraded path for engines lacking Intl.Segmenter: step by code point\n // (keeps surrogate pairs intact, but not combining sequences).\n let index = 0;\n for (const codePoint of lineText) {\n if (index > 0) {\n graphemeStarts.push(index);\n }\n index += codePoint.length;\n }\n return graphemeStarts;\n}\n\n// Returns the character column one grapheme cluster to the left or right of\n// `character` on `line`. Stepping by grapheme rather than by a single UTF-16\n// code unit keeps the caret from landing inside an emoji or other multi-unit\n// character. Crossing a line boundary is left to the caller.\nfunction stepCharacterByGrapheme(\n textDocument: TextDocument,\n line: number,\n character: number,\n forward: boolean\n): number {\n const lineLength = textDocument.getLineLength(line);\n if (forward) {\n if (character >= lineLength) {\n return lineLength;\n }\n const lineStart = textDocument.offsetAt({ line, character: 0 });\n const suffix = textDocument.getTextSlice(\n lineStart + character,\n lineStart + lineLength\n );\n const segmenter = getGraphemeSegmenter();\n if (segmenter !== undefined) {\n for (const segment of segmenter.segment(suffix)) {\n return character + segment.segment.length;\n }\n return lineLength;\n }\n // Degraded path for engines lacking Intl.Segmenter: step one code point.\n for (const codePoint of suffix) {\n return character + codePoint.length;\n }\n return lineLength;\n }\n if (character <= 0) {\n return 0;\n }\n const lineStart = textDocument.offsetAt({ line, character: 0 });\n const prefix = textDocument.getTextSlice(lineStart, lineStart + character);\n let prevStart = 0;\n const segmenter = getGraphemeSegmenter();\n if (segmenter !== undefined) {\n for (const segment of segmenter.segment(prefix)) {\n prevStart = segment.index;\n }\n return prevStart;\n }\n // Degraded path for engines lacking Intl.Segmenter: step one code point.\n let index = 0;\n for (const codePoint of prefix) {\n prevStart = index;\n index += codePoint.length;\n }\n return prevStart;\n}\n\nfunction getSelectionAnchorAndFocusOffsets(\n textDocument: TextDocument,\n selection: EditorSelection\n): [anchorOffset: number, focusOffset: number] {\n const isBackward = selection.direction === DirectionBackward;\n return [\n textDocument.offsetAt(isBackward ? selection.end : selection.start),\n textDocument.offsetAt(getCaretPosition(selection)),\n ];\n}\n\n// Resolves the range removed by deleteHardLineForward for one selection.\nfunction resolveDeleteHardLineForwardRange(\n textDocument: TextDocument,\n selection: EditorSelection\n): Range {\n if (!isCollapsedSelection(selection)) {\n return { start: selection.start, end: selection.end };\n }\n const { line, character } = selection.start;\n const lineText = textDocument.getLineText(line);\n const lineLength = lineText.length;\n if (character < lineLength) {\n return {\n start: { line, character },\n end: { line, character: lineLength },\n };\n }\n if (line < textDocument.lineCount - 1) {\n return {\n start: { line, character },\n end: { line: line + 1, character: 0 },\n };\n }\n return {\n start: { line, character },\n end: { line, character },\n };\n}\n\n// When the user inserts a lone line break, copy the current line's indentation onto the new line.\nfunction expandSingleNewlineInsert(\n textDocument: TextDocument,\n insertText: string,\n insertStartOffset: number\n): string {\n if (insertText !== '\\n' && insertText !== '\\r' && insertText !== '\\r\\n') {\n return insertText;\n }\n const line = textDocument.positionAt(insertStartOffset).line;\n const lineText = textDocument.getLineText(line);\n const indentLen = getLeadingSpaces(lineText);\n if (indentLen === 0) {\n return insertText;\n }\n return insertText + lineText.slice(0, indentLen);\n}\n\nfunction getLeadingSpaces(text: string): number {\n let indent = 0;\n for (; indent < text.length; indent++) {\n const c = text.charCodeAt(indent);\n if (c !== /* space */ 32 && c !== /* tab */ 9) {\n break;\n }\n }\n return indent;\n}\n\nfunction createSelectionsFromOffsetPairs(\n textDocument: TextDocument,\n offsetPairs: readonly [anchorOffset: number, focusOffset: number][]\n): EditorSelection[] {\n const normalizedOffsets: number[] = [];\n for (const [anchorOffset, focusOffset] of offsetPairs) {\n normalizedOffsets.push(\n Math.min(anchorOffset, focusOffset),\n Math.max(anchorOffset, focusOffset)\n );\n }\n const positions = textDocument.positionsAt(normalizedOffsets);\n return offsetPairs.map(([anchorOffset, focusOffset], index) => {\n const direction =\n anchorOffset === focusOffset\n ? DirectionNone\n : anchorOffset < focusOffset\n ? DirectionForward\n : DirectionBackward;\n return {\n start: positions[index * 2],\n end: positions[index * 2 + 1],\n direction,\n };\n });\n}\n\n// Expands a backspace over leading spaces into one soft-tab width so mixed hard/soft indentation\n// behaves like the explicit outdent command.\nfunction normalizeLeadingIndentForChange(\n textDocument: TextDocument,\n change: ResolvedTextEdit,\n tabSize: number\n): ResolvedTextEdit {\n if (change.text !== '' || change.start !== change.end - 1) {\n return change;\n }\n const caretPosition = textDocument.positionAt(change.end);\n if (caretPosition.character === 0) {\n return change;\n }\n const lineText = textDocument.getLineText(caretPosition.line);\n const leadingText = lineText.slice(0, caretPosition.character);\n if (/[^ \\t]/.test(leadingText)) {\n return change;\n }\n if (lineText[caretPosition.character - 1] === '\\t') {\n return change;\n }\n const softTabStart = Math.max(0, caretPosition.character - tabSize);\n const softTabText = lineText.slice(softTabStart, caretPosition.character);\n if (softTabText.length === tabSize && /^ +$/.test(softTabText)) {\n return {\n ...change,\n start: change.end - softTabText.length,\n };\n }\n return change;\n}\n\nfunction boundaryToPosition(node: Node, offset: number): Position | null {\n const host = node.nodeType === 1 ? (node as HTMLElement) : node.parentElement;\n let lineEl: HTMLElement | null = host;\n while (lineEl !== null && getLineIndex(lineEl) === undefined) {\n lineEl = lineEl.parentElement;\n }\n if (lineEl === null) {\n return null;\n }\n const line = getLineIndex(lineEl);\n if (line === undefined) {\n return null;\n }\n\n if (node.nodeType === 3) {\n if (node.parentElement === null) {\n return null;\n }\n if (findTokenSpan(node.parentElement) !== null) {\n return { line, character: getLineChildEnd(node, offset) };\n }\n return {\n line,\n character:\n offsetBefore(lineEl, node) + getTextOffset(node.textContent, offset),\n };\n }\n\n if (node.nodeType === 1) {\n const el = node as HTMLElement;\n if (el.tagName === 'DIV') {\n let character = 0;\n for (let i = 0; i < offset; i++) {\n character = getLineChildEnd(el.childNodes[i]);\n }\n return { line, character };\n }\n if (el.tagName === 'BR') {\n return { line, character: 0 };\n }\n if (el.tagName === 'SPAN') {\n if (offset < el.childNodes.length) {\n const next = el.childNodes[offset];\n if (next?.nodeType === 1) {\n const nextBase = getCharacterIndex(next as HTMLElement);\n if (nextBase !== undefined) {\n return { line, character: nextBase };\n }\n const token = findTokenSpan(next as HTMLElement);\n const tokenBase =\n token === null ? undefined : getCharacterIndex(token);\n if (tokenBase !== undefined) {\n return { line, character: tokenBase };\n }\n }\n }\n return {\n line,\n character:\n offset > 0\n ? getLineChildEnd(el.childNodes[offset - 1])\n : offsetBefore(lineEl, el),\n };\n }\n return { line, character: offsetBefore(lineEl, el) };\n }\n return null;\n}\n\nfunction collectTokens(line: HTMLElement): HTMLElement[] {\n const tokens: HTMLElement[] = [];\n for (const child of line.childNodes) {\n if (child.nodeType !== 1) {\n continue;\n }\n const el = child as HTMLElement;\n if (el.tagName !== 'SPAN') {\n continue;\n }\n const base = getCharacterIndex(el);\n if (base !== undefined) {\n tokens.push(el);\n continue;\n }\n for (const nested of el.childNodes) {\n if (\n nested.nodeType === 1 &&\n getCharacterIndex(nested as HTMLElement) !== undefined\n ) {\n tokens.push(nested as HTMLElement);\n }\n }\n }\n return tokens;\n}\n\nfunction textAt(token: HTMLElement, offset: number): [Node, number] | null {\n let remaining = Math.max(0, offset);\n const stack: Array<{ container: Node; index: number }> = [\n { container: token, index: 0 },\n ];\n while (stack.length > 0) {\n const frame = stack[stack.length - 1];\n if (frame.index >= frame.container.childNodes.length) {\n stack.pop();\n continue;\n }\n const walkNode = frame.container.childNodes[frame.index];\n frame.index++;\n if (walkNode.nodeType === 3) {\n const len = getTextOffset(\n walkNode.textContent,\n walkNode.textContent?.length ?? 0\n );\n if (remaining <= len) {\n return [walkNode, remaining];\n }\n remaining -= len;\n } else if (walkNode.nodeType === 1) {\n stack.push({ container: walkNode, index: 0 });\n }\n }\n return null;\n}\n\nfunction textLengthBefore(root: Node, target: Node): number {\n let before = 0;\n const stack: Array<{ container: Node; index: number }> = [\n { container: root, index: 0 },\n ];\n while (stack.length > 0) {\n const frame = stack[stack.length - 1];\n if (frame.index >= frame.container.childNodes.length) {\n stack.pop();\n continue;\n }\n const walkNode = frame.container.childNodes[frame.index];\n if (walkNode === target) {\n return before;\n }\n frame.index++;\n if (walkNode.nodeType === 3) {\n before += getTextOffset(\n walkNode.textContent,\n walkNode.textContent?.length ?? 0\n );\n } else if (walkNode.nodeType === 1) {\n stack.push({ container: walkNode, index: 0 });\n }\n }\n return before;\n}\n\nfunction isInside(token: HTMLElement, node: Node): boolean {\n let current: Node | null = node;\n while (current !== null) {\n if (current === token) {\n return true;\n }\n current = current.parentElement;\n }\n return false;\n}\n\nfunction offsetBefore(line: HTMLElement, node: Node): number {\n if (node.parentElement === line) {\n let offset = 0;\n const index = Array.prototype.indexOf.call(line.childNodes, node);\n for (let i = 0; i < index; i++) {\n offset = getLineChildEnd(line.childNodes[i]);\n }\n return offset;\n }\n for (const token of collectTokens(line)) {\n if (isInside(token, node)) {\n const base = getCharacterIndex(token)!;\n return base + (node.nodeType === 3 ? textLengthBefore(token, node) : 0);\n }\n }\n let offset = 0;\n let target: HTMLElement | null =\n node.nodeType === 1 ? (node as HTMLElement) : node.parentElement;\n while (target !== null && target.parentElement !== null) {\n if (getLineIndex(target.parentElement) !== undefined) {\n break;\n }\n const parent = target.parentElement;\n const index = Array.prototype.indexOf.call(parent.childNodes, target);\n for (let i = 0; i < index; i++) {\n offset = getLineChildEnd(parent.childNodes[i]);\n }\n target = parent;\n }\n return offset;\n}\n\nfunction findTokenSpan(el: HTMLElement): HTMLElement | null {\n let current: HTMLElement | null = el;\n while (current !== null) {\n if (getLineIndex(current) !== undefined) {\n return null;\n }\n if (getCharacterIndex(current) !== undefined) {\n return current;\n }\n current = current.parentElement;\n }\n return null;\n}\n\nfunction getLineChildEnd(\n child: Node | undefined,\n textOffsetInChild?: number\n): number {\n if (child === undefined) {\n return 0;\n }\n if (child.nodeType === 3) {\n const parent = child.parentElement;\n if (parent === null) {\n return 0;\n }\n const token = findTokenSpan(parent);\n if (token === null) {\n return 0;\n }\n const base = getCharacterIndex(token);\n if (base === undefined) {\n return 0;\n }\n const length =\n textOffsetInChild === undefined\n ? getTextOffset(child.textContent, child.textContent?.length ?? 0)\n : getTextOffset(child.textContent, textOffsetInChild);\n return base + textLengthBefore(token, child) + length;\n }\n if (child.nodeType !== 1) {\n return 0;\n }\n const el = child as HTMLElement;\n if (el.tagName !== 'SPAN' && el.tagName !== 'BR') {\n return 0;\n }\n const base = getCharacterIndex(el);\n if (base !== undefined) {\n return base + (el.textContent?.length ?? 0);\n }\n let end = 0;\n for (const token of el.childNodes) {\n end = Math.max(end, getLineChildEnd(token));\n }\n return end;\n}\n\nfunction getLineIndex(el: HTMLElement): number | undefined {\n const { line, lineType } = el.dataset;\n if (line !== undefined && lineType !== 'change-deletion') {\n const lineNumber = parseInt(line, 10);\n if (!Number.isNaN(lineNumber)) {\n return lineNumber - 1;\n }\n }\n return undefined;\n}\n\nfunction getCharacterIndex(el: HTMLElement): number | undefined {\n const { char } = el.dataset;\n if (char !== undefined) {\n const charIndex = parseInt(char, 10);\n if (!Number.isNaN(charIndex)) {\n return charIndex;\n }\n }\n return undefined;\n}\n\nfunction getTextOffset(\n text: string | null | undefined,\n offset: number\n): number {\n const value = text ?? '';\n const lineBreakIndex = value.search(/[\\r\\n]/);\n return Math.min(\n offset,\n lineBreakIndex === -1 ? value.length : lineBreakIndex\n );\n}\n"],"mappings":"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"}
|
|
@@ -17,11 +17,12 @@ declare function isHighlighterLoaded(): boolean;
|
|
|
17
17
|
interface GetHighlighterIfLoadedProps {
|
|
18
18
|
theme?: DiffsThemeNames | ThemesType;
|
|
19
19
|
lang?: SupportedLanguages;
|
|
20
|
+
langs?: SupportedLanguages[];
|
|
20
21
|
}
|
|
21
22
|
/**
|
|
22
23
|
* Returns undefined if the theme or language is not loaded.
|
|
23
24
|
*/
|
|
24
|
-
declare function getHighlighterIfLoaded({ theme, lang }?: GetHighlighterIfLoadedProps): DiffsHighlighter | undefined;
|
|
25
|
+
declare function getHighlighterIfLoaded({ theme, lang, langs }?: GetHighlighterIfLoadedProps): DiffsHighlighter | undefined;
|
|
25
26
|
declare function isHighlighterLoading(): boolean;
|
|
26
27
|
declare function isHighlighterNull(): boolean;
|
|
27
28
|
declare function preloadHighlighter(options: HighlighterOptions): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared_highlighter.d.ts","names":[],"sources":["../../src/highlighter/shared_highlighter.ts"],"mappings":";;;;UAyBiB;EACf,QAAQ;EACR,OAAO;EACP,uBAAuB;;;;;;iBAOH,kBACpB,OAAO,mBACN,QAAQ;iBAgBW,uBACpB,QACA,OACA,wBACC,qBAAqB,QAAQ;iBAwChB;UAKN;EACR,QAAQ,kBAAkB;EAC1B,OAAO;;;;;
|
|
1
|
+
{"version":3,"file":"shared_highlighter.d.ts","names":[],"sources":["../../src/highlighter/shared_highlighter.ts"],"mappings":";;;;UAyBiB;EACf,QAAQ;EACR,OAAO;EACP,uBAAuB;;;;;;iBAOH,kBACpB,OAAO,mBACN,QAAQ;iBAgBW,uBACpB,QACA,OACA,wBACC,qBAAqB,QAAQ;iBAwChB;UAKN;EACR,QAAQ,kBAAkB;EAC1B,OAAO;EACP,QAAQ;;;;;iBAMM,yBACd,OACA,MACA,UACC,8BAAmC;iBAkBtB;iBAIA;iBAKM,mBACpB,SAAS,qBACR;;;;;;iBASmB,sBAAsB"}
|
|
@@ -47,10 +47,10 @@ function isHighlighterLoaded() {
|
|
|
47
47
|
/**
|
|
48
48
|
* Returns undefined if the theme or language is not loaded.
|
|
49
49
|
*/
|
|
50
|
-
function getHighlighterIfLoaded({ theme, lang } = {}) {
|
|
50
|
+
function getHighlighterIfLoaded({ theme, lang, langs } = {}) {
|
|
51
51
|
dropDisposedHighlighter();
|
|
52
52
|
const instance = highlighter;
|
|
53
|
-
if (instance == null || "then" in instance || theme != null && !areThemesAttached(theme, instance) || lang != null && !instance.hasLoadedLanguages([lang])) return;
|
|
53
|
+
if (instance == null || "then" in instance || theme != null && !areThemesAttached(theme, instance) || (lang != null || langs != null) && !instance.hasLoadedLanguages([...lang != null ? [lang] : [], ...langs ?? []])) return;
|
|
54
54
|
return instance;
|
|
55
55
|
}
|
|
56
56
|
function isHighlighterLoading() {
|