@pierre/diffs 1.3.0-beta.8 → 1.3.0-rc.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.
Files changed (229) hide show
  1. package/dist/components/CodeView.d.ts +12 -12
  2. package/dist/components/CodeView.d.ts.map +1 -1
  3. package/dist/components/CodeView.js +51 -43
  4. package/dist/components/CodeView.js.map +1 -1
  5. package/dist/components/File.d.ts +7 -2
  6. package/dist/components/File.d.ts.map +1 -1
  7. package/dist/components/File.js +36 -8
  8. package/dist/components/File.js.map +1 -1
  9. package/dist/components/FileDiff.d.ts +34 -6
  10. package/dist/components/FileDiff.d.ts.map +1 -1
  11. package/dist/components/FileDiff.js +198 -17
  12. package/dist/components/FileDiff.js.map +1 -1
  13. package/dist/components/FileStream.d.ts.map +1 -1
  14. package/dist/components/FileStream.js +2 -1
  15. package/dist/components/FileStream.js.map +1 -1
  16. package/dist/components/VirtualizedFile.d.ts +2 -1
  17. package/dist/components/VirtualizedFile.d.ts.map +1 -1
  18. package/dist/components/VirtualizedFile.js +9 -5
  19. package/dist/components/VirtualizedFile.js.map +1 -1
  20. package/dist/components/VirtualizedFileDiff.d.ts +14 -0
  21. package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
  22. package/dist/components/VirtualizedFileDiff.js +61 -3
  23. package/dist/components/VirtualizedFileDiff.js.map +1 -1
  24. package/dist/components/Virtualizer.d.ts +14 -2
  25. package/dist/components/Virtualizer.d.ts.map +1 -1
  26. package/dist/components/Virtualizer.js +29 -3
  27. package/dist/components/Virtualizer.js.map +1 -1
  28. package/dist/edit/index.d.ts +5 -0
  29. package/dist/edit/index.js +3 -0
  30. package/dist/editor/command.d.ts +1 -1
  31. package/dist/editor/command.d.ts.map +1 -1
  32. package/dist/editor/command.js +11 -0
  33. package/dist/editor/command.js.map +1 -1
  34. package/dist/editor/editStack.d.ts +6 -2
  35. package/dist/editor/editStack.d.ts.map +1 -1
  36. package/dist/editor/editStack.js +54 -13
  37. package/dist/editor/editStack.js.map +1 -1
  38. package/dist/editor/editor.d.ts +51 -23
  39. package/dist/editor/editor.d.ts.map +1 -1
  40. package/dist/editor/editor.js +995 -242
  41. package/dist/editor/editor.js.map +1 -1
  42. package/dist/editor/editor2.js +1 -1
  43. package/dist/editor/languages.d.ts +26 -0
  44. package/dist/editor/languages.d.ts.map +1 -0
  45. package/dist/editor/languages.js +363 -0
  46. package/dist/editor/languages.js.map +1 -0
  47. package/dist/editor/lineAnnotations.d.ts.map +1 -1
  48. package/dist/editor/lineAnnotations.js +25 -26
  49. package/dist/editor/lineAnnotations.js.map +1 -1
  50. package/dist/editor/marker.d.ts +5 -3
  51. package/dist/editor/marker.d.ts.map +1 -1
  52. package/dist/editor/marker.js +111 -91
  53. package/dist/editor/marker.js.map +1 -1
  54. package/dist/editor/matchBrackets.d.ts +3 -2
  55. package/dist/editor/matchBrackets.d.ts.map +1 -1
  56. package/dist/editor/matchBrackets.js +2 -10
  57. package/dist/editor/matchBrackets.js.map +1 -1
  58. package/dist/editor/pieceTable.d.ts +2 -1
  59. package/dist/editor/pieceTable.d.ts.map +1 -1
  60. package/dist/editor/pieceTable.js +103 -39
  61. package/dist/editor/pieceTable.js.map +1 -1
  62. package/dist/editor/platform.js +2 -0
  63. package/dist/editor/platform.js.map +1 -1
  64. package/dist/editor/popover.d.ts +25 -5
  65. package/dist/editor/popover.d.ts.map +1 -1
  66. package/dist/editor/popover.js +60 -14
  67. package/dist/editor/popover.js.map +1 -1
  68. package/dist/editor/searchPanel.d.ts +1 -0
  69. package/dist/editor/searchPanel.d.ts.map +1 -1
  70. package/dist/editor/searchPanel.js +15 -8
  71. package/dist/editor/searchPanel.js.map +1 -1
  72. package/dist/editor/selection.d.ts +31 -11
  73. package/dist/editor/selection.d.ts.map +1 -1
  74. package/dist/editor/selection.js +198 -70
  75. package/dist/editor/selection.js.map +1 -1
  76. package/dist/editor/selectionAction.d.ts +4 -3
  77. package/dist/editor/selectionAction.d.ts.map +1 -1
  78. package/dist/editor/selectionAction.js +9 -5
  79. package/dist/editor/selectionAction.js.map +1 -1
  80. package/dist/editor/stateStorage.d.ts +15 -0
  81. package/dist/editor/stateStorage.d.ts.map +1 -0
  82. package/dist/editor/stateStorage.js +65 -0
  83. package/dist/editor/stateStorage.js.map +1 -0
  84. package/dist/editor/textDocument.d.ts +12 -77
  85. package/dist/editor/textDocument.d.ts.map +1 -1
  86. package/dist/editor/textDocument.js +76 -34
  87. package/dist/editor/textDocument.js.map +1 -1
  88. package/dist/editor/textMeasure.d.ts +7 -12
  89. package/dist/editor/textMeasure.d.ts.map +1 -1
  90. package/dist/editor/textMeasure.js +40 -32
  91. package/dist/editor/textMeasure.js.map +1 -1
  92. package/dist/editor/{tokenzier.d.ts → tokenizer.d.ts} +3 -3
  93. package/dist/editor/tokenizer.d.ts.map +1 -0
  94. package/dist/editor/{tokenzier.js → tokenizer.js} +91 -26
  95. package/dist/editor/tokenizer.js.map +1 -0
  96. package/dist/editor/utils.js +1 -1
  97. package/dist/editor/utils.js.map +1 -1
  98. package/dist/index.d.ts +5 -4
  99. package/dist/index.js +7 -6
  100. package/dist/managers/InteractionManager.d.ts +18 -7
  101. package/dist/managers/InteractionManager.d.ts.map +1 -1
  102. package/dist/managers/InteractionManager.js +154 -99
  103. package/dist/managers/InteractionManager.js.map +1 -1
  104. package/dist/managers/UniversalRenderingManager.d.ts +2 -1
  105. package/dist/managers/UniversalRenderingManager.d.ts.map +1 -1
  106. package/dist/managers/UniversalRenderingManager.js +7 -3
  107. package/dist/managers/UniversalRenderingManager.js.map +1 -1
  108. package/dist/react/CodeView.d.ts +13 -13
  109. package/dist/react/CodeView.d.ts.map +1 -1
  110. package/dist/react/CodeView.js +38 -29
  111. package/dist/react/CodeView.js.map +1 -1
  112. package/dist/react/EditContext.d.ts +20 -0
  113. package/dist/react/EditContext.d.ts.map +1 -0
  114. package/dist/react/EditContext.js +20 -0
  115. package/dist/react/EditContext.js.map +1 -0
  116. package/dist/react/File.d.ts +2 -1
  117. package/dist/react/File.d.ts.map +1 -1
  118. package/dist/react/File.js +3 -2
  119. package/dist/react/File.js.map +1 -1
  120. package/dist/react/FileDiff.d.ts +2 -2
  121. package/dist/react/FileDiff.d.ts.map +1 -1
  122. package/dist/react/FileDiff.js +3 -2
  123. package/dist/react/FileDiff.js.map +1 -1
  124. package/dist/react/MultiFileDiff.d.ts +2 -2
  125. package/dist/react/MultiFileDiff.d.ts.map +1 -1
  126. package/dist/react/MultiFileDiff.js +3 -2
  127. package/dist/react/MultiFileDiff.js.map +1 -1
  128. package/dist/react/PatchDiff.d.ts +2 -2
  129. package/dist/react/PatchDiff.d.ts.map +1 -1
  130. package/dist/react/PatchDiff.js +3 -2
  131. package/dist/react/PatchDiff.js.map +1 -1
  132. package/dist/react/UnresolvedFile.d.ts +1 -1
  133. package/dist/react/UnresolvedFile.js.map +1 -1
  134. package/dist/react/index.d.ts +4 -4
  135. package/dist/react/index.js +3 -3
  136. package/dist/react/types.d.ts +9 -1
  137. package/dist/react/types.d.ts.map +1 -1
  138. package/dist/react/utils/useFileDiffInstance.d.ts +5 -3
  139. package/dist/react/utils/useFileDiffInstance.d.ts.map +1 -1
  140. package/dist/react/utils/useFileDiffInstance.js +28 -27
  141. package/dist/react/utils/useFileDiffInstance.js.map +1 -1
  142. package/dist/react/utils/useFileInstance.d.ts +5 -3
  143. package/dist/react/utils/useFileInstance.d.ts.map +1 -1
  144. package/dist/react/utils/useFileInstance.js +29 -25
  145. package/dist/react/utils/useFileInstance.js.map +1 -1
  146. package/dist/react/utils/useUnresolvedFileInstance.js +3 -3
  147. package/dist/react/utils/useUnresolvedFileInstance.js.map +1 -1
  148. package/dist/renderers/DiffHunksRenderer.d.ts +33 -1
  149. package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
  150. package/dist/renderers/DiffHunksRenderer.js +134 -21
  151. package/dist/renderers/DiffHunksRenderer.js.map +1 -1
  152. package/dist/renderers/FileRenderer.d.ts +2 -0
  153. package/dist/renderers/FileRenderer.d.ts.map +1 -1
  154. package/dist/renderers/FileRenderer.js +33 -11
  155. package/dist/renderers/FileRenderer.js.map +1 -1
  156. package/dist/ssr/FileDiffReact.js +1 -1
  157. package/dist/ssr/index.d.ts +2 -2
  158. package/dist/ssr/preloadDiffs.js +1 -1
  159. package/dist/style.js +1 -1
  160. package/dist/types.d.ts +185 -42
  161. package/dist/types.d.ts.map +1 -1
  162. package/dist/utils/annotationHelpers.d.ts +20 -0
  163. package/dist/utils/annotationHelpers.d.ts.map +1 -0
  164. package/dist/utils/annotationHelpers.js +29 -0
  165. package/dist/utils/annotationHelpers.js.map +1 -0
  166. package/dist/utils/computeFileOffsets.d.ts.map +1 -1
  167. package/dist/utils/computeFileOffsets.js +34 -5
  168. package/dist/utils/computeFileOffsets.js.map +1 -1
  169. package/dist/utils/editSessionHunks.d.ts +66 -0
  170. package/dist/utils/editSessionHunks.d.ts.map +1 -0
  171. package/dist/utils/editSessionHunks.js +437 -0
  172. package/dist/utils/editSessionHunks.js.map +1 -0
  173. package/dist/utils/getHunkSideBoundaries.d.ts +7 -0
  174. package/dist/utils/getHunkSideBoundaries.d.ts.map +1 -0
  175. package/dist/utils/getHunkSideBoundaries.js +12 -0
  176. package/dist/utils/getHunkSideBoundaries.js.map +1 -0
  177. package/dist/utils/getTotalLineCountFromHunks.d.ts.map +1 -1
  178. package/dist/utils/getTotalLineCountFromHunks.js +2 -1
  179. package/dist/utils/getTotalLineCountFromHunks.js.map +1 -1
  180. package/dist/utils/hydratePartialDiff.d.ts.map +1 -1
  181. package/dist/utils/hydratePartialDiff.js +4 -3
  182. package/dist/utils/hydratePartialDiff.js.map +1 -1
  183. package/dist/utils/isGutterUtilityPath.d.ts +5 -0
  184. package/dist/utils/isGutterUtilityPath.d.ts.map +1 -0
  185. package/dist/utils/isGutterUtilityPath.js +12 -0
  186. package/dist/utils/isGutterUtilityPath.js.map +1 -0
  187. package/dist/utils/iterateOverDiff.d.ts.map +1 -1
  188. package/dist/utils/iterateOverDiff.js +17 -12
  189. package/dist/utils/iterateOverDiff.js.map +1 -1
  190. package/dist/utils/parseMergeConflictDiffFromFile.d.ts.map +1 -1
  191. package/dist/utils/parseMergeConflictDiffFromFile.js +9 -6
  192. package/dist/utils/parseMergeConflictDiffFromFile.js.map +1 -1
  193. package/dist/utils/parsePatchFiles.d.ts.map +1 -1
  194. package/dist/utils/parsePatchFiles.js +6 -3
  195. package/dist/utils/parsePatchFiles.js.map +1 -1
  196. package/dist/utils/realignChangeContent.d.ts +33 -0
  197. package/dist/utils/realignChangeContent.d.ts.map +1 -0
  198. package/dist/utils/realignChangeContent.js +148 -0
  199. package/dist/utils/realignChangeContent.js.map +1 -0
  200. package/dist/utils/renderDiffWithHighlighter.js +1 -1
  201. package/dist/utils/resolveRegion.d.ts.map +1 -1
  202. package/dist/utils/resolveRegion.js +18 -2
  203. package/dist/utils/resolveRegion.js.map +1 -1
  204. package/dist/utils/updateDiffHunks.d.ts +8 -2
  205. package/dist/utils/updateDiffHunks.d.ts.map +1 -1
  206. package/dist/utils/updateDiffHunks.js +9 -7
  207. package/dist/utils/updateDiffHunks.js.map +1 -1
  208. package/dist/utils/virtualDiffLayout.d.ts +42 -2
  209. package/dist/utils/virtualDiffLayout.d.ts.map +1 -1
  210. package/dist/utils/virtualDiffLayout.js +101 -7
  211. package/dist/utils/virtualDiffLayout.js.map +1 -1
  212. package/dist/worker/WorkerPoolManager.d.ts.map +1 -1
  213. package/dist/worker/WorkerPoolManager.js +4 -2
  214. package/dist/worker/WorkerPoolManager.js.map +1 -1
  215. package/dist/worker/types.d.ts +4 -0
  216. package/dist/worker/types.d.ts.map +1 -1
  217. package/dist/worker/worker-portable.js +60 -20
  218. package/dist/worker/worker-portable.js.map +1 -1
  219. package/dist/worker/worker.js +61 -19
  220. package/dist/worker/worker.js.map +1 -1
  221. package/package.json +13 -8
  222. package/dist/editor/index.d.ts +0 -3
  223. package/dist/editor/index.js +0 -3
  224. package/dist/editor/tokenzier.d.ts.map +0 -1
  225. package/dist/editor/tokenzier.js.map +0 -1
  226. package/dist/react/EditorContext.d.ts +0 -15
  227. package/dist/react/EditorContext.d.ts.map +0 -1
  228. package/dist/react/EditorContext.js +0 -23
  229. package/dist/react/EditorContext.js.map +0 -1
@@ -4,6 +4,26 @@ import { applyDocumentChangeToLineAnnotations } from "./lineAnnotations.js";
4
4
  const DirectionBackward = -1;
5
5
  const DirectionNone = 0;
6
6
  const DirectionForward = 1;
7
+ const AUTO_SURROUND_CLOSE_CHARS = /* @__PURE__ */ new Map([
8
+ ["'", "'"],
9
+ ["\"", "\""],
10
+ ["`", "`"],
11
+ ["{", "}"],
12
+ ["[", "]"],
13
+ ["<", ">"],
14
+ ["(", ")"]
15
+ ]);
16
+ const AUTO_SURROUND_QUOTE_CHARS = /* @__PURE__ */ new Set([
17
+ "'",
18
+ "\"",
19
+ "`"
20
+ ]);
21
+ const AUTO_SURROUND_BRACKET_CHARS = /* @__PURE__ */ new Set([
22
+ "{",
23
+ "[",
24
+ "(",
25
+ "<"
26
+ ]);
7
27
  /**
8
28
  * Converts a selection from a web selection to an editor selection.
9
29
  */
@@ -25,11 +45,13 @@ function resolveIndentEdits(textDocument, selection, tabSize, outdent) {
25
45
  const { start, end } = selection;
26
46
  const edits = [];
27
47
  let newSelection = { ...selection };
48
+ const blockIndent = start.line !== end.line;
28
49
  let endLine = end.line;
29
50
  if (start.line < end.line && end.character === 0) endLine--;
30
51
  for (let line = start.line; line <= endLine; line++) {
31
52
  const lineText = textDocument.getLineText(line);
32
53
  if (lineText === void 0) continue;
54
+ if (blockIndent && lineText.trim().length === 0) continue;
33
55
  const indentUnit = lineText.startsWith(" ") ? " " : " ".repeat(tabSize);
34
56
  let deleteLength = 0;
35
57
  let newText = indentUnit;
@@ -76,7 +98,7 @@ function resolveIndentEdits(textDocument, selection, tabSize, outdent) {
76
98
  /**
77
99
  * Maps the cursor move to all selections.
78
100
  */
79
- function mapCursorMove(textDocument, selections, shortcut) {
101
+ function mapCursorMove(textDocument, selections, shortcut, options = {}) {
80
102
  const lineCount = textDocument.lineCount;
81
103
  return selections.map((selection) => {
82
104
  let { line, character } = shortcut === "up" || shortcut === "left" ? selection.start : selection.end;
@@ -84,25 +106,46 @@ function mapCursorMove(textDocument, selections, shortcut) {
84
106
  const caret = getCaretPosition(selection);
85
107
  line = caret.line;
86
108
  character = caret.character;
109
+ const softLine = getSoftLineInfo(textDocument, line, character, options);
87
110
  if (shortcut === "textStart") {
88
- const indent = getLeadingSpaces(textDocument.getLineText(line));
89
- character = character === indent ? 0 : indent;
90
- } else character = shortcut === "start" ? 0 : textDocument.getLineLength(line);
91
- } else if (shortcut === "up") line = Math.max(0, line - 1);
92
- else if (shortcut === "down") line = Math.min(Math.max(lineCount - 1, 0), line + 1);
93
- else if (isCollapsedSelection(selection)) {
111
+ const softLineText = textDocument.getLineText(line).slice(softLine.start, softLine.end);
112
+ const indent = softLine.start + getLeadingSpaces(softLineText);
113
+ character = character === indent ? softLine.start : indent;
114
+ } else character = shortcut === "start" ? softLine.start : softLine.end;
115
+ } else if (shortcut === "up") {
116
+ const moved = moveBySoftLine(textDocument, line, character, -1, options);
117
+ if (moved !== void 0) {
118
+ line = moved.line;
119
+ character = moved.character;
120
+ } else if (line > 0) line = options.resolveRenderableLine == null ? line - 1 : options.resolveRenderableLine(line - 1, "up") ?? line;
121
+ } else if (shortcut === "down") {
122
+ const moved = moveBySoftLine(textDocument, line, character, 1, options);
123
+ if (moved !== void 0) {
124
+ line = moved.line;
125
+ character = moved.character;
126
+ } else {
127
+ const maxLine = Math.max(lineCount - 1, 0);
128
+ if (line < maxLine) line = options.resolveRenderableLine == null ? line + 1 : Math.min(options.resolveRenderableLine(line + 1, "down") ?? line, maxLine);
129
+ }
130
+ } else if (isCollapsedSelection(selection)) {
94
131
  const lineLength = textDocument.getLineLength(line);
95
132
  character = Math.min(character, lineLength);
96
133
  if (shortcut === "left") {
97
134
  if (character > 0) character = stepCharacterByGrapheme(textDocument, line, character, false);
98
135
  else if (line > 0) {
99
- line = line - 1;
100
- character = textDocument.getLineLength(line);
136
+ const targetLine = options.resolveRenderableLine == null ? line - 1 : options.resolveRenderableLine(line - 1, "up");
137
+ if (targetLine !== void 0) {
138
+ line = targetLine;
139
+ character = textDocument.getLineLength(line);
140
+ }
101
141
  }
102
142
  } else if (character < lineLength) character = stepCharacterByGrapheme(textDocument, line, character, true);
103
143
  else if (line < lineCount - 1) {
104
- line = line + 1;
105
- character = 0;
144
+ const targetLine = options.resolveRenderableLine == null ? line + 1 : options.resolveRenderableLine(line + 1, "down");
145
+ if (targetLine !== void 0) {
146
+ line = Math.min(targetLine, lineCount - 1);
147
+ character = 0;
148
+ }
106
149
  }
107
150
  }
108
151
  const pos = {
@@ -116,17 +159,106 @@ function mapCursorMove(textDocument, selections, shortcut) {
116
159
  };
117
160
  });
118
161
  }
162
+ function moveBySoftLine(textDocument, line, character, direction, options) {
163
+ if (options.getSoftLineOffsets === void 0) return;
164
+ const current = getSoftLineInfo(textDocument, line, character, options);
165
+ const targetIndex = current.index + direction;
166
+ let targetLine = line;
167
+ let target;
168
+ if (targetIndex >= 0 && targetIndex < current.count) target = getSoftLineInfoAtIndex(textDocument, targetLine, targetIndex, options);
169
+ else {
170
+ const nextLine = line + direction;
171
+ if (nextLine < 0 || nextLine >= textDocument.lineCount) return {
172
+ line,
173
+ character
174
+ };
175
+ const resolvedLine = options.resolveRenderableLine == null ? nextLine : options.resolveRenderableLine(nextLine, direction < 0 ? "up" : "down");
176
+ if (resolvedLine === void 0) return {
177
+ line,
178
+ character
179
+ };
180
+ targetLine = Math.min(resolvedLine, textDocument.lineCount - 1);
181
+ const targetCount = getSoftLineCount(textDocument, targetLine, options);
182
+ target = getSoftLineInfoAtIndex(textDocument, targetLine, direction < 0 ? targetCount - 1 : 0, options);
183
+ }
184
+ const column = Math.max(0, character - current.start);
185
+ const targetCharacter = target.start + column;
186
+ const landedCharacter = target.index === target.count - 1 ? targetCharacter : Math.min(targetCharacter, target.end);
187
+ const targetLineText = textDocument.getLineText(targetLine);
188
+ return {
189
+ line: targetLine,
190
+ character: landedCharacter > targetLineText.length ? landedCharacter : snapCharacterToGraphemeBoundary(targetLineText, landedCharacter)
191
+ };
192
+ }
193
+ function snapCharacterToGraphemeBoundary(lineText, character) {
194
+ if (character <= 0 || character >= lineText.length) return character;
195
+ const segmenter = getGraphemeSegmenter();
196
+ if (segmenter !== void 0) {
197
+ for (const segment of segmenter.segment(lineText)) {
198
+ if (character <= segment.index) return character;
199
+ const segmentEnd = segment.index + segment.segment.length;
200
+ if (character < segmentEnd) return segmentEnd;
201
+ }
202
+ return character;
203
+ }
204
+ let segmentStart = 0;
205
+ for (const codePoint of lineText) {
206
+ if (character <= segmentStart) return character;
207
+ const segmentEnd = segmentStart + codePoint.length;
208
+ if (character < segmentEnd) return segmentEnd;
209
+ segmentStart = segmentEnd;
210
+ }
211
+ return character;
212
+ }
213
+ function getSoftLineInfo(textDocument, line, character, options) {
214
+ const lineLength = textDocument.getLineLength(line);
215
+ const offsets = options.getSoftLineOffsets?.(line);
216
+ if (offsets === void 0 || offsets.length < 2) return {
217
+ start: 0,
218
+ end: lineLength,
219
+ index: 0,
220
+ count: 1
221
+ };
222
+ for (let index = 0; index + 1 < offsets.length; index++) {
223
+ const softLine = getSoftLineInfoAtIndex(textDocument, line, index, options);
224
+ if (character >= softLine.start && character <= softLine.end) return softLine;
225
+ }
226
+ return getSoftLineInfoAtIndex(textDocument, line, character < (offsets[0] ?? 0) ? 0 : offsets.length - 2, options);
227
+ }
228
+ function getSoftLineCount(textDocument, line, options) {
229
+ const offsets = options.getSoftLineOffsets?.(line);
230
+ return offsets === void 0 || offsets.length < 2 ? 1 : offsets.length - 1;
231
+ }
232
+ function getSoftLineInfoAtIndex(textDocument, line, index, options) {
233
+ const lineLength = textDocument.getLineLength(line);
234
+ const offsets = options.getSoftLineOffsets?.(line);
235
+ if (offsets === void 0 || offsets.length < 2) return {
236
+ start: 0,
237
+ end: lineLength,
238
+ index: 0,
239
+ count: 1
240
+ };
241
+ const count = offsets.length - 1;
242
+ const boundedIndex = Math.max(0, Math.min(index, count - 1));
243
+ const start = Math.max(0, Math.min(lineLength, offsets[boundedIndex] ?? 0));
244
+ return {
245
+ start,
246
+ end: Math.max(start, Math.min(lineLength, offsets[boundedIndex + 1] ?? lineLength)),
247
+ index: boundedIndex,
248
+ count
249
+ };
250
+ }
119
251
  /**
120
252
  * Same as mapCursorMove, but with shift key pressed.
121
253
  */
122
- function mapSelectionShift(textDocument, selections, shortcut) {
254
+ function mapSelectionShift(textDocument, selections, shortcut, options = {}) {
123
255
  return selections.map((selection) => {
124
256
  const focusPosition = selection.direction === -1 ? selection.start : selection.end;
125
257
  const [movedFocusSelection] = mapCursorMove(textDocument, [{
126
258
  start: focusPosition,
127
259
  end: focusPosition,
128
260
  direction: 0
129
- }], shortcut);
261
+ }], shortcut, options);
130
262
  return createSelectionFrom(selection, movedFocusSelection);
131
263
  });
132
264
  }
@@ -218,12 +350,18 @@ function applyTextChangeToSelections(textDocument, selections, edit, lineAnnotat
218
350
  * When the inserted text still contains the original selection (auto-surround),
219
351
  * the inner range is reselected to match VS Code/CodeMirror behavior.
220
352
  */
353
+ function getAutoSurroundPreservedOffset(originalText, newText) {
354
+ if (newText.length !== originalText.length + 2) return;
355
+ const closeChar = AUTO_SURROUND_CLOSE_CHARS.get(newText[0]);
356
+ if (closeChar === void 0 || newText[newText.length - 1] !== closeChar || newText.slice(1, -1) !== originalText) return;
357
+ return 1;
358
+ }
221
359
  function getNextSelectionOffsetPairAfterReplace(textDocument, entry, offsetDelta, newText) {
222
360
  const insertStart = entry.start + offsetDelta;
223
361
  const insertEnd = insertStart + newText.length;
224
362
  if (entry.end - entry.start > 0) {
225
363
  const originalText = textDocument.getTextSlice(entry.start, entry.end);
226
- const preservedOffset = newText.indexOf(originalText);
364
+ const preservedOffset = getAutoSurroundPreservedOffset(originalText, newText) ?? newText.indexOf(originalText);
227
365
  if (preservedOffset !== -1 && preservedOffset + originalText.length <= newText.length) {
228
366
  const rangeStart = insertStart + preservedOffset;
229
367
  return [rangeStart, rangeStart + originalText.length];
@@ -232,9 +370,10 @@ function getNextSelectionOffsetPairAfterReplace(textDocument, entry, offsetDelta
232
370
  return [insertEnd, insertEnd];
233
371
  }
234
372
  /**
235
- * Applies a text replace to multiple selections.
373
+ * Applies text replacements to multiple selections. Texts pair by selection
374
+ * index unless they are explicitly marked as document ordered.
236
375
  */
237
- function applyTextReplaceToSelections(textDocument, selections, texts, lineAnnotations, undoBoundary = false) {
376
+ function applyTextReplaceToSelections(textDocument, selections, texts, lineAnnotations, undoBoundary = false, textOrder = "selection") {
238
377
  if (selections.length !== texts.length) throw new Error("Selection text replacements must match the selection count");
239
378
  const selectionPositions = [];
240
379
  for (const selection of selections) selectionPositions.push(selection.start, selection.end);
@@ -245,8 +384,7 @@ function applyTextReplaceToSelections(textDocument, selections, texts, lineAnnot
245
384
  const entry = {
246
385
  index,
247
386
  start: selectionOffsets[index * 2],
248
- end: selectionOffsets[index * 2 + 1],
249
- text: texts[index]
387
+ end: selectionOffsets[index * 2 + 1]
250
388
  };
251
389
  const previous = ordered[ordered.length - 1];
252
390
  if (previous !== void 0 && (entry.start < previous.start || entry.start === previous.start && entry.end < previous.end)) isAlreadyOrdered = false;
@@ -302,10 +440,11 @@ function applyTextReplaceToSelections(textDocument, selections, texts, lineAnnot
302
440
  edits = [];
303
441
  let offsetDelta = 0;
304
442
  let previousEditEnd = -1;
305
- for (const entry of ordered) {
443
+ for (let index = 0; index < ordered.length; index++) {
444
+ const entry = ordered[index];
306
445
  if (entry.start < previousEditEnd) throw new Error("Overlapping multi-selection edits are not supported");
307
446
  previousEditEnd = entry.end;
308
- const newText = expandSingleNewlineInsert(textDocument, entry.text, entry.start);
447
+ const newText = expandSingleNewlineInsert(textDocument, texts[textOrder === "document" ? index : entry.index], entry.start);
309
448
  edits.push({
310
449
  start: entry.start,
311
450
  end: entry.end,
@@ -330,26 +469,6 @@ function applyTextReplaceToSelections(textDocument, selections, texts, lineAnnot
330
469
  change
331
470
  };
332
471
  }
333
- const AUTO_SURROUND_CLOSE_CHARS = /* @__PURE__ */ new Map([
334
- ["'", "'"],
335
- ["\"", "\""],
336
- ["`", "`"],
337
- ["{", "}"],
338
- ["[", "]"],
339
- ["<", ">"],
340
- ["(", ")"]
341
- ]);
342
- const AUTO_SURROUND_QUOTE_CHARS = /* @__PURE__ */ new Set([
343
- "'",
344
- "\"",
345
- "`"
346
- ]);
347
- const AUTO_SURROUND_BRACKET_CHARS = /* @__PURE__ */ new Set([
348
- "{",
349
- "[",
350
- "(",
351
- "<"
352
- ]);
353
472
  function shouldAutoSurroundChar(autoSurround, char) {
354
473
  if (autoSurround === "never") return false;
355
474
  if (autoSurround === "brackets") return AUTO_SURROUND_BRACKET_CHARS.has(char);
@@ -827,7 +946,7 @@ function shiftSelectionLines(selection, direction, lineCount, getLineLength) {
827
946
  /**
828
947
  * Finds the next matching word and updates the selections.
829
948
  */
830
- function findNexMatch(textDocument, selections) {
949
+ function findNextMatch(textDocument, selections) {
831
950
  if (selections.length === 0) return;
832
951
  const normalizedSelections = selections.map((selection) => isCollapsedSelection(selection) ? expandCollapsedSelectionToWord(textDocument, selection) : selection);
833
952
  const texts = normalizedSelections.map((s) => textDocument.getText(s));
@@ -879,6 +998,34 @@ function getDocumentBoundarySelection(textDocument, atEnd, trimmedEndNewLine) {
879
998
  direction: 1
880
999
  };
881
1000
  }
1001
+ /** Resolves the document offset range one selection contributes to a copy. */
1002
+ function resolveClipboardRegion(textDocument, selection) {
1003
+ if (isCollapsedSelection(selection)) {
1004
+ const line = selection.start.line;
1005
+ return {
1006
+ start: textDocument.offsetAt({
1007
+ line,
1008
+ character: 0
1009
+ }),
1010
+ end: line < textDocument.lineCount - 1 ? textDocument.offsetAt({
1011
+ line: line + 1,
1012
+ character: 0
1013
+ }) : textDocument.offsetAt({
1014
+ line,
1015
+ character: textDocument.getLineLength(line)
1016
+ })
1017
+ };
1018
+ }
1019
+ const start = textDocument.offsetAt(selection.start);
1020
+ const end = textDocument.offsetAt(selection.end);
1021
+ return start <= end ? {
1022
+ start,
1023
+ end
1024
+ } : {
1025
+ start: end,
1026
+ end: start
1027
+ };
1028
+ }
882
1029
  /**
883
1030
  * Resolves the document offset range each selection contributes to the
884
1031
  * clipboard, ordered by position. A collapsed selection contributes its whole
@@ -886,38 +1033,19 @@ function getDocumentBoundarySelection(textDocument, atEnd, trimmedEndNewLine) {
886
1033
  * trailing break to include. A ranged selection contributes the selected text.
887
1034
  */
888
1035
  function resolveClipboardRegions(textDocument, selections) {
889
- return selections.map((selection) => {
890
- if (isCollapsedSelection(selection)) {
891
- const line = selection.start.line;
892
- return {
893
- start: textDocument.offsetAt({
894
- line,
895
- character: 0
896
- }),
897
- end: line < textDocument.lineCount - 1 ? textDocument.offsetAt({
898
- line: line + 1,
899
- character: 0
900
- }) : textDocument.offsetAt({
901
- line,
902
- character: textDocument.getLineLength(line)
903
- })
904
- };
905
- }
906
- const start = textDocument.offsetAt(selection.start);
907
- const end = textDocument.offsetAt(selection.end);
908
- return start <= end ? {
909
- start,
910
- end
911
- } : {
912
- start: end,
913
- end: start
914
- };
915
- }).sort((a, b) => {
1036
+ return selections.map((selection) => resolveClipboardRegion(textDocument, selection)).sort((a, b) => {
916
1037
  const startOrder = a.start - b.start;
917
1038
  return startOrder !== 0 ? startOrder : a.end - b.end;
918
1039
  });
919
1040
  }
920
1041
  /**
1042
+ * Gets the text contributed by each selection in document order, preserving
1043
+ * the pairing needed to paste the values into another set of selections.
1044
+ */
1045
+ function getSelectionClipboardTexts(textDocument, selections) {
1046
+ return resolveClipboardRegions(textDocument, selections).map(({ start, end }) => textDocument.getTextSlice(start, end));
1047
+ }
1048
+ /**
921
1049
  * Get the clipboard text of the selections for the given text document. Used by
922
1050
  * both copy and cut so the two stay in sync. Overlapping regions (e.g. several
923
1051
  * carets on one line) are merged so the same text is never emitted twice, and a
@@ -1135,7 +1263,7 @@ function resolveDeleteWordBackwardRange(textDocument, selection) {
1135
1263
  const nextChar = lineText.slice(prev, pos);
1136
1264
  const nextMatch = !/\S/.test(nextChar) ? 0 : /\p{Alphabetic}|\p{Number}|_/u.test(nextChar) ? 1 : 2;
1137
1265
  if (match !== void 0 && nextMatch !== match) break;
1138
- if (nextChar !== " " || pos !== head) match = nextMatch;
1266
+ if (nextMatch !== 0 || pos !== head) match = nextMatch;
1139
1267
  pos = prev;
1140
1268
  }
1141
1269
  return [{
@@ -1493,6 +1621,6 @@ function getTextOffset(text, offset) {
1493
1621
  return Math.min(offset, lineBreakIndex === -1 ? value.length : lineBreakIndex);
1494
1622
  }
1495
1623
  //#endregion
1496
- export { DirectionBackward, DirectionForward, DirectionNone, applyDeleteCharacterToSelections, applyDeleteHardLineForwardToSelections, applyDeleteSoftLineBackwardToSelections, applyDeleteWordBackwardToSelections, applyTextChangeToSelections, applyTextReplaceToSelections, applyTransposeToSelections, comparePosition, convertSelection, createSelectionFrom, createSelectionFromAnchorAndFocusOffsets, expandCollapsedSelectionToWord, extendSelection, extendSelections, findNexMatch, getAutoSurroundReplacementTexts, getCaretPosition, getDocumentBoundarySelection, getDocumentFullSelection, getSelectedLineBlocks, getSelectionAnchor, getSelectionText, isCollapsedSelection, isLineEditable, mapCursorMove, mapSelectionShift, mergeOverlappingSelections, remapSelectionsAfterEdits, resolveDeleteCharacterRange, resolveIndentEdits, resolveSelectionCut, selectionIntersects, shiftSelectionLines };
1624
+ export { DirectionBackward, DirectionForward, DirectionNone, applyDeleteCharacterToSelections, applyDeleteHardLineForwardToSelections, applyDeleteSoftLineBackwardToSelections, applyDeleteWordBackwardToSelections, applyTextChangeToSelections, applyTextReplaceToSelections, applyTransposeToSelections, comparePosition, convertSelection, createSelectionFrom, createSelectionFromAnchorAndFocusOffsets, expandCollapsedSelectionToWord, extendSelection, extendSelections, findNextMatch, getAutoSurroundReplacementTexts, getCaretPosition, getDocumentBoundarySelection, getDocumentFullSelection, getSelectedLineBlocks, getSelectionAnchor, getSelectionClipboardTexts, getSelectionText, isCollapsedSelection, isLineEditable, mapCursorMove, mapSelectionShift, mergeOverlappingSelections, remapSelectionsAfterEdits, resolveDeleteCharacterRange, resolveIndentEdits, resolveSelectionCut, selectionIntersects, shiftSelectionLines };
1497
1625
 
1498
1626
  //# sourceMappingURL=selection.js.map