@pierre/diffs 1.3.0-beta.5 → 1.3.0-beta.7
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/README.md +9 -9
- package/dist/components/CodeView.d.ts +13 -11
- package/dist/components/CodeView.d.ts.map +1 -1
- package/dist/components/CodeView.js +53 -14
- package/dist/components/CodeView.js.map +1 -1
- package/dist/components/File.d.ts +4 -5
- package/dist/components/File.d.ts.map +1 -1
- package/dist/components/File.js +37 -19
- package/dist/components/File.js.map +1 -1
- package/dist/components/FileDiff.d.ts +49 -36
- package/dist/components/FileDiff.d.ts.map +1 -1
- package/dist/components/FileDiff.js +173 -75
- package/dist/components/FileDiff.js.map +1 -1
- package/dist/components/FileStream.d.ts +0 -1
- package/dist/components/FileStream.d.ts.map +1 -1
- package/dist/components/FileStream.js +4 -4
- package/dist/components/FileStream.js.map +1 -1
- package/dist/components/UnresolvedFile.d.ts +3 -3
- package/dist/components/UnresolvedFile.d.ts.map +1 -1
- package/dist/components/UnresolvedFile.js +7 -5
- package/dist/components/UnresolvedFile.js.map +1 -1
- package/dist/components/VirtualizedFile.d.ts +0 -1
- package/dist/components/VirtualizedFile.d.ts.map +1 -1
- package/dist/components/VirtualizedFile.js +22 -25
- package/dist/components/VirtualizedFile.js.map +1 -1
- package/dist/components/VirtualizedFileDiff.d.ts +12 -7
- package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
- package/dist/components/VirtualizedFileDiff.js +192 -64
- package/dist/components/VirtualizedFileDiff.js.map +1 -1
- package/dist/components/Virtualizer.d.ts +1 -1
- package/dist/components/Virtualizer.d.ts.map +1 -1
- package/dist/components/Virtualizer.js +23 -24
- package/dist/components/Virtualizer.js.map +1 -1
- package/dist/components/VirtulizerDevelopment.d.ts.map +1 -1
- package/dist/components/web-components.d.ts.map +1 -1
- package/dist/components/web-components.js +2 -3
- package/dist/components/web-components.js.map +1 -1
- package/dist/constants.d.ts +3 -2
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +3 -2
- package/dist/constants.js.map +1 -1
- package/dist/editor/command.d.ts +2 -1
- package/dist/editor/command.d.ts.map +1 -1
- package/dist/editor/command.js +7 -3
- package/dist/editor/command.js.map +1 -1
- package/dist/editor/editStack.d.ts +7 -1
- package/dist/editor/editStack.d.ts.map +1 -1
- package/dist/editor/editStack.js +3 -3
- package/dist/editor/editStack.js.map +1 -1
- package/dist/editor/editor.d.ts +28 -4
- package/dist/editor/editor.d.ts.map +1 -1
- package/dist/editor/editor.js +669 -313
- package/dist/editor/editor.js.map +1 -1
- package/dist/editor/editor2.js +3 -3
- package/dist/editor/editor2.js.map +1 -1
- package/dist/editor/index.js +1 -2
- package/dist/editor/lineAnnotations.d.ts.map +1 -1
- package/dist/editor/lineAnnotations.js +2 -3
- package/dist/editor/lineAnnotations.js.map +1 -1
- package/dist/editor/marker.d.ts +2 -1
- package/dist/editor/marker.d.ts.map +1 -1
- package/dist/editor/marker.js +28 -11
- package/dist/editor/marker.js.map +1 -1
- package/dist/editor/pieceTable.d.ts +4 -2
- package/dist/editor/pieceTable.d.ts.map +1 -1
- package/dist/editor/pieceTable.js +138 -128
- package/dist/editor/pieceTable.js.map +1 -1
- package/dist/editor/platform.d.ts +8 -1
- package/dist/editor/platform.d.ts.map +1 -1
- package/dist/editor/platform.js +16 -5
- package/dist/editor/platform.js.map +1 -1
- package/dist/editor/searchPanel.d.ts +1 -0
- package/dist/editor/searchPanel.d.ts.map +1 -1
- package/dist/editor/searchPanel.js +75 -62
- package/dist/editor/searchPanel.js.map +1 -1
- package/dist/editor/selection.d.ts +42 -5
- package/dist/editor/selection.d.ts.map +1 -1
- package/dist/editor/selection.js +504 -114
- package/dist/editor/selection.js.map +1 -1
- package/dist/editor/selectionAction.d.ts +4 -5
- package/dist/editor/selectionAction.d.ts.map +1 -1
- package/dist/editor/selectionAction.js +14 -64
- package/dist/editor/selectionAction.js.map +1 -1
- package/dist/editor/sprite.d.ts +2 -2
- package/dist/editor/sprite.d.ts.map +1 -1
- package/dist/editor/sprite.js +7 -14
- package/dist/editor/sprite.js.map +1 -1
- package/dist/editor/textDocument.d.ts +5 -4
- package/dist/editor/textDocument.d.ts.map +1 -1
- package/dist/editor/textDocument.js +26 -15
- package/dist/editor/textDocument.js.map +1 -1
- package/dist/editor/textMeasure.d.ts +36 -3
- package/dist/editor/textMeasure.d.ts.map +1 -1
- package/dist/editor/textMeasure.js +104 -17
- package/dist/editor/textMeasure.js.map +1 -1
- package/dist/editor/tokenzier.d.ts +3 -0
- package/dist/editor/tokenzier.d.ts.map +1 -1
- package/dist/editor/tokenzier.js +27 -16
- package/dist/editor/tokenzier.js.map +1 -1
- package/dist/editor/utils.d.ts +4 -1
- package/dist/editor/utils.d.ts.map +1 -1
- package/dist/editor/utils.js +19 -3
- package/dist/editor/utils.js.map +1 -1
- package/dist/highlighter/languages/areLanguagesAttached.d.ts.map +1 -1
- package/dist/highlighter/languages/areLanguagesAttached.js +1 -2
- package/dist/highlighter/languages/areLanguagesAttached.js.map +1 -1
- package/dist/highlighter/languages/attachResolvedLanguages.d.ts +0 -2
- package/dist/highlighter/languages/attachResolvedLanguages.d.ts.map +1 -1
- package/dist/highlighter/languages/attachResolvedLanguages.js +1 -2
- package/dist/highlighter/languages/attachResolvedLanguages.js.map +1 -1
- package/dist/highlighter/languages/cleanUpResolvedLanguages.d.ts.map +1 -1
- package/dist/highlighter/languages/cleanUpResolvedLanguages.js +1 -2
- package/dist/highlighter/languages/cleanUpResolvedLanguages.js.map +1 -1
- package/dist/highlighter/languages/constants.d.ts +0 -1
- package/dist/highlighter/languages/constants.d.ts.map +1 -1
- package/dist/highlighter/languages/constants.js +1 -1
- package/dist/highlighter/languages/constants.js.map +1 -1
- package/dist/highlighter/languages/getResolvedLanguages.d.ts +0 -2
- package/dist/highlighter/languages/getResolvedLanguages.d.ts.map +1 -1
- package/dist/highlighter/languages/getResolvedLanguages.js +1 -2
- package/dist/highlighter/languages/getResolvedLanguages.js.map +1 -1
- package/dist/highlighter/languages/getResolvedOrResolveLanguage.d.ts +0 -2
- package/dist/highlighter/languages/getResolvedOrResolveLanguage.d.ts.map +1 -1
- package/dist/highlighter/languages/getResolvedOrResolveLanguage.js +1 -2
- package/dist/highlighter/languages/getResolvedOrResolveLanguage.js.map +1 -1
- package/dist/highlighter/languages/hasResolvedLanguages.d.ts.map +1 -1
- package/dist/highlighter/languages/hasResolvedLanguages.js +1 -2
- package/dist/highlighter/languages/hasResolvedLanguages.js.map +1 -1
- package/dist/highlighter/languages/registerCustomLanguage.d.ts +0 -1
- package/dist/highlighter/languages/registerCustomLanguage.d.ts.map +1 -1
- package/dist/highlighter/languages/registerCustomLanguage.js +1 -2
- package/dist/highlighter/languages/registerCustomLanguage.js.map +1 -1
- package/dist/highlighter/languages/resolveLanguage.d.ts +0 -2
- package/dist/highlighter/languages/resolveLanguage.d.ts.map +1 -1
- package/dist/highlighter/languages/resolveLanguage.js +4 -5
- package/dist/highlighter/languages/resolveLanguage.js.map +1 -1
- package/dist/highlighter/languages/resolveLanguages.d.ts +0 -2
- package/dist/highlighter/languages/resolveLanguages.d.ts.map +1 -1
- package/dist/highlighter/languages/resolveLanguages.js +1 -2
- package/dist/highlighter/languages/resolveLanguages.js.map +1 -1
- package/dist/highlighter/shared_highlighter.d.ts.map +1 -1
- package/dist/highlighter/shared_highlighter.js +3 -4
- package/dist/highlighter/shared_highlighter.js.map +1 -1
- package/dist/highlighter/themes/areThemesAttached.d.ts.map +1 -1
- package/dist/highlighter/themes/areThemesAttached.js +1 -2
- package/dist/highlighter/themes/areThemesAttached.js.map +1 -1
- package/dist/highlighter/themes/attachResolvedThemes.d.ts.map +1 -1
- package/dist/highlighter/themes/attachResolvedThemes.js +1 -2
- package/dist/highlighter/themes/attachResolvedThemes.js.map +1 -1
- package/dist/highlighter/themes/cleanUpResolvedThemes.d.ts.map +1 -1
- package/dist/highlighter/themes/cleanUpResolvedThemes.js +1 -2
- package/dist/highlighter/themes/cleanUpResolvedThemes.js.map +1 -1
- package/dist/highlighter/themes/constants.d.ts.map +1 -1
- package/dist/highlighter/themes/constants.js +1 -1
- package/dist/highlighter/themes/constants.js.map +1 -1
- package/dist/highlighter/themes/getResolvedOrResolveTheme.d.ts.map +1 -1
- package/dist/highlighter/themes/getResolvedOrResolveTheme.js +1 -2
- package/dist/highlighter/themes/getResolvedOrResolveTheme.js.map +1 -1
- package/dist/highlighter/themes/getResolvedThemes.d.ts.map +1 -1
- package/dist/highlighter/themes/getResolvedThemes.js +1 -2
- package/dist/highlighter/themes/getResolvedThemes.js.map +1 -1
- package/dist/highlighter/themes/hasResolvedThemes.d.ts.map +1 -1
- package/dist/highlighter/themes/hasResolvedThemes.js +1 -2
- package/dist/highlighter/themes/hasResolvedThemes.js.map +1 -1
- package/dist/highlighter/themes/registerCustomCSSVariableTheme.d.ts.map +1 -1
- package/dist/highlighter/themes/registerCustomCSSVariableTheme.js +1 -2
- package/dist/highlighter/themes/registerCustomCSSVariableTheme.js.map +1 -1
- package/dist/highlighter/themes/registerCustomTheme.d.ts.map +1 -1
- package/dist/highlighter/themes/registerCustomTheme.js +1 -2
- package/dist/highlighter/themes/registerCustomTheme.js.map +1 -1
- package/dist/highlighter/themes/resolveTheme.d.ts.map +1 -1
- package/dist/highlighter/themes/resolveTheme.js +1 -2
- package/dist/highlighter/themes/resolveTheme.js.map +1 -1
- package/dist/highlighter/themes/resolveThemes.d.ts.map +1 -1
- package/dist/highlighter/themes/resolveThemes.js +1 -2
- package/dist/highlighter/themes/resolveThemes.js.map +1 -1
- package/dist/highlighter/themes/themeResolution.d.ts.map +1 -1
- package/dist/highlighter/themes/themeResolution.js +1 -2
- package/dist/highlighter/themes/themeResolution.js.map +1 -1
- package/dist/highlighter/themes/themeResolver.d.ts +2 -2
- package/dist/highlighter/themes/themeResolver.d.ts.map +1 -1
- package/dist/highlighter/themes/themeResolver.js +1 -2
- package/dist/highlighter/themes/themeResolver.js.map +1 -1
- package/dist/index.d.ts +12 -10
- package/dist/index.js +4 -3
- package/dist/managers/InteractionManager.d.ts +7 -0
- package/dist/managers/InteractionManager.d.ts.map +1 -1
- package/dist/managers/InteractionManager.js +25 -4
- package/dist/managers/InteractionManager.js.map +1 -1
- package/dist/managers/ResizeManager.d.ts.map +1 -1
- package/dist/managers/ResizeManager.js +1 -1
- package/dist/managers/ResizeManager.js.map +1 -1
- package/dist/managers/ScrollSyncManager.d.ts.map +1 -1
- package/dist/managers/ScrollSyncManager.js +1 -1
- package/dist/managers/ScrollSyncManager.js.map +1 -1
- package/dist/managers/UniversalRenderingManager.d.ts.map +1 -1
- package/dist/managers/UniversalRenderingManager.js +2 -2
- package/dist/managers/UniversalRenderingManager.js.map +1 -1
- package/dist/node_modules/.pnpm/@types_hast@3.0.4/node_modules/@types/hast/index.d.ts +228 -0
- package/dist/node_modules/.pnpm/@types_hast@3.0.4/node_modules/@types/hast/index.d.ts.map +1 -0
- package/dist/node_modules/.pnpm/@types_unist@3.0.3/node_modules/@types/unist/index.d.ts +84 -0
- package/dist/node_modules/.pnpm/@types_unist@3.0.3/node_modules/@types/unist/index.d.ts.map +1 -0
- package/dist/react/CodeView.d.ts +1 -1
- package/dist/react/CodeView.d.ts.map +1 -1
- package/dist/react/CodeView.js +17 -16
- package/dist/react/CodeView.js.map +1 -1
- package/dist/react/EditorContext.d.ts +0 -1
- package/dist/react/EditorContext.d.ts.map +1 -1
- package/dist/react/EditorContext.js +2 -5
- package/dist/react/EditorContext.js.map +1 -1
- package/dist/react/File.d.ts +1 -0
- package/dist/react/File.d.ts.map +1 -1
- package/dist/react/File.js +4 -6
- package/dist/react/File.js.map +1 -1
- package/dist/react/FileDiff.d.ts +1 -0
- package/dist/react/FileDiff.d.ts.map +1 -1
- package/dist/react/FileDiff.js +4 -6
- package/dist/react/FileDiff.js.map +1 -1
- package/dist/react/MultiFileDiff.d.ts +4 -4
- package/dist/react/MultiFileDiff.d.ts.map +1 -1
- package/dist/react/MultiFileDiff.js +4 -6
- package/dist/react/MultiFileDiff.js.map +1 -1
- package/dist/react/PatchDiff.d.ts +1 -0
- package/dist/react/PatchDiff.d.ts.map +1 -1
- package/dist/react/PatchDiff.js +4 -6
- package/dist/react/PatchDiff.js.map +1 -1
- package/dist/react/UnresolvedFile.d.ts +2 -1
- package/dist/react/UnresolvedFile.d.ts.map +1 -1
- package/dist/react/UnresolvedFile.js +4 -6
- package/dist/react/UnresolvedFile.js.map +1 -1
- package/dist/react/Virtualizer.d.ts.map +1 -1
- package/dist/react/Virtualizer.js +2 -5
- package/dist/react/Virtualizer.js.map +1 -1
- package/dist/react/WorkerPoolContext.d.ts +0 -1
- package/dist/react/WorkerPoolContext.d.ts.map +1 -1
- package/dist/react/WorkerPoolContext.js +2 -5
- package/dist/react/WorkerPoolContext.js.map +1 -1
- package/dist/react/constants.d.ts.map +1 -1
- package/dist/react/constants.js +1 -1
- package/dist/react/constants.js.map +1 -1
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.js +1 -2
- package/dist/react/jsx.d.ts +0 -2
- package/dist/react/jsx.d.ts.map +1 -1
- package/dist/react/types.d.ts +2 -0
- package/dist/react/types.d.ts.map +1 -1
- package/dist/react/utils/renderDiffChildren.d.ts +2 -0
- package/dist/react/utils/renderDiffChildren.d.ts.map +1 -1
- package/dist/react/utils/renderDiffChildren.js +18 -11
- package/dist/react/utils/renderDiffChildren.js.map +1 -1
- package/dist/react/utils/renderFileChildren.d.ts +2 -0
- package/dist/react/utils/renderFileChildren.d.ts.map +1 -1
- package/dist/react/utils/renderFileChildren.js +18 -11
- package/dist/react/utils/renderFileChildren.js.map +1 -1
- package/dist/react/utils/templateRender.d.ts.map +1 -1
- package/dist/react/utils/templateRender.js +1 -2
- package/dist/react/utils/templateRender.js.map +1 -1
- package/dist/react/utils/useFileDiffInstance.d.ts.map +1 -1
- package/dist/react/utils/useFileDiffInstance.js +15 -18
- package/dist/react/utils/useFileDiffInstance.js.map +1 -1
- package/dist/react/utils/useFileInstance.d.ts.map +1 -1
- package/dist/react/utils/useFileInstance.js +1 -2
- package/dist/react/utils/useFileInstance.js.map +1 -1
- package/dist/react/utils/useStableCallback.d.ts.map +1 -1
- package/dist/react/utils/useStableCallback.js +1 -2
- package/dist/react/utils/useStableCallback.js.map +1 -1
- package/dist/react/utils/useUnresolvedFileInstance.d.ts.map +1 -1
- package/dist/react/utils/useUnresolvedFileInstance.js +10 -11
- package/dist/react/utils/useUnresolvedFileInstance.js.map +1 -1
- package/dist/renderers/DiffHunksRenderer.d.ts +2 -3
- package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
- package/dist/renderers/DiffHunksRenderer.js +52 -33
- package/dist/renderers/DiffHunksRenderer.js.map +1 -1
- package/dist/renderers/FileRenderer.d.ts +1 -3
- package/dist/renderers/FileRenderer.d.ts.map +1 -1
- package/dist/renderers/FileRenderer.js +14 -11
- package/dist/renderers/FileRenderer.js.map +1 -1
- package/dist/renderers/UnresolvedFileHunksRenderer.d.ts +1 -2
- package/dist/renderers/UnresolvedFileHunksRenderer.d.ts.map +1 -1
- package/dist/renderers/UnresolvedFileHunksRenderer.js +1 -2
- package/dist/renderers/UnresolvedFileHunksRenderer.js.map +1 -1
- package/dist/shiki-stream/index.js +1 -2
- package/dist/shiki-stream/stream.d.ts +0 -1
- package/dist/shiki-stream/stream.d.ts.map +1 -1
- package/dist/shiki-stream/stream.js +1 -2
- package/dist/shiki-stream/stream.js.map +1 -1
- package/dist/shiki-stream/tokenizer.d.ts.map +1 -1
- package/dist/shiki-stream/tokenizer.js +1 -1
- package/dist/shiki-stream/tokenizer.js.map +1 -1
- package/dist/shiki-stream/types.d.ts +0 -1
- package/dist/shiki-stream/types.d.ts.map +1 -1
- package/dist/sprite.d.ts.map +1 -1
- package/dist/sprite.js +1 -1
- package/dist/ssr/FileDiffReact.d.ts.map +1 -1
- package/dist/ssr/FileDiffReact.js +5 -8
- package/dist/ssr/FileDiffReact.js.map +1 -1
- package/dist/ssr/index.d.ts +2 -2
- package/dist/ssr/index.js +1 -2
- package/dist/ssr/preloadDiffs.d.ts +12 -11
- package/dist/ssr/preloadDiffs.d.ts.map +1 -1
- package/dist/ssr/preloadDiffs.js +15 -8
- package/dist/ssr/preloadDiffs.js.map +1 -1
- package/dist/ssr/preloadFile.d.ts.map +1 -1
- package/dist/ssr/preloadFile.js +1 -2
- package/dist/ssr/preloadFile.js.map +1 -1
- package/dist/ssr/preloadPatchFile.d.ts.map +1 -1
- package/dist/ssr/preloadPatchFile.js +2 -3
- package/dist/ssr/preloadPatchFile.js.map +1 -1
- package/dist/ssr/renderHTML.d.ts +1 -1
- package/dist/ssr/renderHTML.d.ts.map +1 -1
- package/dist/ssr/renderHTML.js +1 -2
- package/dist/ssr/renderHTML.js.map +1 -1
- package/dist/string-import.d.ts +4 -0
- package/dist/string-import.d.ts.map +1 -1
- package/dist/style.js +3 -3
- package/dist/style.js.map +1 -1
- package/dist/types.d.ts +67 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/areDiffLineAnnotationsEqual.d.ts.map +1 -1
- package/dist/utils/areDiffLineAnnotationsEqual.js +1 -1
- package/dist/utils/areDiffLineAnnotationsEqual.js.map +1 -1
- package/dist/utils/areDiffRenderOptionsEqual.d.ts.map +1 -1
- package/dist/utils/areDiffRenderOptionsEqual.js +1 -2
- package/dist/utils/areDiffRenderOptionsEqual.js.map +1 -1
- package/dist/utils/areDiffTargetsEqual.d.ts.map +1 -1
- package/dist/utils/areDiffTargetsEqual.js +1 -1
- package/dist/utils/areDiffTargetsEqual.js.map +1 -1
- package/dist/utils/areFileRenderOptionsEqual.d.ts.map +1 -1
- package/dist/utils/areFileRenderOptionsEqual.js +1 -2
- package/dist/utils/areFileRenderOptionsEqual.js.map +1 -1
- package/dist/utils/areFilesEqual.d.ts.map +1 -1
- package/dist/utils/areFilesEqual.js +1 -1
- package/dist/utils/areFilesEqual.js.map +1 -1
- package/dist/utils/areHunkDataEqual.d.ts.map +1 -1
- package/dist/utils/areHunkDataEqual.js +2 -2
- package/dist/utils/areHunkDataEqual.js.map +1 -1
- package/dist/utils/areLineAnnotationsEqual.d.ts.map +1 -1
- package/dist/utils/areLineAnnotationsEqual.js +1 -1
- package/dist/utils/areLineAnnotationsEqual.js.map +1 -1
- package/dist/utils/areManagedSnapshotsEqual.d.ts.map +1 -1
- package/dist/utils/areManagedSnapshotsEqual.js +1 -1
- package/dist/utils/areManagedSnapshotsEqual.js.map +1 -1
- package/dist/utils/areMergeConflictActionsEqual.d.ts.map +1 -1
- package/dist/utils/areMergeConflictActionsEqual.js +1 -1
- package/dist/utils/areMergeConflictActionsEqual.js.map +1 -1
- package/dist/utils/areObjectsEqual.d.ts.map +1 -1
- package/dist/utils/areObjectsEqual.js +1 -1
- package/dist/utils/areObjectsEqual.js.map +1 -1
- package/dist/utils/areOptionsEqual.d.ts +0 -2
- package/dist/utils/areOptionsEqual.d.ts.map +1 -1
- package/dist/utils/areOptionsEqual.js +1 -2
- package/dist/utils/areOptionsEqual.js.map +1 -1
- package/dist/utils/arePrePropertiesEqual.d.ts.map +1 -1
- package/dist/utils/arePrePropertiesEqual.js +1 -1
- package/dist/utils/arePrePropertiesEqual.js.map +1 -1
- package/dist/utils/areRenderRangesEqual.d.ts.map +1 -1
- package/dist/utils/areRenderRangesEqual.js +1 -1
- package/dist/utils/areRenderRangesEqual.js.map +1 -1
- package/dist/utils/areSelectionPointsEqual.d.ts.map +1 -1
- package/dist/utils/areSelectionPointsEqual.js +1 -1
- package/dist/utils/areSelectionPointsEqual.js.map +1 -1
- package/dist/utils/areSelectionsEqual.d.ts.map +1 -1
- package/dist/utils/areSelectionsEqual.js +1 -1
- package/dist/utils/areSelectionsEqual.js.map +1 -1
- package/dist/utils/areThemesEqual.d.ts.map +1 -1
- package/dist/utils/areThemesEqual.js +1 -1
- package/dist/utils/areThemesEqual.js.map +1 -1
- package/dist/utils/areVirtualWindowSpecsEqual.d.ts.map +1 -1
- package/dist/utils/areVirtualWindowSpecsEqual.js +1 -1
- package/dist/utils/areVirtualWindowSpecsEqual.js.map +1 -1
- package/dist/utils/areWorkerStatsEqual.d.ts +0 -2
- package/dist/utils/areWorkerStatsEqual.d.ts.map +1 -1
- package/dist/utils/areWorkerStatsEqual.js +1 -1
- package/dist/utils/areWorkerStatsEqual.js.map +1 -1
- package/dist/utils/awaitWithTimeout.d.ts +5 -0
- package/dist/utils/awaitWithTimeout.d.ts.map +1 -0
- package/dist/utils/awaitWithTimeout.js +15 -0
- package/dist/utils/awaitWithTimeout.js.map +1 -0
- package/dist/utils/cleanLastNewline.d.ts.map +1 -1
- package/dist/utils/cleanLastNewline.js +1 -1
- package/dist/utils/cleanLastNewline.js.map +1 -1
- package/dist/utils/cloneFileDiffMetadata.d.ts +7 -0
- package/dist/utils/cloneFileDiffMetadata.d.ts.map +1 -0
- package/dist/utils/cloneFileDiffMetadata.js +16 -0
- package/dist/utils/cloneFileDiffMetadata.js.map +1 -0
- package/dist/utils/computeEstimatedDiffHeights.d.ts +3 -1
- package/dist/utils/computeEstimatedDiffHeights.d.ts.map +1 -1
- package/dist/utils/computeEstimatedDiffHeights.js +9 -3
- package/dist/utils/computeEstimatedDiffHeights.js.map +1 -1
- package/dist/utils/computeFileOffsets.d.ts +9 -1
- package/dist/utils/computeFileOffsets.d.ts.map +1 -1
- package/dist/utils/computeFileOffsets.js +20 -2
- package/dist/utils/computeFileOffsets.js.map +1 -1
- package/dist/utils/computeVirtualFileMetrics.d.ts.map +1 -1
- package/dist/utils/computeVirtualFileMetrics.js +1 -2
- package/dist/utils/computeVirtualFileMetrics.js.map +1 -1
- package/dist/utils/createAnnotationElement.d.ts +1 -1
- package/dist/utils/createAnnotationElement.d.ts.map +1 -1
- package/dist/utils/createAnnotationElement.js +1 -2
- package/dist/utils/createAnnotationElement.js.map +1 -1
- package/dist/utils/createAnnotationWrapperNode.d.ts.map +1 -1
- package/dist/utils/createAnnotationWrapperNode.js +1 -1
- package/dist/utils/createAnnotationWrapperNode.js.map +1 -1
- package/dist/utils/createContentColumn.d.ts +1 -1
- package/dist/utils/createContentColumn.d.ts.map +1 -1
- package/dist/utils/createContentColumn.js +1 -2
- package/dist/utils/createContentColumn.js.map +1 -1
- package/dist/utils/createEmptyRowBuffer.d.ts +1 -1
- package/dist/utils/createEmptyRowBuffer.d.ts.map +1 -1
- package/dist/utils/createEmptyRowBuffer.js +1 -2
- package/dist/utils/createEmptyRowBuffer.js.map +1 -1
- package/dist/utils/createFileHeaderElement.d.ts +1 -1
- package/dist/utils/createFileHeaderElement.d.ts.map +1 -1
- package/dist/utils/createFileHeaderElement.js +6 -3
- package/dist/utils/createFileHeaderElement.js.map +1 -1
- package/dist/utils/createGutterUtilityContentNode.d.ts.map +1 -1
- package/dist/utils/createGutterUtilityContentNode.js +1 -1
- package/dist/utils/createGutterUtilityContentNode.js.map +1 -1
- package/dist/utils/createGutterUtilityElement.d.ts +1 -1
- package/dist/utils/createGutterUtilityElement.d.ts.map +1 -1
- package/dist/utils/createGutterUtilityElement.js +1 -2
- package/dist/utils/createGutterUtilityElement.js.map +1 -1
- package/dist/utils/createNoNewlineElement.d.ts +1 -1
- package/dist/utils/createNoNewlineElement.d.ts.map +1 -1
- package/dist/utils/createNoNewlineElement.js +1 -2
- package/dist/utils/createNoNewlineElement.js.map +1 -1
- package/dist/utils/createPreElement.d.ts +1 -1
- package/dist/utils/createPreElement.d.ts.map +1 -1
- package/dist/utils/createPreElement.js +1 -3
- package/dist/utils/createPreElement.js.map +1 -1
- package/dist/utils/createRowNodes.d.ts.map +1 -1
- package/dist/utils/createRowNodes.js +1 -1
- package/dist/utils/createRowNodes.js.map +1 -1
- package/dist/utils/createSeparator.d.ts +1 -1
- package/dist/utils/createSeparator.d.ts.map +1 -1
- package/dist/utils/createSeparator.js +1 -2
- package/dist/utils/createSeparator.js.map +1 -1
- package/dist/utils/createSpanNodeFromToken.d.ts.map +1 -1
- package/dist/utils/createSpanNodeFromToken.js +1 -2
- package/dist/utils/createSpanNodeFromToken.js.map +1 -1
- package/dist/utils/createStyleElement.d.ts +1 -1
- package/dist/utils/createStyleElement.d.ts.map +1 -1
- package/dist/utils/createStyleElement.js +1 -2
- package/dist/utils/createStyleElement.js.map +1 -1
- package/dist/utils/createTransformerWithState.d.ts.map +1 -1
- package/dist/utils/createTransformerWithState.js +1 -2
- package/dist/utils/createTransformerWithState.js.map +1 -1
- package/dist/utils/createUnsafeCSSStyleNode.d.ts.map +1 -1
- package/dist/utils/createUnsafeCSSStyleNode.js +1 -2
- package/dist/utils/createUnsafeCSSStyleNode.js.map +1 -1
- package/dist/utils/createWindowFromScrollPosition.d.ts.map +1 -1
- package/dist/utils/createWindowFromScrollPosition.js +5 -5
- package/dist/utils/createWindowFromScrollPosition.js.map +1 -1
- package/dist/utils/cssWrappers.d.ts.map +1 -1
- package/dist/utils/cssWrappers.js +2 -3
- package/dist/utils/cssWrappers.js.map +1 -1
- package/dist/utils/detachString.d.ts.map +1 -1
- package/dist/utils/detachString.js +1 -1
- package/dist/utils/detachString.js.map +1 -1
- package/dist/utils/diffAcceptRejectHunk.d.ts.map +1 -1
- package/dist/utils/diffAcceptRejectHunk.js +1 -2
- package/dist/utils/diffAcceptRejectHunk.js.map +1 -1
- package/dist/utils/formatCSSVariablePrefix.d.ts.map +1 -1
- package/dist/utils/formatCSSVariablePrefix.js +1 -1
- package/dist/utils/formatCSSVariablePrefix.js.map +1 -1
- package/dist/utils/getDiffFileInput.d.ts +14 -0
- package/dist/utils/getDiffFileInput.d.ts.map +1 -0
- package/dist/utils/getDiffFileInput.js +24 -0
- package/dist/utils/getDiffFileInput.js.map +1 -0
- package/dist/utils/getDiffHunksRendererOptions.d.ts.map +1 -1
- package/dist/utils/getDiffHunksRendererOptions.js +2 -1
- package/dist/utils/getDiffHunksRendererOptions.js.map +1 -1
- package/dist/utils/getFileRendererOptions.d.ts.map +1 -1
- package/dist/utils/getFileRendererOptions.js +1 -1
- package/dist/utils/getFileRendererOptions.js.map +1 -1
- package/dist/utils/getFiletypeFromFileName.d.ts.map +1 -1
- package/dist/utils/getFiletypeFromFileName.js +3 -1
- package/dist/utils/getFiletypeFromFileName.js.map +1 -1
- package/dist/utils/getHighlighterOptions.d.ts.map +1 -1
- package/dist/utils/getHighlighterOptions.js +1 -2
- package/dist/utils/getHighlighterOptions.js.map +1 -1
- package/dist/utils/getHighlighterThemeStyles.d.ts.map +1 -1
- package/dist/utils/getHighlighterThemeStyles.js +1 -2
- package/dist/utils/getHighlighterThemeStyles.js.map +1 -1
- package/dist/utils/getHunkSeparatorSlotName.d.ts.map +1 -1
- package/dist/utils/getHunkSeparatorSlotName.js +1 -1
- package/dist/utils/getHunkSeparatorSlotName.js.map +1 -1
- package/dist/utils/getIconForType.d.ts.map +1 -1
- package/dist/utils/getIconForType.js +1 -1
- package/dist/utils/getIconForType.js.map +1 -1
- package/dist/utils/getLineAnnotationName.d.ts.map +1 -1
- package/dist/utils/getLineAnnotationName.js +1 -1
- package/dist/utils/getLineAnnotationName.js.map +1 -1
- package/dist/utils/getLineEndingType.d.ts.map +1 -1
- package/dist/utils/getLineEndingType.js +1 -1
- package/dist/utils/getLineEndingType.js.map +1 -1
- package/dist/utils/getLineNodes.d.ts +1 -1
- package/dist/utils/getLineNodes.d.ts.map +1 -1
- package/dist/utils/getLineNodes.js +1 -1
- package/dist/utils/getLineNodes.js.map +1 -1
- package/dist/utils/getMergeConflictActionSlotName.d.ts.map +1 -1
- package/dist/utils/getMergeConflictActionSlotName.js +1 -1
- package/dist/utils/getMergeConflictActionSlotName.js.map +1 -1
- package/dist/utils/getMergeConflictLineTypes.d.ts.map +1 -1
- package/dist/utils/getMergeConflictLineTypes.js +1 -2
- package/dist/utils/getMergeConflictLineTypes.js.map +1 -1
- package/dist/utils/getOrCreateCodeNode.d.ts.map +1 -1
- package/dist/utils/getOrCreateCodeNode.js +1 -1
- package/dist/utils/getOrCreateCodeNode.js.map +1 -1
- package/dist/utils/getSingularPatch.d.ts.map +1 -1
- package/dist/utils/getSingularPatch.js +1 -2
- package/dist/utils/getSingularPatch.js.map +1 -1
- package/dist/utils/getThemes.d.ts.map +1 -1
- package/dist/utils/getThemes.js +1 -2
- package/dist/utils/getThemes.js.map +1 -1
- package/dist/utils/getTotalLineCountFromHunks.d.ts.map +1 -1
- package/dist/utils/getTotalLineCountFromHunks.js +1 -1
- package/dist/utils/getTotalLineCountFromHunks.js.map +1 -1
- package/dist/utils/hast_utils.d.ts +1 -1
- package/dist/utils/hast_utils.d.ts.map +1 -1
- package/dist/utils/hast_utils.js +1 -1
- package/dist/utils/hast_utils.js.map +1 -1
- package/dist/utils/hostTheme.d.ts.map +1 -1
- package/dist/utils/hostTheme.js +1 -2
- package/dist/utils/hostTheme.js.map +1 -1
- package/dist/utils/hydratePartialDiff.d.ts +10 -0
- package/dist/utils/hydratePartialDiff.d.ts.map +1 -0
- package/dist/utils/hydratePartialDiff.js +140 -0
- package/dist/utils/hydratePartialDiff.js.map +1 -0
- package/dist/utils/includesFileAnnotations.d.ts.map +1 -1
- package/dist/utils/includesFileAnnotations.js +5 -5
- package/dist/utils/includesFileAnnotations.js.map +1 -1
- package/dist/utils/isDefaultRenderRange.d.ts.map +1 -1
- package/dist/utils/isDefaultRenderRange.js +1 -1
- package/dist/utils/isDefaultRenderRange.js.map +1 -1
- package/dist/utils/isDiffPlainText.d.ts.map +1 -1
- package/dist/utils/isDiffPlainText.js +1 -2
- package/dist/utils/isDiffPlainText.js.map +1 -1
- package/dist/utils/isFilePlainText.d.ts.map +1 -1
- package/dist/utils/isFilePlainText.js +1 -2
- package/dist/utils/isFilePlainText.js.map +1 -1
- package/dist/utils/isStyleNode.d.ts.map +1 -1
- package/dist/utils/isStyleNode.js +1 -1
- package/dist/utils/isStyleNode.js.map +1 -1
- package/dist/utils/isWorkerContext.d.ts.map +1 -1
- package/dist/utils/isWorkerContext.js +1 -1
- package/dist/utils/isWorkerContext.js.map +1 -1
- package/dist/utils/iterateOverDiff.d.ts.map +1 -1
- package/dist/utils/iterateOverDiff.js +47 -48
- package/dist/utils/iterateOverDiff.js.map +1 -1
- package/dist/utils/normalizeDiffResolution.d.ts.map +1 -1
- package/dist/utils/normalizeDiffResolution.js +1 -1
- package/dist/utils/normalizeDiffResolution.js.map +1 -1
- package/dist/utils/parseDiffDecorations.d.ts.map +1 -1
- package/dist/utils/parseDiffDecorations.js +1 -2
- package/dist/utils/parseDiffDecorations.js.map +1 -1
- package/dist/utils/parseDiffFromFile.d.ts +1 -2
- package/dist/utils/parseDiffFromFile.d.ts.map +1 -1
- package/dist/utils/parseDiffFromFile.js +27 -7
- package/dist/utils/parseDiffFromFile.js.map +1 -1
- package/dist/utils/parseLineType.d.ts.map +1 -1
- package/dist/utils/parseLineType.js +1 -1
- package/dist/utils/parseLineType.js.map +1 -1
- package/dist/utils/parseMergeConflictDiffFromFile.d.ts.map +1 -1
- package/dist/utils/parseMergeConflictDiffFromFile.js +5 -5
- package/dist/utils/parseMergeConflictDiffFromFile.js.map +1 -1
- package/dist/utils/parsePatchFiles.d.ts.map +1 -1
- package/dist/utils/parsePatchFiles.js +6 -7
- package/dist/utils/parsePatchFiles.js.map +1 -1
- package/dist/utils/prefersReducedMotion.d.ts.map +1 -1
- package/dist/utils/prefersReducedMotion.js +1 -1
- package/dist/utils/prefersReducedMotion.js.map +1 -1
- package/dist/utils/prerenderHTMLIfNecessary.d.ts.map +1 -1
- package/dist/utils/prerenderHTMLIfNecessary.js +1 -1
- package/dist/utils/prerenderHTMLIfNecessary.js.map +1 -1
- package/dist/utils/processLine.d.ts +1 -1
- package/dist/utils/processLine.d.ts.map +1 -1
- package/dist/utils/processLine.js +1 -2
- package/dist/utils/processLine.js.map +1 -1
- package/dist/utils/renderDiffWithHighlighter.d.ts.map +1 -1
- package/dist/utils/renderDiffWithHighlighter.js +4 -5
- package/dist/utils/renderDiffWithHighlighter.js.map +1 -1
- package/dist/utils/renderFileWithHighlighter.d.ts.map +1 -1
- package/dist/utils/renderFileWithHighlighter.js +1 -2
- package/dist/utils/renderFileWithHighlighter.js.map +1 -1
- package/dist/utils/resolveConflict.d.ts.map +1 -1
- package/dist/utils/resolveConflict.js +1 -2
- package/dist/utils/resolveConflict.js.map +1 -1
- package/dist/utils/resolveRegion.d.ts.map +1 -1
- package/dist/utils/resolveRegion.js +1 -1
- package/dist/utils/resolveRegion.js.map +1 -1
- package/dist/utils/roundToDevicePixel.d.ts.map +1 -1
- package/dist/utils/roundToDevicePixel.js +1 -1
- package/dist/utils/roundToDevicePixel.js.map +1 -1
- package/dist/utils/scrollbarGutter.d.ts.map +1 -1
- package/dist/utils/scrollbarGutter.js +1 -2
- package/dist/utils/scrollbarGutter.js.map +1 -1
- package/dist/utils/setLanguageOverride.d.ts.map +1 -1
- package/dist/utils/setLanguageOverride.js +1 -1
- package/dist/utils/setLanguageOverride.js.map +1 -1
- package/dist/utils/setWrapperNodeProps.d.ts.map +1 -1
- package/dist/utils/setWrapperNodeProps.js +1 -2
- package/dist/utils/setWrapperNodeProps.js.map +1 -1
- package/dist/utils/shouldUseTokenTransformer.d.ts.map +1 -1
- package/dist/utils/shouldUseTokenTransformer.js +1 -1
- package/dist/utils/shouldUseTokenTransformer.js.map +1 -1
- package/dist/utils/splitFileContents.d.ts.map +1 -1
- package/dist/utils/splitFileContents.js +1 -2
- package/dist/utils/splitFileContents.js.map +1 -1
- package/dist/utils/trimPatchContext.d.ts.map +1 -1
- package/dist/utils/trimPatchContext.js +1 -2
- package/dist/utils/trimPatchContext.js.map +1 -1
- package/dist/utils/updateDiffHunks.d.ts +6 -1
- package/dist/utils/updateDiffHunks.d.ts.map +1 -1
- package/dist/utils/updateDiffHunks.js +44 -3
- package/dist/utils/updateDiffHunks.js.map +1 -1
- package/dist/utils/virtualDiffLayout.d.ts.map +1 -1
- package/dist/utils/virtualDiffLayout.js +1 -2
- package/dist/utils/virtualDiffLayout.js.map +1 -1
- package/dist/utils/wrapTokenFragments.d.ts +1 -1
- package/dist/utils/wrapTokenFragments.d.ts.map +1 -1
- package/dist/utils/wrapTokenFragments.js +1 -2
- package/dist/utils/wrapTokenFragments.js.map +1 -1
- package/dist/worker/WorkerPoolManager.d.ts +7 -2
- package/dist/worker/WorkerPoolManager.d.ts.map +1 -1
- package/dist/worker/WorkerPoolManager.js +83 -20
- package/dist/worker/WorkerPoolManager.js.map +1 -1
- package/dist/worker/getOrCreateWorkerPoolSingleton.d.ts.map +1 -1
- package/dist/worker/getOrCreateWorkerPoolSingleton.js +1 -2
- package/dist/worker/getOrCreateWorkerPoolSingleton.js.map +1 -1
- package/dist/worker/index.d.ts +2 -2
- package/dist/worker/index.js +1 -2
- package/dist/worker/types.d.ts +7 -1
- package/dist/worker/types.d.ts.map +1 -1
- package/dist/worker/wasm-B9ZqxnKj.js +8 -0
- package/dist/worker/wasm-B9ZqxnKj.js.map +1 -0
- package/dist/worker/worker-portable.js +2784 -6406
- package/dist/worker/worker-portable.js.map +1 -1
- package/dist/worker/worker.js +94 -126
- package/dist/worker/worker.js.map +1 -1
- package/package.json +13 -14
- package/dist/worker/wasm-qE0LgnY3.js +0 -10
- package/dist/worker/wasm-qE0LgnY3.js.map +0 -1
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { computeLineOffsets } from "../utils/computeFileOffsets.js";
|
|
2
|
-
|
|
3
2
|
//#region src/editor/pieceTable.ts
|
|
4
3
|
const MAX_FIND_MATCHES = 1e5;
|
|
5
4
|
const WORD_SEPARATORS = "`~!@#$%^&*()-=+[{]}\\|;:'\",.<>/?";
|
|
6
5
|
var Piece = class {
|
|
6
|
+
source;
|
|
7
|
+
offset;
|
|
8
|
+
length;
|
|
9
|
+
lineOffsetStart;
|
|
10
|
+
lineOffsetEnd;
|
|
7
11
|
static Original = 0;
|
|
8
12
|
static Added = 1;
|
|
9
13
|
constructor(source, offset, length, lineOffsetStart, lineOffsetEnd) {
|
|
@@ -18,6 +22,7 @@ var Piece = class {
|
|
|
18
22
|
}
|
|
19
23
|
};
|
|
20
24
|
var TextBuffer = class {
|
|
25
|
+
text;
|
|
21
26
|
lineOffsets;
|
|
22
27
|
constructor(text) {
|
|
23
28
|
this.text = text;
|
|
@@ -32,9 +37,13 @@ var TextBuffer = class {
|
|
|
32
37
|
}
|
|
33
38
|
};
|
|
34
39
|
var PieceNode = class {
|
|
40
|
+
piece;
|
|
41
|
+
subtreeLength;
|
|
42
|
+
subtreeLineBreakCount;
|
|
35
43
|
left = null;
|
|
36
44
|
right = null;
|
|
37
45
|
parent = null;
|
|
46
|
+
priority = 0;
|
|
38
47
|
constructor(piece, subtreeLength = piece.length, subtreeLineBreakCount = piece.lineBreakCount) {
|
|
39
48
|
this.piece = piece;
|
|
40
49
|
this.subtreeLength = subtreeLength;
|
|
@@ -48,21 +57,27 @@ var PieceNode = class {
|
|
|
48
57
|
/**
|
|
49
58
|
* A piece table is a data structure that allows for efficient insertion and deletion of text.
|
|
50
59
|
* It is a tree of pieces, where each piece is a segment of text that is either original or added.
|
|
51
|
-
* The tree is
|
|
60
|
+
* The tree is a treap (a binary search tree that also keeps each node's random priority in heap
|
|
61
|
+
* order, which keeps the tree balanced without an explicit rebalancing pass). Each edit reshapes
|
|
62
|
+
* only the nodes along one root-to-leaf path via split and merge in O(log P), instead of
|
|
63
|
+
* rebuilding all P pieces.
|
|
52
64
|
* Inspired by https://code.visualstudio.com/blogs/2018/03/23/text-buffer-reimplementation
|
|
53
65
|
*/
|
|
54
66
|
var PieceTable = class {
|
|
55
67
|
#original;
|
|
56
68
|
#add = new TextBuffer("");
|
|
57
69
|
#root = null;
|
|
58
|
-
#piecesCache = [];
|
|
59
70
|
#length = 0;
|
|
60
71
|
#lineCount = 0;
|
|
61
72
|
#lastVisitedLine = null;
|
|
62
73
|
#lastVisitedLineLength = null;
|
|
74
|
+
#priorityState = 2654435769;
|
|
63
75
|
constructor(originalText) {
|
|
64
76
|
this.#original = new TextBuffer(originalText);
|
|
65
|
-
this.#
|
|
77
|
+
const piece = this.#createPiece(Piece.Original, 0, originalText.length);
|
|
78
|
+
this.#root = piece.length > 0 ? this.#createNode(piece) : null;
|
|
79
|
+
this.#length = this.#root?.subtreeLength ?? 0;
|
|
80
|
+
this.#lineCount = (this.#root?.subtreeLineBreakCount ?? 0) + 1;
|
|
66
81
|
}
|
|
67
82
|
get lineCount() {
|
|
68
83
|
return this.#lineCount;
|
|
@@ -95,13 +110,13 @@ var PieceTable = class {
|
|
|
95
110
|
const lastVisitedLine = this.#lastVisitedLine;
|
|
96
111
|
if (lastVisitedLineLength !== null && lastVisitedLineLength[0] === line && lastVisitedLineLength[1] === includeLineBreak) return lastVisitedLineLength[2];
|
|
97
112
|
if (lastVisitedLine !== null && lastVisitedLine[0] === line && lastVisitedLine[1] === includeLineBreak) {
|
|
98
|
-
const length
|
|
113
|
+
const length = lastVisitedLine[2].length;
|
|
99
114
|
this.#lastVisitedLineLength = [
|
|
100
115
|
line,
|
|
101
116
|
includeLineBreak,
|
|
102
|
-
length
|
|
117
|
+
length
|
|
103
118
|
];
|
|
104
|
-
return length
|
|
119
|
+
return length;
|
|
105
120
|
}
|
|
106
121
|
const offset = this.#getLineOffset(line);
|
|
107
122
|
if (offset === void 0) throw new Error(`Line index out of range: ${line}`);
|
|
@@ -128,10 +143,10 @@ var PieceTable = class {
|
|
|
128
143
|
while (node !== null && remaining > 0) {
|
|
129
144
|
const takeLength = Math.min(node.piece.length - offsetInPiece, remaining);
|
|
130
145
|
const buffer = this.#bufferFor(node.piece.source);
|
|
131
|
-
const start
|
|
132
|
-
let end
|
|
133
|
-
if (trimEOF) while (end
|
|
134
|
-
chunks.push(buffer.text.slice(start
|
|
146
|
+
const start = node.piece.offset + offsetInPiece;
|
|
147
|
+
let end = start + takeLength;
|
|
148
|
+
if (trimEOF) while (end > start && isEOL(buffer.text.charCodeAt(end - 1))) end--;
|
|
149
|
+
chunks.push(buffer.text.slice(start, end));
|
|
135
150
|
remaining -= takeLength;
|
|
136
151
|
offsetInPiece = 0;
|
|
137
152
|
node = this.#nextNode(node);
|
|
@@ -215,14 +230,13 @@ var PieceTable = class {
|
|
|
215
230
|
line,
|
|
216
231
|
character: 0
|
|
217
232
|
});
|
|
218
|
-
|
|
219
|
-
re.lastIndex = 0;
|
|
233
|
+
pattern.lastIndex = 0;
|
|
220
234
|
let match;
|
|
221
|
-
while ((match =
|
|
235
|
+
while ((match = pattern.exec(lineText)) !== null) {
|
|
222
236
|
const rel = match.index;
|
|
223
237
|
const fragment = match[0];
|
|
224
238
|
if (fragment.length === 0) {
|
|
225
|
-
|
|
239
|
+
pattern.lastIndex = advancePastEmptyMatch(lineText, rel);
|
|
226
240
|
continue;
|
|
227
241
|
}
|
|
228
242
|
const docStart = lineStart + rel;
|
|
@@ -230,99 +244,31 @@ var PieceTable = class {
|
|
|
230
244
|
out.push([docStart, docStart + fragment.length]);
|
|
231
245
|
if (out.length >= limit) return out;
|
|
232
246
|
}
|
|
233
|
-
if (rel ===
|
|
247
|
+
if (rel === pattern.lastIndex) pattern.lastIndex = advancePastEmptyMatch(lineText, rel);
|
|
234
248
|
}
|
|
235
249
|
}
|
|
236
250
|
return out;
|
|
237
251
|
}
|
|
238
252
|
insert(text, offset) {
|
|
239
253
|
if (text.length === 0) return;
|
|
240
|
-
const
|
|
241
|
-
|
|
242
|
-
const insertedPiece = this.#createPiece(Piece.Added, addOffset, text.length);
|
|
243
|
-
const pieces = this.#pieces();
|
|
244
|
-
const nextPieces = [];
|
|
245
|
-
let cursor = 0;
|
|
246
|
-
let inserted = false;
|
|
247
|
-
for (const piece of pieces) {
|
|
248
|
-
const pieceEnd = cursor + piece.length;
|
|
249
|
-
if (!inserted && insertOffset <= pieceEnd) {
|
|
250
|
-
const splitOffset = insertOffset - cursor;
|
|
251
|
-
if (splitOffset > 0) nextPieces.push(this.#createPiece(piece.source, piece.offset, splitOffset));
|
|
252
|
-
nextPieces.push(insertedPiece);
|
|
253
|
-
if (splitOffset < piece.length) nextPieces.push(this.#createPiece(piece.source, piece.offset + splitOffset, piece.length - splitOffset));
|
|
254
|
-
inserted = true;
|
|
255
|
-
} else nextPieces.push(piece);
|
|
256
|
-
cursor = pieceEnd;
|
|
257
|
-
}
|
|
258
|
-
if (!inserted) nextPieces.push(insertedPiece);
|
|
259
|
-
this.#setPieces(nextPieces);
|
|
260
|
-
this.#lastVisitedLine = null;
|
|
261
|
-
this.#lastVisitedLineLength = null;
|
|
254
|
+
const start = clamp(offset, 0, this.#length);
|
|
255
|
+
this.#replaceRangeIncremental(start, start, text);
|
|
262
256
|
}
|
|
263
257
|
delete(offset, length) {
|
|
264
258
|
if (length <= 0 || this.#length === 0) return;
|
|
265
259
|
const start = clamp(offset, 0, this.#length);
|
|
266
260
|
const end = clamp(start + length, start, this.#length);
|
|
267
261
|
if (start === end) return;
|
|
268
|
-
|
|
269
|
-
let cursor = 0;
|
|
270
|
-
for (const piece of this.#pieces()) {
|
|
271
|
-
const pieceStart = cursor;
|
|
272
|
-
const pieceEnd = cursor + piece.length;
|
|
273
|
-
const keepBefore = clamp(start - pieceStart, 0, piece.length);
|
|
274
|
-
const keepAfter = clamp(pieceEnd - end, 0, piece.length);
|
|
275
|
-
if (keepBefore > 0) nextPieces.push(this.#createPiece(piece.source, piece.offset, keepBefore));
|
|
276
|
-
if (keepAfter > 0) nextPieces.push(this.#createPiece(piece.source, piece.offset + piece.length - keepAfter, keepAfter));
|
|
277
|
-
cursor = pieceEnd;
|
|
278
|
-
}
|
|
279
|
-
this.#setPieces(nextPieces);
|
|
280
|
-
this.#lastVisitedLine = null;
|
|
281
|
-
this.#lastVisitedLineLength = null;
|
|
262
|
+
this.#replaceRangeIncremental(start, end, "");
|
|
282
263
|
}
|
|
283
264
|
applyEdits(edits) {
|
|
284
265
|
if (edits.length === 0) return;
|
|
285
|
-
let
|
|
286
|
-
let pieceStart = 0;
|
|
287
|
-
let copyCursor = 0;
|
|
288
|
-
const pieces = this.#pieces();
|
|
289
|
-
const insertedPieces = edits.map((edit) => edit.text.length === 0 ? void 0 : this.#createPiece(Piece.Added, this.#add.append(edit.text), edit.text.length));
|
|
290
|
-
const nextPieces = [];
|
|
291
|
-
const advancePiece = () => {
|
|
292
|
-
const piece = pieces[pieceIndex];
|
|
293
|
-
if (piece !== void 0) {
|
|
294
|
-
pieceStart += piece.length;
|
|
295
|
-
pieceIndex++;
|
|
296
|
-
}
|
|
297
|
-
};
|
|
298
|
-
const appendRange = (start, end) => {
|
|
299
|
-
let rangeStart = clamp(start, 0, this.#length);
|
|
300
|
-
const rangeEnd = clamp(end, rangeStart, this.#length);
|
|
301
|
-
while (pieceIndex < pieces.length && pieceStart + pieces[pieceIndex].length <= rangeStart) advancePiece();
|
|
302
|
-
while (pieceIndex < pieces.length && rangeStart < rangeEnd) {
|
|
303
|
-
const piece = pieces[pieceIndex];
|
|
304
|
-
const pieceEnd = pieceStart + piece.length;
|
|
305
|
-
const offsetInPiece = clamp(rangeStart - pieceStart, 0, piece.length);
|
|
306
|
-
const takeEnd = Math.min(pieceEnd, rangeEnd);
|
|
307
|
-
const takeLength = takeEnd - (pieceStart + offsetInPiece);
|
|
308
|
-
if (takeLength > 0) nextPieces.push(offsetInPiece === 0 && takeLength === piece.length ? piece : this.#createPiece(piece.source, piece.offset + offsetInPiece, takeLength));
|
|
309
|
-
rangeStart = takeEnd;
|
|
310
|
-
if (rangeStart >= pieceEnd) advancePiece();
|
|
311
|
-
}
|
|
312
|
-
};
|
|
313
|
-
for (let i = 0; i < edits.length; i++) {
|
|
266
|
+
for (let i = edits.length - 1; i >= 0; i--) {
|
|
314
267
|
const edit = edits[i];
|
|
315
|
-
const start = clamp(edit.start,
|
|
268
|
+
const start = clamp(edit.start, 0, this.#length);
|
|
316
269
|
const end = clamp(edit.end, start, this.#length);
|
|
317
|
-
|
|
318
|
-
const insertedPiece = insertedPieces[i];
|
|
319
|
-
if (insertedPiece !== void 0) nextPieces.push(insertedPiece);
|
|
320
|
-
copyCursor = end;
|
|
270
|
+
this.#replaceRangeIncremental(start, end, edit.text);
|
|
321
271
|
}
|
|
322
|
-
appendRange(copyCursor, this.#length);
|
|
323
|
-
this.#setPieces(nextPieces);
|
|
324
|
-
this.#lastVisitedLine = null;
|
|
325
|
-
this.#lastVisitedLineLength = null;
|
|
326
272
|
}
|
|
327
273
|
positionAt(offset) {
|
|
328
274
|
const clampedOffset = clamp(offset, 0, this.#length);
|
|
@@ -462,32 +408,104 @@ var PieceTable = class {
|
|
|
462
408
|
const buffer = this.#bufferFor(source);
|
|
463
409
|
return new Piece(source, offset, length, upperBound(buffer.lineOffsets, offset), upperBound(buffer.lineOffsets, offset + length));
|
|
464
410
|
}
|
|
465
|
-
#
|
|
466
|
-
return
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
411
|
+
#replaceRangeIncremental(start, end, text) {
|
|
412
|
+
if (start === end && text.length === 0) return;
|
|
413
|
+
const [left, rest] = this.#split(this.#root, start);
|
|
414
|
+
const [, right] = this.#split(rest, end - start);
|
|
415
|
+
let root;
|
|
416
|
+
if (text.length > 0) {
|
|
417
|
+
const insertedPiece = this.#createPiece(Piece.Added, this.#add.append(text), text.length);
|
|
418
|
+
root = this.#mergeNodes(this.#appendCoalescing(left, insertedPiece), right);
|
|
419
|
+
} else {
|
|
420
|
+
const [seamPiece, restRight] = this.#popLeftmost(right);
|
|
421
|
+
root = seamPiece === void 0 ? left : this.#mergeNodes(this.#appendCoalescing(left, seamPiece), restRight);
|
|
476
422
|
}
|
|
477
|
-
|
|
478
|
-
this.#
|
|
479
|
-
this.#
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
423
|
+
if (root !== null) root.parent = null;
|
|
424
|
+
this.#root = root;
|
|
425
|
+
this.#length = root?.subtreeLength ?? 0;
|
|
426
|
+
this.#lineCount = (root?.subtreeLineBreakCount ?? 0) + 1;
|
|
427
|
+
this.#lastVisitedLine = null;
|
|
428
|
+
this.#lastVisitedLineLength = null;
|
|
429
|
+
}
|
|
430
|
+
#nextPriority() {
|
|
431
|
+
this.#priorityState = Math.imul(this.#priorityState, 1664525) + 1013904223 >>> 0;
|
|
432
|
+
return this.#priorityState;
|
|
433
|
+
}
|
|
434
|
+
#createNode(piece) {
|
|
435
|
+
const node = new PieceNode(piece);
|
|
436
|
+
node.priority = this.#nextPriority();
|
|
489
437
|
return node;
|
|
490
438
|
}
|
|
439
|
+
#setLeft(node, child) {
|
|
440
|
+
node.left = child;
|
|
441
|
+
if (child !== null) child.parent = node;
|
|
442
|
+
}
|
|
443
|
+
#setRight(node, child) {
|
|
444
|
+
node.right = child;
|
|
445
|
+
if (child !== null) child.parent = node;
|
|
446
|
+
}
|
|
447
|
+
#split(node, offset) {
|
|
448
|
+
if (node === null) return [null, null];
|
|
449
|
+
const leftLength = node.left?.subtreeLength ?? 0;
|
|
450
|
+
if (offset <= leftLength) {
|
|
451
|
+
const [left, right] = this.#split(node.left, offset);
|
|
452
|
+
this.#setLeft(node, right);
|
|
453
|
+
node.updateSubtreeLength();
|
|
454
|
+
return [left, node];
|
|
455
|
+
}
|
|
456
|
+
const pieceLength = node.piece.length;
|
|
457
|
+
if (offset >= leftLength + pieceLength) {
|
|
458
|
+
const [left, right] = this.#split(node.right, offset - leftLength - pieceLength);
|
|
459
|
+
this.#setRight(node, left);
|
|
460
|
+
node.updateSubtreeLength();
|
|
461
|
+
return [node, right];
|
|
462
|
+
}
|
|
463
|
+
const inPiece = offset - leftLength;
|
|
464
|
+
const leftNode = new PieceNode(this.#createPiece(node.piece.source, node.piece.offset, inPiece));
|
|
465
|
+
const rightNode = new PieceNode(this.#createPiece(node.piece.source, node.piece.offset + inPiece, pieceLength - inPiece));
|
|
466
|
+
leftNode.priority = node.priority;
|
|
467
|
+
rightNode.priority = node.priority;
|
|
468
|
+
this.#setLeft(leftNode, node.left);
|
|
469
|
+
this.#setRight(rightNode, node.right);
|
|
470
|
+
leftNode.updateSubtreeLength();
|
|
471
|
+
rightNode.updateSubtreeLength();
|
|
472
|
+
return [leftNode, rightNode];
|
|
473
|
+
}
|
|
474
|
+
#mergeNodes(left, right) {
|
|
475
|
+
if (left === null) return right;
|
|
476
|
+
if (right === null) return left;
|
|
477
|
+
if (left.priority >= right.priority) {
|
|
478
|
+
this.#setRight(left, this.#mergeNodes(left.right, right));
|
|
479
|
+
left.updateSubtreeLength();
|
|
480
|
+
return left;
|
|
481
|
+
}
|
|
482
|
+
this.#setLeft(right, this.#mergeNodes(left, right.left));
|
|
483
|
+
right.updateSubtreeLength();
|
|
484
|
+
return right;
|
|
485
|
+
}
|
|
486
|
+
#appendCoalescing(tree, piece) {
|
|
487
|
+
if (tree === null) return this.#createNode(piece);
|
|
488
|
+
let last = tree;
|
|
489
|
+
while (last.right !== null) last = last.right;
|
|
490
|
+
if (canCoalescePieces(last.piece, piece)) {
|
|
491
|
+
last.piece = coalesceTwoPieces(last.piece, piece);
|
|
492
|
+
for (let node = last; node !== null;) {
|
|
493
|
+
node.updateSubtreeLength();
|
|
494
|
+
if (node === tree) break;
|
|
495
|
+
node = node.parent;
|
|
496
|
+
}
|
|
497
|
+
return tree;
|
|
498
|
+
}
|
|
499
|
+
return this.#mergeNodes(tree, this.#createNode(piece));
|
|
500
|
+
}
|
|
501
|
+
#popLeftmost(tree) {
|
|
502
|
+
if (tree === null) return [void 0, null];
|
|
503
|
+
if (tree.left === null) return [tree.piece, tree.right];
|
|
504
|
+
const [piece, newLeft] = this.#popLeftmost(tree.left);
|
|
505
|
+
this.#setLeft(tree, newLeft);
|
|
506
|
+
tree.updateSubtreeLength();
|
|
507
|
+
return [piece, tree];
|
|
508
|
+
}
|
|
491
509
|
#walk(node, visit) {
|
|
492
510
|
if (node === null) return true;
|
|
493
511
|
if (!this.#walk(node.left, visit)) return false;
|
|
@@ -542,18 +560,11 @@ function rangeOverlaps(ranges, start, end) {
|
|
|
542
560
|
const range = ranges[low];
|
|
543
561
|
return range !== void 0 && range[0] < end;
|
|
544
562
|
}
|
|
545
|
-
function
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
if (previous !== void 0 && previous.source === piece.source && previous.offset + previous.length === piece.offset) {
|
|
551
|
-
coalescedPieces[coalescedPieces.length - 1] = new Piece(previous.source, previous.offset, previous.length + piece.length, previous.lineOffsetStart, piece.lineOffsetEnd);
|
|
552
|
-
continue;
|
|
553
|
-
}
|
|
554
|
-
coalescedPieces.push(piece);
|
|
555
|
-
}
|
|
556
|
-
return coalescedPieces;
|
|
563
|
+
function canCoalescePieces(prev, next) {
|
|
564
|
+
return prev.source === next.source && prev.offset + prev.length === next.offset;
|
|
565
|
+
}
|
|
566
|
+
function coalesceTwoPieces(prev, next) {
|
|
567
|
+
return new Piece(prev.source, prev.offset, prev.length + next.length, prev.lineOffsetStart, next.lineOffsetEnd);
|
|
557
568
|
}
|
|
558
569
|
function upperBound(values, target) {
|
|
559
570
|
let lo = 0;
|
|
@@ -584,8 +595,7 @@ function charCodeUnitAt(charAt, offset) {
|
|
|
584
595
|
}
|
|
585
596
|
function compileSearchRegExp(source, isRegex, caseSensitive) {
|
|
586
597
|
const body = isRegex ? source : escapeRegExp(source);
|
|
587
|
-
|
|
588
|
-
return new RegExp(body, flags);
|
|
598
|
+
return new RegExp(body, `g${caseSensitive ? "" : "i"}${isRegex ? "m" : ""}`);
|
|
589
599
|
}
|
|
590
600
|
/** Expands `$&`, `$1`, `$$`, etc. in a regex replace string using a match. */
|
|
591
601
|
function expandReplaceString(replacement, match) {
|
|
@@ -626,7 +636,7 @@ function advancePastEmptyMatch(text, index) {
|
|
|
626
636
|
}
|
|
627
637
|
return index + 1;
|
|
628
638
|
}
|
|
629
|
-
|
|
630
639
|
//#endregion
|
|
631
640
|
export { PieceTable, buildSearchReplacementText };
|
|
641
|
+
|
|
632
642
|
//# sourceMappingURL=pieceTable.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pieceTable.js","names":["source: number","offset: number","length: number","lineOffsetStart: number","lineOffsetEnd: number","text: string","piece: Piece","subtreeLength: number","subtreeLineBreakCount: number","#original","#setPieces","#createPiece","#lineCount","#textFromPieces","#lastVisitedLine","#getLineOffset","#lastVisitedLineLength","length","#length","#findPieceAtOffset","chunks: string[]","#bufferFor","start","end","#nextNode","#forEachPieceSegment","wrappedOffset: number | undefined","foundOffset: number | undefined","pattern: RegExp","#collectSearchMatchesLineByLine","out: [number, number][]","match: RegExpExecArray | null","#add","#pieces","nextPieces: Piece[]","#lineAtOffset","#lineBreakOffset","positions: Position[]","#root","#walk","#piecesCache","#buildBalancedTree","normalized: [start: number, end: number][]","merged: [start: number, end: number][]","coalescedPieces: Piece[]"],"sources":["../../src/editor/pieceTable.ts"],"sourcesContent":["import { computeLineOffsets } from '../utils/computeFileOffsets';\nimport type { SearchParams } from './searchPanel';\nimport type { Position, Range, ResolvedTextEdit } from './textDocument';\n\nconst MAX_FIND_MATCHES = 100000;\n// TODO(ije): use Intl.Segmenter instead of regex for word separators\nconst WORD_SEPARATORS = '`~!@#$%^&*()-=+[{]}\\\\|;:\\'\",.<>/?' as const;\n\n// A piece is a segment of text that is either original or added.\nclass Piece {\n static Original = 0;\n static Added = 1;\n\n constructor(\n public readonly source: number,\n public readonly offset: number,\n public readonly length: number,\n public readonly lineOffsetStart: number,\n public readonly lineOffsetEnd: number\n ) {}\n\n get lineBreakCount(): number {\n return this.lineOffsetEnd - this.lineOffsetStart;\n }\n}\n\n// A text buffer is a string with its line offsets.\nclass TextBuffer {\n lineOffsets: number[];\n\n constructor(public text: string) {\n this.lineOffsets = computeLineOffsets(text);\n }\n\n // the append operation is efficient because it only appends\n // elements to the lineOffsets array in the end\n append(text: string): number {\n const offset = this.text.length;\n const appendedLineOffsets = computeLineOffsets(text);\n for (let i = 1; i < appendedLineOffsets.length; i++) {\n this.lineOffsets.push(offset + appendedLineOffsets[i]);\n }\n this.text += text;\n return offset;\n }\n}\n\n// A node in the balanced piece tree.\nclass PieceNode {\n left: PieceNode | null = null;\n right: PieceNode | null = null;\n parent: PieceNode | null = null;\n\n constructor(\n public piece: Piece,\n public subtreeLength: number = piece.length,\n public subtreeLineBreakCount: number = piece.lineBreakCount\n ) {}\n\n updateSubtreeLength(): void {\n this.subtreeLength =\n (this.left?.subtreeLength ?? 0) +\n this.piece.length +\n (this.right?.subtreeLength ?? 0);\n this.subtreeLineBreakCount =\n (this.left?.subtreeLineBreakCount ?? 0) +\n this.piece.lineBreakCount +\n (this.right?.subtreeLineBreakCount ?? 0);\n }\n}\n\n/**\n * A piece table is a data structure that allows for efficient insertion and deletion of text.\n * It is a tree of pieces, where each piece is a segment of text that is either original or added.\n * The tree is rebuilt as a balanced tree after edits to keep lookups efficient.\n * Inspired by https://code.visualstudio.com/blogs/2018/03/23/text-buffer-reimplementation\n */\nexport class PieceTable {\n #original: TextBuffer;\n #add = new TextBuffer('');\n #root: PieceNode | null = null;\n #piecesCache: Piece[] = [];\n #length = 0;\n #lineCount = 0;\n #lastVisitedLine: [number, boolean, string] | null = null;\n #lastVisitedLineLength: [number, boolean, number] | null = null;\n\n constructor(originalText: string) {\n this.#original = new TextBuffer(originalText);\n this.#setPieces([\n this.#createPiece(Piece.Original, 0, originalText.length),\n ]);\n }\n\n get lineCount(): number {\n return this.#lineCount;\n }\n\n getText(range?: Range): string {\n if (range === undefined) {\n return this.#textFromPieces();\n }\n const start = this.offsetAt(range.start);\n const end = this.offsetAt(range.end);\n return this.getTextSlice(start, end);\n }\n\n getLineText(line: number, includeLineBreak = false): string {\n if (\n this.#lastVisitedLine !== null &&\n this.#lastVisitedLine[0] === line &&\n this.#lastVisitedLine[1] === includeLineBreak\n ) {\n return this.#lastVisitedLine[2];\n }\n const offset = this.#getLineOffset(line);\n if (offset === undefined) {\n throw new Error(`Line index out of range: ${line}`);\n }\n const text = this.getTextSlice(offset[0], offset[1], !includeLineBreak);\n this.#lastVisitedLine = [line, includeLineBreak, text];\n this.#lastVisitedLineLength = [line, includeLineBreak, text.length];\n return text;\n }\n\n getLineLength(line: number, includeLineBreak = false): number {\n const lastVisitedLineLength = this.#lastVisitedLineLength;\n const lastVisitedLine = this.#lastVisitedLine;\n if (\n lastVisitedLineLength !== null &&\n lastVisitedLineLength[0] === line &&\n lastVisitedLineLength[1] === includeLineBreak\n ) {\n return lastVisitedLineLength[2];\n }\n if (\n lastVisitedLine !== null &&\n lastVisitedLine[0] === line &&\n lastVisitedLine[1] === includeLineBreak\n ) {\n const length = lastVisitedLine[2].length;\n this.#lastVisitedLineLength = [line, includeLineBreak, length];\n return length;\n }\n const offset = this.#getLineOffset(line);\n if (offset === undefined) {\n throw new Error(`Line index out of range: ${line}`);\n }\n const [start, end] = offset;\n let length = end - start;\n if (!includeLineBreak) {\n while (\n length > 0 &&\n isEOL(this.charAt(start + length - 1).charCodeAt(0))\n ) {\n length--;\n }\n }\n this.#lastVisitedLineLength = [line, includeLineBreak, length];\n return length;\n }\n\n getTextSlice(start: number, end: number, trimEOF = false): string {\n if (start >= end) {\n return '';\n }\n\n const sliceStart = clamp(start, 0, this.#length);\n const sliceEnd = clamp(end, sliceStart, this.#length);\n if (sliceStart >= sliceEnd) {\n return '';\n }\n\n const location = this.#findPieceAtOffset(sliceStart);\n if (location === undefined) {\n return '';\n }\n\n const chunks: string[] = [];\n let [node, offsetInPiece] = location as [PieceNode | null, number];\n let remaining = sliceEnd - sliceStart;\n while (node !== null && remaining > 0) {\n const takeLength = Math.min(node.piece.length - offsetInPiece, remaining);\n const buffer = this.#bufferFor(node.piece.source);\n const start = node.piece.offset + offsetInPiece;\n let end = start + takeLength;\n if (trimEOF) {\n while (end > start && isEOL(buffer.text.charCodeAt(end - 1))) {\n end--;\n }\n }\n chunks.push(buffer.text.slice(start, end));\n remaining -= takeLength;\n offsetInPiece = 0;\n node = this.#nextNode(node);\n }\n\n return chunks.join('');\n }\n\n charAt(offset: number): string {\n const location = this.#findPieceAtOffset(offset);\n if (location === undefined) {\n return '';\n }\n\n const [node, offsetInPiece] = location;\n const buffer = this.#bufferFor(node.piece.source);\n return buffer.text.charAt(node.piece.offset + offsetInPiece);\n }\n\n includes(needle: string): boolean {\n if (needle.length === 0) {\n return true;\n }\n\n const prefixTable = createPrefixTable(needle);\n let matched = 0;\n let found = false;\n this.#forEachPieceSegment((segment) => {\n for (let offset = segment.start; offset < segment.end; offset++) {\n const charCode = segment.text.charCodeAt(offset);\n while (matched > 0 && charCode !== needle.charCodeAt(matched)) {\n matched = prefixTable[matched - 1];\n }\n if (charCode === needle.charCodeAt(matched)) {\n matched++;\n }\n if (matched === needle.length) {\n found = true;\n return false;\n }\n }\n return true;\n });\n return found;\n }\n\n findNextNonOverlappingSubstring(\n needle: string,\n occupied: readonly [start: number, end: number][]\n ): number | undefined {\n if (needle.length === 0 || needle.length > this.#length) {\n return undefined;\n }\n\n const ranges = normalizeRanges(occupied, this.#length);\n const pivot = ranges.reduce((max, [, end]) => Math.max(max, end), 0);\n const prefixTable = createPrefixTable(needle);\n let matched = 0;\n let documentOffset = 0;\n let wrappedOffset: number | undefined;\n let foundOffset: number | undefined;\n\n this.#forEachPieceSegment((segment) => {\n for (let offset = segment.start; offset < segment.end; offset++) {\n const charCode = segment.text.charCodeAt(offset);\n while (matched > 0 && charCode !== needle.charCodeAt(matched)) {\n matched = prefixTable[matched - 1];\n }\n if (charCode === needle.charCodeAt(matched)) {\n matched++;\n }\n if (matched === needle.length) {\n const start = documentOffset - needle.length + 1;\n if (!rangeOverlaps(ranges, start, start + needle.length)) {\n if (start >= pivot) {\n foundOffset = start;\n return false;\n }\n wrappedOffset ??= start;\n }\n matched = prefixTable[matched - 1];\n }\n documentOffset++;\n }\n return true;\n });\n\n return foundOffset ?? wrappedOffset;\n }\n\n search(searchParams: SearchParams): [start: number, end: number][] {\n if (searchParams.text.length === 0 || this.#length === 0) {\n return [];\n }\n\n // Search currently operates line-by-line, so newline-spanning patterns are unsupported.\n if (\n searchParams.text.includes('\\n') ||\n searchParams.text.includes('\\r') ||\n (searchParams.regex &&\n (searchParams.text.includes('\\\\n') ||\n searchParams.text.includes('\\\\r')))\n ) {\n return [];\n }\n\n let pattern: RegExp;\n try {\n pattern = compileSearchRegExp(\n searchParams.text,\n searchParams.regex,\n searchParams.caseSensitive\n );\n } catch {\n return [];\n }\n\n return this.#collectSearchMatchesLineByLine(\n pattern,\n searchParams.wholeWord,\n MAX_FIND_MATCHES\n );\n }\n\n #collectSearchMatchesLineByLine(\n pattern: RegExp,\n wholeWord: boolean,\n limit: number\n ): [number, number][] {\n const out: [number, number][] = [];\n const docLength = this.#length;\n const charAt = (offset: number) => this.charAt(offset);\n\n for (let line = 0; line < this.#lineCount; line++) {\n const lineText = this.getLineText(line);\n const lineStart = this.offsetAt({ line, character: 0 });\n const re = new RegExp(pattern.source, pattern.flags);\n re.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = re.exec(lineText)) !== null) {\n const rel = match.index;\n const fragment = match[0];\n if (fragment.length === 0) {\n re.lastIndex = advancePastEmptyMatch(lineText, rel);\n continue;\n }\n const docStart = lineStart + rel;\n if (\n !wholeWord ||\n isWholeWordAtDocOffsets(docStart, fragment.length, docLength, charAt)\n ) {\n out.push([docStart, docStart + fragment.length]);\n if (out.length >= limit) {\n return out;\n }\n }\n if (rel === re.lastIndex) {\n re.lastIndex = advancePastEmptyMatch(lineText, rel);\n }\n }\n }\n return out;\n }\n\n insert(text: string, offset: number): void {\n if (text.length === 0) {\n return;\n }\n\n const insertOffset = clamp(offset, 0, this.#length);\n const addOffset = this.#add.append(text);\n const insertedPiece = this.#createPiece(\n Piece.Added,\n addOffset,\n text.length\n );\n const pieces = this.#pieces();\n const nextPieces: Piece[] = [];\n\n let cursor = 0;\n let inserted = false;\n\n for (const piece of pieces) {\n const pieceEnd = cursor + piece.length;\n if (!inserted && insertOffset <= pieceEnd) {\n const splitOffset = insertOffset - cursor;\n if (splitOffset > 0) {\n nextPieces.push(\n this.#createPiece(piece.source, piece.offset, splitOffset)\n );\n }\n nextPieces.push(insertedPiece);\n if (splitOffset < piece.length) {\n nextPieces.push(\n this.#createPiece(\n piece.source,\n piece.offset + splitOffset,\n piece.length - splitOffset\n )\n );\n }\n inserted = true;\n } else {\n nextPieces.push(piece);\n }\n cursor = pieceEnd;\n }\n\n if (!inserted) {\n nextPieces.push(insertedPiece);\n }\n\n this.#setPieces(nextPieces);\n this.#lastVisitedLine = null;\n this.#lastVisitedLineLength = null;\n }\n\n delete(offset: number, length: number): void {\n if (length <= 0 || this.#length === 0) {\n return;\n }\n\n const start = clamp(offset, 0, this.#length);\n const end = clamp(start + length, start, this.#length);\n if (start === end) {\n return;\n }\n\n const nextPieces: Piece[] = [];\n let cursor = 0;\n for (const piece of this.#pieces()) {\n const pieceStart = cursor;\n const pieceEnd = cursor + piece.length;\n const keepBefore = clamp(start - pieceStart, 0, piece.length);\n const keepAfter = clamp(pieceEnd - end, 0, piece.length);\n\n if (keepBefore > 0) {\n nextPieces.push(\n this.#createPiece(piece.source, piece.offset, keepBefore)\n );\n }\n if (keepAfter > 0) {\n nextPieces.push(\n this.#createPiece(\n piece.source,\n piece.offset + piece.length - keepAfter,\n keepAfter\n )\n );\n }\n cursor = pieceEnd;\n }\n\n this.#setPieces(nextPieces);\n this.#lastVisitedLine = null;\n this.#lastVisitedLineLength = null;\n }\n\n applyEdits(edits: readonly ResolvedTextEdit[]): void {\n if (edits.length === 0) {\n return;\n }\n\n let pieceIndex = 0;\n let pieceStart = 0;\n let copyCursor = 0;\n\n const pieces = this.#pieces();\n const insertedPieces = edits.map((edit) =>\n edit.text.length === 0\n ? undefined\n : this.#createPiece(\n Piece.Added,\n this.#add.append(edit.text),\n edit.text.length\n )\n );\n const nextPieces: Piece[] = [];\n\n const advancePiece = () => {\n const piece = pieces[pieceIndex];\n if (piece !== undefined) {\n pieceStart += piece.length;\n pieceIndex++;\n }\n };\n\n const appendRange = (start: number, end: number) => {\n let rangeStart = clamp(start, 0, this.#length);\n const rangeEnd = clamp(end, rangeStart, this.#length);\n while (\n pieceIndex < pieces.length &&\n pieceStart + pieces[pieceIndex].length <= rangeStart\n ) {\n advancePiece();\n }\n while (pieceIndex < pieces.length && rangeStart < rangeEnd) {\n const piece = pieces[pieceIndex];\n const pieceEnd = pieceStart + piece.length;\n const offsetInPiece = clamp(rangeStart - pieceStart, 0, piece.length);\n const takeEnd = Math.min(pieceEnd, rangeEnd);\n const takeLength = takeEnd - (pieceStart + offsetInPiece);\n if (takeLength > 0) {\n nextPieces.push(\n offsetInPiece === 0 && takeLength === piece.length\n ? piece\n : this.#createPiece(\n piece.source,\n piece.offset + offsetInPiece,\n takeLength\n )\n );\n }\n rangeStart = takeEnd;\n if (rangeStart >= pieceEnd) {\n advancePiece();\n }\n }\n };\n\n for (let i = 0; i < edits.length; i++) {\n const edit = edits[i];\n const start = clamp(edit.start, copyCursor, this.#length);\n const end = clamp(edit.end, start, this.#length);\n appendRange(copyCursor, start);\n\n const insertedPiece = insertedPieces[i];\n if (insertedPiece !== undefined) {\n nextPieces.push(insertedPiece);\n }\n copyCursor = end;\n }\n appendRange(copyCursor, this.#length);\n\n this.#setPieces(nextPieces);\n this.#lastVisitedLine = null;\n this.#lastVisitedLineLength = null;\n }\n\n positionAt(offset: number): Position {\n const clampedOffset = clamp(offset, 0, this.#length);\n if (this.#length === 0) {\n return { line: 0, character: 0 };\n }\n const line = this.#lineAtOffset(clampedOffset);\n const lineStart = line === 0 ? 0 : this.#lineBreakOffset(line - 1);\n return {\n line,\n character: clampedOffset - lineStart,\n };\n }\n\n positionsAt(offsets: readonly number[]): Position[] {\n const positions: Position[] = Array.from({ length: offsets.length });\n if (offsets.length === 0) {\n return positions;\n }\n if (this.#length === 0) {\n return positions.fill({ line: 0, character: 0 });\n }\n\n for (let i = 0; i < offsets.length; i++) {\n positions[i] = this.positionAt(offsets[i]);\n }\n\n return positions;\n }\n\n offsetAt(position: Position): number {\n if (position.line < 0 || this.#length === 0) {\n return 0;\n }\n if (position.line >= this.#lineCount) {\n throw new Error(`Line index out of range: ${position.line}`);\n }\n const offset = this.#getLineOffset(position.line);\n if (offset === undefined) {\n throw new Error(`Line index out of range: ${position.line}`);\n }\n const character = clamp(position.character, 0, offset[1] - offset[0]);\n return offset[0] + character;\n }\n\n #findPieceAtOffset(\n offset: number\n ): [node: PieceNode, offsetInPiece: number] | undefined {\n if (offset < 0 || offset >= this.#length) {\n return undefined;\n }\n\n let node = this.#root;\n let remaining = offset;\n while (node !== null) {\n const leftLength = node.left?.subtreeLength ?? 0;\n if (remaining < leftLength) {\n node = node.left;\n continue;\n }\n\n remaining -= leftLength;\n if (remaining < node.piece.length) {\n return [node, remaining];\n }\n\n remaining -= node.piece.length;\n node = node.right;\n }\n\n return undefined;\n }\n\n #nextNode(node: PieceNode): PieceNode | null {\n if (node.right !== null) {\n let next = node.right;\n while (next.left !== null) {\n next = next.left;\n }\n return next;\n }\n\n let current = node;\n while (current.parent !== null && current === current.parent.right) {\n current = current.parent;\n }\n return current.parent;\n }\n\n #getLineOffset(line: number): [start: number, end: number] | undefined {\n if (line < 0) {\n throw new Error(`Line index out of range: ${line}`);\n }\n if (this.#length === 0) {\n if (line === 0) {\n return [0, 0];\n }\n throw new Error(`Line index out of range: ${line}`);\n }\n if (line >= this.#lineCount) {\n throw new Error(`Line index out of range: ${line}`);\n }\n\n const start = line === 0 ? 0 : this.#lineBreakOffset(line - 1);\n const end =\n line < this.#lineCount - 1 ? this.#lineBreakOffset(line) : this.#length;\n return [start, end];\n }\n\n #lineAtOffset(offset: number): number {\n let node = this.#root;\n let remaining = clamp(offset, 0, this.#length);\n let line = 0;\n\n while (node !== null) {\n const leftLength = node.left?.subtreeLength ?? 0;\n if (remaining < leftLength) {\n node = node.left;\n continue;\n }\n\n line += node.left?.subtreeLineBreakCount ?? 0;\n remaining -= leftLength;\n if (remaining <= node.piece.length) {\n const buffer = this.#bufferFor(node.piece.source);\n line +=\n upperBound(buffer.lineOffsets, node.piece.offset + remaining) -\n node.piece.lineOffsetStart;\n return line;\n }\n\n line += node.piece.lineBreakCount;\n remaining -= node.piece.length;\n node = node.right;\n }\n\n return this.#lineCount - 1;\n }\n\n #lineBreakOffset(lineBreakIndex: number): number {\n let node = this.#root;\n let remaining = lineBreakIndex;\n let documentOffset = 0;\n\n while (node !== null) {\n const leftLineBreakCount = node.left?.subtreeLineBreakCount ?? 0;\n if (remaining < leftLineBreakCount) {\n node = node.left;\n continue;\n }\n\n const leftLength = node.left?.subtreeLength ?? 0;\n documentOffset += leftLength;\n remaining -= leftLineBreakCount;\n\n if (remaining < node.piece.lineBreakCount) {\n const bufferLineOffset = this.#bufferFor(node.piece.source).lineOffsets[\n node.piece.lineOffsetStart + remaining\n ];\n return documentOffset + (bufferLineOffset - node.piece.offset);\n }\n\n documentOffset += node.piece.length;\n remaining -= node.piece.lineBreakCount;\n node = node.right;\n }\n\n return this.#length;\n }\n\n #textFromPieces(): string {\n const chunks: string[] = [];\n this.#forEachPieceSegment((segment) => {\n chunks.push(segment.text.slice(segment.start, segment.end));\n });\n return chunks.join('');\n }\n\n #forEachPieceSegment(\n callback: (segment: {\n readonly start: number;\n readonly end: number;\n readonly text: string;\n readonly lineOffsets: number[];\n readonly lineOffsetStart: number;\n readonly lineOffsetEnd: number;\n }) => boolean | void\n ): void {\n this.#walk(this.#root, (node) => {\n const buffer = this.#bufferFor(node.piece.source);\n return callback({\n text: buffer.text,\n lineOffsets: buffer.lineOffsets,\n lineOffsetStart: node.piece.lineOffsetStart,\n lineOffsetEnd: node.piece.lineOffsetEnd,\n start: node.piece.offset,\n end: node.piece.offset + node.piece.length,\n });\n });\n }\n\n #bufferFor(source: number): TextBuffer {\n return source === Piece.Original ? this.#original : this.#add;\n }\n\n #createPiece(source: number, offset: number, length: number): Piece {\n const buffer = this.#bufferFor(source);\n return new Piece(\n source,\n offset,\n length,\n upperBound(buffer.lineOffsets, offset),\n upperBound(buffer.lineOffsets, offset + length)\n );\n }\n\n #pieces(): Piece[] {\n return this.#piecesCache;\n }\n\n #setPieces(pieces: Piece[]): void {\n const coalescedPieces = coalescePieces(pieces);\n this.#piecesCache = coalescedPieces;\n let length = 0;\n let lineBreakCount = 0;\n for (const piece of coalescedPieces) {\n length += piece.length;\n lineBreakCount += piece.lineBreakCount;\n }\n this.#root = this.#buildBalancedTree(\n coalescedPieces,\n 0,\n coalescedPieces.length,\n null\n );\n this.#length = length;\n this.#lineCount = lineBreakCount + 1;\n }\n\n #buildBalancedTree(\n pieces: Piece[],\n start: number,\n end: number,\n parent: PieceNode | null\n ): PieceNode | null {\n if (start >= end) {\n return null;\n }\n\n const middle = start + Math.floor((end - start) / 2);\n const node = new PieceNode(pieces[middle]);\n node.parent = parent;\n node.left = this.#buildBalancedTree(pieces, start, middle, node);\n node.right = this.#buildBalancedTree(pieces, middle + 1, end, node);\n node.updateSubtreeLength();\n return node;\n }\n\n #walk(\n node: PieceNode | null,\n visit: (node: PieceNode) => boolean | void\n ): boolean {\n if (node === null) {\n return true;\n }\n if (!this.#walk(node.left, visit)) {\n return false;\n }\n if (visit(node) === false) {\n return false;\n }\n return this.#walk(node.right, visit);\n }\n}\n\nfunction isEOL(charCode: number): boolean {\n return charCode === /* \\n */ 10 || charCode === /* \\r */ 13;\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\nfunction createPrefixTable(text: string): number[] {\n const table = Array.from<number>({ length: text.length }).fill(0);\n let matched = 0;\n for (let i = 1; i < text.length; i++) {\n const charCode = text.charCodeAt(i);\n while (matched > 0 && charCode !== text.charCodeAt(matched)) {\n matched = table[matched - 1];\n }\n if (charCode === text.charCodeAt(matched)) {\n matched++;\n }\n table[i] = matched;\n }\n return table;\n}\n\nfunction normalizeRanges(\n ranges: readonly [start: number, end: number][],\n length: number\n): [start: number, end: number][] {\n const normalized: [start: number, end: number][] = [];\n for (const [rawStart, rawEnd] of ranges) {\n const start = clamp(rawStart, 0, length);\n const end = clamp(rawEnd, start, length);\n if (start < end) {\n normalized.push([start, end]);\n }\n }\n normalized.sort((a, b) => a[0] - b[0]);\n\n const merged: [start: number, end: number][] = [];\n for (const range of normalized) {\n const previous = merged[merged.length - 1];\n if (previous !== undefined && range[0] <= previous[1]) {\n previous[1] = Math.max(previous[1], range[1]);\n continue;\n }\n merged.push(range);\n }\n return merged;\n}\n\nfunction rangeOverlaps(\n ranges: readonly [start: number, end: number][],\n start: number,\n end: number\n): boolean {\n let low = 0;\n let high = ranges.length;\n while (low < high) {\n const mid = low + Math.floor((high - low) / 2);\n if (ranges[mid][1] <= start) {\n low = mid + 1;\n } else {\n high = mid;\n }\n }\n\n const range = ranges[low];\n return range !== undefined && range[0] < end;\n}\n\n// Keeps the table compact after repeated edits by joining neighboring pieces\n// that already point at contiguous text in the same backing buffer.\nfunction coalescePieces(pieces: Piece[]): Piece[] {\n const coalescedPieces: Piece[] = [];\n for (const piece of pieces) {\n if (piece.length === 0) {\n continue;\n }\n\n const previous = coalescedPieces[coalescedPieces.length - 1];\n if (\n previous !== undefined &&\n previous.source === piece.source &&\n previous.offset + previous.length === piece.offset\n ) {\n coalescedPieces[coalescedPieces.length - 1] = new Piece(\n previous.source,\n previous.offset,\n previous.length + piece.length,\n previous.lineOffsetStart,\n piece.lineOffsetEnd\n );\n continue;\n }\n\n coalescedPieces.push(piece);\n }\n return coalescedPieces;\n}\n\n// Returns the index of the first element in the array that is greater than the target.\nfunction upperBound(values: number[], target: number): number {\n let lo = 0;\n let hi = values.length;\n while (lo < hi) {\n const mid = lo + Math.floor((hi - lo) / 2);\n if (values[mid] <= target) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n return lo;\n}\n\nfunction escapeRegExp(text: string): string {\n return text.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction isWordSeparatorCharCode(charCode: number): boolean {\n if (charCode <= 32 || charCode === 127) {\n return true;\n }\n const ch = String.fromCharCode(charCode);\n return WORD_SEPARATORS.includes(ch);\n}\n\n// Checks if the given text is a whole word by checking if the\n// characters before and after are word separators.\nfunction isWholeWordAtDocOffsets(\n docStart: number,\n length: number,\n docLength: number,\n charAt: (offset: number) => string\n): boolean {\n const beforeOk =\n docStart <= 0 ||\n isWordSeparatorCharCode(charCodeUnitAt(charAt, docStart - 1));\n const afterOk =\n docStart + length >= docLength ||\n isWordSeparatorCharCode(charCodeUnitAt(charAt, docStart + length));\n return beforeOk && afterOk;\n}\n\nfunction charCodeUnitAt(\n charAt: (offset: number) => string,\n offset: number\n): number {\n const unit = charAt(offset);\n return unit.length === 0 ? 0 : unit.charCodeAt(0);\n}\n\nfunction compileSearchRegExp(\n source: string,\n isRegex: boolean,\n caseSensitive: boolean\n): RegExp {\n const body = isRegex ? source : escapeRegExp(source);\n const flags = `g${caseSensitive ? '' : 'i'}${isRegex ? 'm' : ''}`;\n return new RegExp(body, flags);\n}\n\n/** Expands `$&`, `$1`, `$$`, etc. in a regex replace string using a match. */\nfunction expandReplaceString(\n replacement: string,\n match: RegExpExecArray\n): string {\n return replacement.replace(/\\$([$&]|\\d+)/g, (_token, group: string) => {\n if (group === '$') {\n return '$';\n }\n if (group === '&') {\n return match[0] ?? '';\n }\n const index = Number(group);\n return match[index] ?? '';\n });\n}\n\n/**\n * Builds the text to insert for one search match, including regex capture\n * substitution when regex mode is enabled.\n */\nexport function buildSearchReplacementText(\n positionAt: (offset: number) => Position,\n offsetAt: (position: Position) => number,\n getLineText: (line: number) => string,\n searchParams: SearchParams,\n matchStart: number,\n matchEnd: number\n): string {\n if (!searchParams.regex) {\n return searchParams.replaceText;\n }\n\n const position = positionAt(matchStart);\n const lineText = getLineText(position.line);\n const lineStart = offsetAt({ line: position.line, character: 0 });\n const relStart = matchStart - lineStart;\n const matched = lineText.slice(relStart, relStart + (matchEnd - matchStart));\n\n let pattern: RegExp;\n try {\n pattern = compileSearchRegExp(\n searchParams.text,\n true,\n searchParams.caseSensitive\n );\n } catch {\n return searchParams.replaceText;\n }\n\n const re = new RegExp(pattern.source, pattern.flags.replace('g', ''));\n const match = re.exec(matched);\n if (match === null || match[0].length !== matched.length) {\n return searchParams.replaceText;\n }\n return expandReplaceString(searchParams.replaceText, match);\n}\n\nfunction advancePastEmptyMatch(text: string, index: number): number {\n if (index + 1 < text.length) {\n const first = text.charCodeAt(index);\n const second = text.charCodeAt(index + 1);\n if (\n first >= 0xd800 &&\n first <= 0xdbff &&\n second >= 0xdc00 &&\n second <= 0xdfff\n ) {\n return index + 2;\n }\n }\n return index + 1;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pieceTable.js","names":["#original","#createPiece","#root","#createNode","#length","#lineCount","#textFromPieces","#lastVisitedLine","#getLineOffset","#lastVisitedLineLength","#findPieceAtOffset","#bufferFor","#nextNode","#forEachPieceSegment","#collectSearchMatchesLineByLine","#replaceRangeIncremental","#lineAtOffset","#lineBreakOffset","#walk","#add","#split","#mergeNodes","#appendCoalescing","#popLeftmost","#priorityState","#nextPriority","#setLeft","#setRight"],"sources":["../../src/editor/pieceTable.ts"],"sourcesContent":["import { computeLineOffsets } from '../utils/computeFileOffsets';\nimport type { SearchParams } from './searchPanel';\nimport type { Position, Range, ResolvedTextEdit } from './textDocument';\n\nconst MAX_FIND_MATCHES = 100000;\n// TODO(ije): use Intl.Segmenter instead of regex for word separators\nconst WORD_SEPARATORS = '`~!@#$%^&*()-=+[{]}\\\\|;:\\'\",.<>/?' as const;\n\n// A piece is a segment of text that is either original or added.\nclass Piece {\n static Original = 0;\n static Added = 1;\n\n constructor(\n public readonly source: number,\n public readonly offset: number,\n public readonly length: number,\n public readonly lineOffsetStart: number,\n public readonly lineOffsetEnd: number\n ) {}\n\n get lineBreakCount(): number {\n return this.lineOffsetEnd - this.lineOffsetStart;\n }\n}\n\n// A text buffer is a string with its line offsets.\nclass TextBuffer {\n lineOffsets: number[];\n\n constructor(public text: string) {\n this.lineOffsets = computeLineOffsets(text);\n }\n\n // the append operation is efficient because it only appends\n // elements to the lineOffsets array in the end\n append(text: string): number {\n const offset = this.text.length;\n const appendedLineOffsets = computeLineOffsets(text);\n for (let i = 1; i < appendedLineOffsets.length; i++) {\n this.lineOffsets.push(offset + appendedLineOffsets[i]);\n }\n this.text += text;\n return offset;\n }\n}\n\n// A node in the balanced piece tree. `priority` keeps the tree balanced as a\n// treap (see PieceTable): the tree is a max-heap on priority while staying a\n// binary search tree on document offset.\nclass PieceNode {\n left: PieceNode | null = null;\n right: PieceNode | null = null;\n parent: PieceNode | null = null;\n priority = 0;\n\n constructor(\n public piece: Piece,\n public subtreeLength: number = piece.length,\n public subtreeLineBreakCount: number = piece.lineBreakCount\n ) {}\n\n updateSubtreeLength(): void {\n this.subtreeLength =\n (this.left?.subtreeLength ?? 0) +\n this.piece.length +\n (this.right?.subtreeLength ?? 0);\n this.subtreeLineBreakCount =\n (this.left?.subtreeLineBreakCount ?? 0) +\n this.piece.lineBreakCount +\n (this.right?.subtreeLineBreakCount ?? 0);\n }\n}\n\n/**\n * A piece table is a data structure that allows for efficient insertion and deletion of text.\n * It is a tree of pieces, where each piece is a segment of text that is either original or added.\n * The tree is a treap (a binary search tree that also keeps each node's random priority in heap\n * order, which keeps the tree balanced without an explicit rebalancing pass). Each edit reshapes\n * only the nodes along one root-to-leaf path via split and merge in O(log P), instead of\n * rebuilding all P pieces.\n * Inspired by https://code.visualstudio.com/blogs/2018/03/23/text-buffer-reimplementation\n */\nexport class PieceTable {\n #original: TextBuffer;\n #add = new TextBuffer('');\n #root: PieceNode | null = null;\n #length = 0;\n #lineCount = 0;\n #lastVisitedLine: [number, boolean, string] | null = null;\n #lastVisitedLineLength: [number, boolean, number] | null = null;\n // Seeds the treap priorities. 0x9e3779b9 is the 32-bit golden-ratio\n // constant (2^32 / phi), a well-mixed value commonly used to seed hashes\n // and PRNGs; any fixed nonzero seed works here. A fixed seed keeps the\n // tree shape, and thus performance, deterministic across runs.\n #priorityState = 0x9e3779b9;\n\n constructor(originalText: string) {\n this.#original = new TextBuffer(originalText);\n const piece = this.#createPiece(Piece.Original, 0, originalText.length);\n this.#root = piece.length > 0 ? this.#createNode(piece) : null;\n this.#length = this.#root?.subtreeLength ?? 0;\n this.#lineCount = (this.#root?.subtreeLineBreakCount ?? 0) + 1;\n }\n\n get lineCount(): number {\n return this.#lineCount;\n }\n\n getText(range?: Range): string {\n if (range === undefined) {\n return this.#textFromPieces();\n }\n const start = this.offsetAt(range.start);\n const end = this.offsetAt(range.end);\n return this.getTextSlice(start, end);\n }\n\n getLineText(line: number, includeLineBreak = false): string {\n if (\n this.#lastVisitedLine !== null &&\n this.#lastVisitedLine[0] === line &&\n this.#lastVisitedLine[1] === includeLineBreak\n ) {\n return this.#lastVisitedLine[2];\n }\n const offset = this.#getLineOffset(line);\n if (offset === undefined) {\n throw new Error(`Line index out of range: ${line}`);\n }\n const text = this.getTextSlice(offset[0], offset[1], !includeLineBreak);\n this.#lastVisitedLine = [line, includeLineBreak, text];\n this.#lastVisitedLineLength = [line, includeLineBreak, text.length];\n return text;\n }\n\n getLineLength(line: number, includeLineBreak = false): number {\n const lastVisitedLineLength = this.#lastVisitedLineLength;\n const lastVisitedLine = this.#lastVisitedLine;\n if (\n lastVisitedLineLength !== null &&\n lastVisitedLineLength[0] === line &&\n lastVisitedLineLength[1] === includeLineBreak\n ) {\n return lastVisitedLineLength[2];\n }\n if (\n lastVisitedLine !== null &&\n lastVisitedLine[0] === line &&\n lastVisitedLine[1] === includeLineBreak\n ) {\n const length = lastVisitedLine[2].length;\n this.#lastVisitedLineLength = [line, includeLineBreak, length];\n return length;\n }\n const offset = this.#getLineOffset(line);\n if (offset === undefined) {\n throw new Error(`Line index out of range: ${line}`);\n }\n const [start, end] = offset;\n let length = end - start;\n if (!includeLineBreak) {\n while (\n length > 0 &&\n isEOL(this.charAt(start + length - 1).charCodeAt(0))\n ) {\n length--;\n }\n }\n this.#lastVisitedLineLength = [line, includeLineBreak, length];\n return length;\n }\n\n getTextSlice(start: number, end: number, trimEOF = false): string {\n if (start >= end) {\n return '';\n }\n\n const sliceStart = clamp(start, 0, this.#length);\n const sliceEnd = clamp(end, sliceStart, this.#length);\n if (sliceStart >= sliceEnd) {\n return '';\n }\n\n const location = this.#findPieceAtOffset(sliceStart);\n if (location === undefined) {\n return '';\n }\n\n const chunks: string[] = [];\n let [node, offsetInPiece] = location as [PieceNode | null, number];\n let remaining = sliceEnd - sliceStart;\n while (node !== null && remaining > 0) {\n const takeLength = Math.min(node.piece.length - offsetInPiece, remaining);\n const buffer = this.#bufferFor(node.piece.source);\n const start = node.piece.offset + offsetInPiece;\n let end = start + takeLength;\n if (trimEOF) {\n while (end > start && isEOL(buffer.text.charCodeAt(end - 1))) {\n end--;\n }\n }\n chunks.push(buffer.text.slice(start, end));\n remaining -= takeLength;\n offsetInPiece = 0;\n node = this.#nextNode(node);\n }\n\n return chunks.join('');\n }\n\n charAt(offset: number): string {\n const location = this.#findPieceAtOffset(offset);\n if (location === undefined) {\n return '';\n }\n\n const [node, offsetInPiece] = location;\n const buffer = this.#bufferFor(node.piece.source);\n return buffer.text.charAt(node.piece.offset + offsetInPiece);\n }\n\n includes(needle: string): boolean {\n if (needle.length === 0) {\n return true;\n }\n\n const prefixTable = createPrefixTable(needle);\n let matched = 0;\n let found = false;\n this.#forEachPieceSegment((segment) => {\n for (let offset = segment.start; offset < segment.end; offset++) {\n const charCode = segment.text.charCodeAt(offset);\n while (matched > 0 && charCode !== needle.charCodeAt(matched)) {\n matched = prefixTable[matched - 1];\n }\n if (charCode === needle.charCodeAt(matched)) {\n matched++;\n }\n if (matched === needle.length) {\n found = true;\n return false;\n }\n }\n return true;\n });\n return found;\n }\n\n findNextNonOverlappingSubstring(\n needle: string,\n occupied: readonly [start: number, end: number][]\n ): number | undefined {\n if (needle.length === 0 || needle.length > this.#length) {\n return undefined;\n }\n\n const ranges = normalizeRanges(occupied, this.#length);\n const pivot = ranges.reduce((max, [, end]) => Math.max(max, end), 0);\n const prefixTable = createPrefixTable(needle);\n let matched = 0;\n let documentOffset = 0;\n let wrappedOffset: number | undefined;\n let foundOffset: number | undefined;\n\n this.#forEachPieceSegment((segment) => {\n for (let offset = segment.start; offset < segment.end; offset++) {\n const charCode = segment.text.charCodeAt(offset);\n while (matched > 0 && charCode !== needle.charCodeAt(matched)) {\n matched = prefixTable[matched - 1];\n }\n if (charCode === needle.charCodeAt(matched)) {\n matched++;\n }\n if (matched === needle.length) {\n const start = documentOffset - needle.length + 1;\n if (!rangeOverlaps(ranges, start, start + needle.length)) {\n if (start >= pivot) {\n foundOffset = start;\n return false;\n }\n wrappedOffset ??= start;\n }\n matched = prefixTable[matched - 1];\n }\n documentOffset++;\n }\n return true;\n });\n\n return foundOffset ?? wrappedOffset;\n }\n\n search(searchParams: SearchParams): [start: number, end: number][] {\n if (searchParams.text.length === 0 || this.#length === 0) {\n return [];\n }\n\n // Search currently operates line-by-line, so newline-spanning patterns are unsupported.\n if (\n searchParams.text.includes('\\n') ||\n searchParams.text.includes('\\r') ||\n (searchParams.regex &&\n (searchParams.text.includes('\\\\n') ||\n searchParams.text.includes('\\\\r')))\n ) {\n return [];\n }\n\n let pattern: RegExp;\n try {\n pattern = compileSearchRegExp(\n searchParams.text,\n searchParams.regex,\n searchParams.caseSensitive\n );\n } catch {\n return [];\n }\n\n return this.#collectSearchMatchesLineByLine(\n pattern,\n searchParams.wholeWord,\n MAX_FIND_MATCHES\n );\n }\n\n #collectSearchMatchesLineByLine(\n pattern: RegExp,\n wholeWord: boolean,\n limit: number\n ): [number, number][] {\n const out: [number, number][] = [];\n const docLength = this.#length;\n const charAt = (offset: number) => this.charAt(offset);\n\n // Reuse the single compiled pattern across every line, resetting its\n // lastIndex before each line, instead of allocating a fresh RegExp per\n // line. The pattern is global, so lastIndex tracks progress within a line.\n for (let line = 0; line < this.#lineCount; line++) {\n const lineText = this.getLineText(line);\n const lineStart = this.offsetAt({ line, character: 0 });\n pattern.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(lineText)) !== null) {\n const rel = match.index;\n const fragment = match[0];\n if (fragment.length === 0) {\n pattern.lastIndex = advancePastEmptyMatch(lineText, rel);\n continue;\n }\n const docStart = lineStart + rel;\n if (\n !wholeWord ||\n isWholeWordAtDocOffsets(docStart, fragment.length, docLength, charAt)\n ) {\n out.push([docStart, docStart + fragment.length]);\n if (out.length >= limit) {\n return out;\n }\n }\n if (rel === pattern.lastIndex) {\n pattern.lastIndex = advancePastEmptyMatch(lineText, rel);\n }\n }\n }\n return out;\n }\n\n insert(text: string, offset: number): void {\n if (text.length === 0) {\n return;\n }\n const start = clamp(offset, 0, this.#length);\n this.#replaceRangeIncremental(start, start, text);\n }\n\n delete(offset: number, length: number): void {\n if (length <= 0 || this.#length === 0) {\n return;\n }\n const start = clamp(offset, 0, this.#length);\n const end = clamp(start + length, start, this.#length);\n if (start === end) {\n return;\n }\n this.#replaceRangeIncremental(start, end, '');\n }\n\n applyEdits(edits: readonly ResolvedTextEdit[]): void {\n if (edits.length === 0) {\n return;\n }\n // Edits arrive sorted ascending and non-overlapping (TextDocument enforces\n // this). Applying them from last to first keeps each remaining edit's\n // offsets valid, since edits at higher offsets never shift lower ones, and\n // every edit becomes an O(log P) incremental replace.\n for (let i = edits.length - 1; i >= 0; i--) {\n const edit = edits[i];\n const start = clamp(edit.start, 0, this.#length);\n const end = clamp(edit.end, start, this.#length);\n this.#replaceRangeIncremental(start, end, edit.text);\n }\n }\n\n positionAt(offset: number): Position {\n const clampedOffset = clamp(offset, 0, this.#length);\n if (this.#length === 0) {\n return { line: 0, character: 0 };\n }\n const line = this.#lineAtOffset(clampedOffset);\n const lineStart = line === 0 ? 0 : this.#lineBreakOffset(line - 1);\n return {\n line,\n character: clampedOffset - lineStart,\n };\n }\n\n positionsAt(offsets: readonly number[]): Position[] {\n const positions: Position[] = Array.from({ length: offsets.length });\n if (offsets.length === 0) {\n return positions;\n }\n if (this.#length === 0) {\n return positions.fill({ line: 0, character: 0 });\n }\n\n for (let i = 0; i < offsets.length; i++) {\n positions[i] = this.positionAt(offsets[i]);\n }\n\n return positions;\n }\n\n offsetAt(position: Position): number {\n if (position.line < 0 || this.#length === 0) {\n return 0;\n }\n if (position.line >= this.#lineCount) {\n throw new Error(`Line index out of range: ${position.line}`);\n }\n const offset = this.#getLineOffset(position.line);\n if (offset === undefined) {\n throw new Error(`Line index out of range: ${position.line}`);\n }\n const character = clamp(position.character, 0, offset[1] - offset[0]);\n return offset[0] + character;\n }\n\n #findPieceAtOffset(\n offset: number\n ): [node: PieceNode, offsetInPiece: number] | undefined {\n if (offset < 0 || offset >= this.#length) {\n return undefined;\n }\n\n let node = this.#root;\n let remaining = offset;\n while (node !== null) {\n const leftLength = node.left?.subtreeLength ?? 0;\n if (remaining < leftLength) {\n node = node.left;\n continue;\n }\n\n remaining -= leftLength;\n if (remaining < node.piece.length) {\n return [node, remaining];\n }\n\n remaining -= node.piece.length;\n node = node.right;\n }\n\n return undefined;\n }\n\n #nextNode(node: PieceNode): PieceNode | null {\n if (node.right !== null) {\n let next = node.right;\n while (next.left !== null) {\n next = next.left;\n }\n return next;\n }\n\n let current = node;\n while (current.parent !== null && current === current.parent.right) {\n current = current.parent;\n }\n return current.parent;\n }\n\n #getLineOffset(line: number): [start: number, end: number] | undefined {\n if (line < 0) {\n throw new Error(`Line index out of range: ${line}`);\n }\n if (this.#length === 0) {\n if (line === 0) {\n return [0, 0];\n }\n throw new Error(`Line index out of range: ${line}`);\n }\n if (line >= this.#lineCount) {\n throw new Error(`Line index out of range: ${line}`);\n }\n\n const start = line === 0 ? 0 : this.#lineBreakOffset(line - 1);\n const end =\n line < this.#lineCount - 1 ? this.#lineBreakOffset(line) : this.#length;\n return [start, end];\n }\n\n #lineAtOffset(offset: number): number {\n let node = this.#root;\n let remaining = clamp(offset, 0, this.#length);\n let line = 0;\n\n while (node !== null) {\n const leftLength = node.left?.subtreeLength ?? 0;\n if (remaining < leftLength) {\n node = node.left;\n continue;\n }\n\n line += node.left?.subtreeLineBreakCount ?? 0;\n remaining -= leftLength;\n if (remaining <= node.piece.length) {\n const buffer = this.#bufferFor(node.piece.source);\n line +=\n upperBound(buffer.lineOffsets, node.piece.offset + remaining) -\n node.piece.lineOffsetStart;\n return line;\n }\n\n line += node.piece.lineBreakCount;\n remaining -= node.piece.length;\n node = node.right;\n }\n\n return this.#lineCount - 1;\n }\n\n #lineBreakOffset(lineBreakIndex: number): number {\n let node = this.#root;\n let remaining = lineBreakIndex;\n let documentOffset = 0;\n\n while (node !== null) {\n const leftLineBreakCount = node.left?.subtreeLineBreakCount ?? 0;\n if (remaining < leftLineBreakCount) {\n node = node.left;\n continue;\n }\n\n const leftLength = node.left?.subtreeLength ?? 0;\n documentOffset += leftLength;\n remaining -= leftLineBreakCount;\n\n if (remaining < node.piece.lineBreakCount) {\n const bufferLineOffset = this.#bufferFor(node.piece.source).lineOffsets[\n node.piece.lineOffsetStart + remaining\n ];\n return documentOffset + (bufferLineOffset - node.piece.offset);\n }\n\n documentOffset += node.piece.length;\n remaining -= node.piece.lineBreakCount;\n node = node.right;\n }\n\n return this.#length;\n }\n\n #textFromPieces(): string {\n const chunks: string[] = [];\n this.#forEachPieceSegment((segment) => {\n chunks.push(segment.text.slice(segment.start, segment.end));\n });\n return chunks.join('');\n }\n\n #forEachPieceSegment(\n callback: (segment: {\n readonly start: number;\n readonly end: number;\n readonly text: string;\n readonly lineOffsets: number[];\n readonly lineOffsetStart: number;\n readonly lineOffsetEnd: number;\n }) => boolean | void\n ): void {\n this.#walk(this.#root, (node) => {\n const buffer = this.#bufferFor(node.piece.source);\n return callback({\n text: buffer.text,\n lineOffsets: buffer.lineOffsets,\n lineOffsetStart: node.piece.lineOffsetStart,\n lineOffsetEnd: node.piece.lineOffsetEnd,\n start: node.piece.offset,\n end: node.piece.offset + node.piece.length,\n });\n });\n }\n\n #bufferFor(source: number): TextBuffer {\n return source === Piece.Original ? this.#original : this.#add;\n }\n\n #createPiece(source: number, offset: number, length: number): Piece {\n const buffer = this.#bufferFor(source);\n return new Piece(\n source,\n offset,\n length,\n upperBound(buffer.lineOffsets, offset),\n upperBound(buffer.lineOffsets, offset + length)\n );\n }\n\n // Replaces document range [start, end) with `text` by splitting the tree at\n // both ends, dropping the middle (the deleted span), and joining the inserted\n // piece back in. Each split/merge touches only one root-to-leaf path, so the\n // edit is O(log P) instead of rebuilding all P pieces. `start`/`end` must be\n // clamped into [0, length] with start <= end.\n #replaceRangeIncremental(start: number, end: number, text: string): void {\n if (start === end && text.length === 0) {\n return;\n }\n\n const [left, rest] = this.#split(this.#root, start);\n const [, right] = this.#split(rest, end - start);\n\n let root: PieceNode | null;\n if (text.length > 0) {\n const insertedPiece = this.#createPiece(\n Piece.Added,\n this.#add.append(text),\n text.length\n );\n // The inserted text is fresh at the end of the add buffer, so it can only\n // sit next to the piece on its left, never the one on its right.\n root = this.#mergeNodes(\n this.#appendCoalescing(left, insertedPiece),\n right\n );\n } else {\n // Pure deletion: the pieces now meeting at the seam may be contiguous in\n // the same buffer, so re-attach the right side's first piece through the\n // coalescing append to merge them when possible.\n const [seamPiece, restRight] = this.#popLeftmost(right);\n root =\n seamPiece === undefined\n ? left\n : this.#mergeNodes(\n this.#appendCoalescing(left, seamPiece),\n restRight\n );\n }\n\n if (root !== null) {\n root.parent = null;\n }\n this.#root = root;\n this.#length = root?.subtreeLength ?? 0;\n this.#lineCount = (root?.subtreeLineBreakCount ?? 0) + 1;\n this.#lastVisitedLine = null;\n this.#lastVisitedLineLength = null;\n }\n\n #nextPriority(): number {\n this.#priorityState =\n (Math.imul(this.#priorityState, 1664525) + 1013904223) >>> 0;\n return this.#priorityState;\n }\n\n #createNode(piece: Piece): PieceNode {\n const node = new PieceNode(piece);\n node.priority = this.#nextPriority();\n return node;\n }\n\n // Attaches `child` as a side of `node`, keeping the parent pointer in sync so\n // read-side iteration (#nextNode) can still walk back up the tree.\n #setLeft(node: PieceNode, child: PieceNode | null): void {\n node.left = child;\n if (child !== null) {\n child.parent = node;\n }\n }\n\n #setRight(node: PieceNode, child: PieceNode | null): void {\n node.right = child;\n if (child !== null) {\n child.parent = node;\n }\n }\n\n // Splits the subtree into [0, offset) and [offset, length). When the offset\n // falls inside a piece, that piece is sliced in two so the split lands on a\n // clean boundary. Internal parent pointers stay correct; the caller fixes the\n // returned roots' own parents when it reattaches or stores them.\n #split(\n node: PieceNode | null,\n offset: number\n ): [left: PieceNode | null, right: PieceNode | null] {\n if (node === null) {\n return [null, null];\n }\n\n const leftLength = node.left?.subtreeLength ?? 0;\n if (offset <= leftLength) {\n const [left, right] = this.#split(node.left, offset);\n this.#setLeft(node, right);\n node.updateSubtreeLength();\n return [left, node];\n }\n\n const pieceLength = node.piece.length;\n if (offset >= leftLength + pieceLength) {\n const [left, right] = this.#split(\n node.right,\n offset - leftLength - pieceLength\n );\n this.#setRight(node, left);\n node.updateSubtreeLength();\n return [node, right];\n }\n\n // The offset is strictly inside this node's piece: slice it in two. Both\n // halves inherit this node's priority, which keeps the heap valid because\n // this node already outranked both of its children.\n const inPiece = offset - leftLength;\n const leftNode = new PieceNode(\n this.#createPiece(node.piece.source, node.piece.offset, inPiece)\n );\n const rightNode = new PieceNode(\n this.#createPiece(\n node.piece.source,\n node.piece.offset + inPiece,\n pieceLength - inPiece\n )\n );\n leftNode.priority = node.priority;\n rightNode.priority = node.priority;\n this.#setLeft(leftNode, node.left);\n this.#setRight(rightNode, node.right);\n leftNode.updateSubtreeLength();\n rightNode.updateSubtreeLength();\n return [leftNode, rightNode];\n }\n\n // Joins two subtrees where every offset in `left` precedes every offset in\n // `right`, taking the higher-priority root so the result stays balanced.\n #mergeNodes(\n left: PieceNode | null,\n right: PieceNode | null\n ): PieceNode | null {\n if (left === null) {\n return right;\n }\n if (right === null) {\n return left;\n }\n if (left.priority >= right.priority) {\n this.#setRight(left, this.#mergeNodes(left.right, right));\n left.updateSubtreeLength();\n return left;\n }\n this.#setLeft(right, this.#mergeNodes(left, right.left));\n right.updateSubtreeLength();\n return right;\n }\n\n // Appends `piece` after every node in `tree`. If the tree's last piece and\n // `piece` point at adjacent text in the same buffer, they are merged in place\n // (no new node) — this is what keeps sequential typing a single piece and\n // stops the piece count from growing without bound.\n #appendCoalescing(tree: PieceNode | null, piece: Piece): PieceNode {\n if (tree === null) {\n return this.#createNode(piece);\n }\n let last = tree;\n while (last.right !== null) {\n last = last.right;\n }\n if (canCoalescePieces(last.piece, piece)) {\n last.piece = coalesceTwoPieces(last.piece, piece);\n // The last piece grew, so refresh aggregates from it up to the root.\n for (let node: PieceNode | null = last; node !== null; ) {\n node.updateSubtreeLength();\n if (node === tree) {\n break;\n }\n node = node.parent;\n }\n return tree;\n }\n // `tree` is non-null here, so merging in the new node always yields a node.\n return this.#mergeNodes(tree, this.#createNode(piece)) as PieceNode;\n }\n\n // Removes and returns the first piece of the tree along with the remaining\n // tree, so a deletion seam can re-merge the piece that becomes adjacent to\n // the one on the other side of the deletion.\n #popLeftmost(\n tree: PieceNode | null\n ): [piece: Piece | undefined, rest: PieceNode | null] {\n if (tree === null) {\n return [undefined, null];\n }\n if (tree.left === null) {\n return [tree.piece, tree.right];\n }\n const [piece, newLeft] = this.#popLeftmost(tree.left);\n this.#setLeft(tree, newLeft);\n tree.updateSubtreeLength();\n return [piece, tree];\n }\n\n #walk(\n node: PieceNode | null,\n visit: (node: PieceNode) => boolean | void\n ): boolean {\n if (node === null) {\n return true;\n }\n if (!this.#walk(node.left, visit)) {\n return false;\n }\n if (visit(node) === false) {\n return false;\n }\n return this.#walk(node.right, visit);\n }\n}\n\nfunction isEOL(charCode: number): boolean {\n return charCode === /* \\n */ 10 || charCode === /* \\r */ 13;\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\nfunction createPrefixTable(text: string): number[] {\n const table = Array.from<number>({ length: text.length }).fill(0);\n let matched = 0;\n for (let i = 1; i < text.length; i++) {\n const charCode = text.charCodeAt(i);\n while (matched > 0 && charCode !== text.charCodeAt(matched)) {\n matched = table[matched - 1];\n }\n if (charCode === text.charCodeAt(matched)) {\n matched++;\n }\n table[i] = matched;\n }\n return table;\n}\n\nfunction normalizeRanges(\n ranges: readonly [start: number, end: number][],\n length: number\n): [start: number, end: number][] {\n const normalized: [start: number, end: number][] = [];\n for (const [rawStart, rawEnd] of ranges) {\n const start = clamp(rawStart, 0, length);\n const end = clamp(rawEnd, start, length);\n if (start < end) {\n normalized.push([start, end]);\n }\n }\n normalized.sort((a, b) => a[0] - b[0]);\n\n const merged: [start: number, end: number][] = [];\n for (const range of normalized) {\n const previous = merged[merged.length - 1];\n if (previous !== undefined && range[0] <= previous[1]) {\n previous[1] = Math.max(previous[1], range[1]);\n continue;\n }\n merged.push(range);\n }\n return merged;\n}\n\nfunction rangeOverlaps(\n ranges: readonly [start: number, end: number][],\n start: number,\n end: number\n): boolean {\n let low = 0;\n let high = ranges.length;\n while (low < high) {\n const mid = low + Math.floor((high - low) / 2);\n if (ranges[mid][1] <= start) {\n low = mid + 1;\n } else {\n high = mid;\n }\n }\n\n const range = ranges[low];\n return range !== undefined && range[0] < end;\n}\n\n// True when two pieces point at directly adjacent text in the same backing\n// buffer, so they can be represented as one piece.\nfunction canCoalescePieces(prev: Piece, next: Piece): boolean {\n return (\n prev.source === next.source && prev.offset + prev.length === next.offset\n );\n}\n\n// Joins two adjacent pieces (see canCoalescePieces) into one. Keeping the table\n// compact after every edit is what stops the piece count from growing without\n// bound during normal typing.\nfunction coalesceTwoPieces(prev: Piece, next: Piece): Piece {\n return new Piece(\n prev.source,\n prev.offset,\n prev.length + next.length,\n prev.lineOffsetStart,\n next.lineOffsetEnd\n );\n}\n\n// Returns the index of the first element in the array that is greater than the target.\nfunction upperBound(values: number[], target: number): number {\n let lo = 0;\n let hi = values.length;\n while (lo < hi) {\n const mid = lo + Math.floor((hi - lo) / 2);\n if (values[mid] <= target) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n return lo;\n}\n\nfunction escapeRegExp(text: string): string {\n return text.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction isWordSeparatorCharCode(charCode: number): boolean {\n if (charCode <= 32 || charCode === 127) {\n return true;\n }\n const ch = String.fromCharCode(charCode);\n return WORD_SEPARATORS.includes(ch);\n}\n\n// Checks if the given text is a whole word by checking if the\n// characters before and after are word separators.\nfunction isWholeWordAtDocOffsets(\n docStart: number,\n length: number,\n docLength: number,\n charAt: (offset: number) => string\n): boolean {\n const beforeOk =\n docStart <= 0 ||\n isWordSeparatorCharCode(charCodeUnitAt(charAt, docStart - 1));\n const afterOk =\n docStart + length >= docLength ||\n isWordSeparatorCharCode(charCodeUnitAt(charAt, docStart + length));\n return beforeOk && afterOk;\n}\n\nfunction charCodeUnitAt(\n charAt: (offset: number) => string,\n offset: number\n): number {\n const unit = charAt(offset);\n return unit.length === 0 ? 0 : unit.charCodeAt(0);\n}\n\nfunction compileSearchRegExp(\n source: string,\n isRegex: boolean,\n caseSensitive: boolean\n): RegExp {\n const body = isRegex ? source : escapeRegExp(source);\n const flags = `g${caseSensitive ? '' : 'i'}${isRegex ? 'm' : ''}`;\n return new RegExp(body, flags);\n}\n\n/** Expands `$&`, `$1`, `$$`, etc. in a regex replace string using a match. */\nfunction expandReplaceString(\n replacement: string,\n match: RegExpExecArray\n): string {\n return replacement.replace(/\\$([$&]|\\d+)/g, (_token, group: string) => {\n if (group === '$') {\n return '$';\n }\n if (group === '&') {\n return match[0] ?? '';\n }\n const index = Number(group);\n return match[index] ?? '';\n });\n}\n\n/**\n * Builds the text to insert for one search match, including regex capture\n * substitution when regex mode is enabled.\n */\nexport function buildSearchReplacementText(\n positionAt: (offset: number) => Position,\n offsetAt: (position: Position) => number,\n getLineText: (line: number) => string,\n searchParams: SearchParams,\n matchStart: number,\n matchEnd: number\n): string {\n if (!searchParams.regex) {\n return searchParams.replaceText;\n }\n\n const position = positionAt(matchStart);\n const lineText = getLineText(position.line);\n const lineStart = offsetAt({ line: position.line, character: 0 });\n const relStart = matchStart - lineStart;\n const matched = lineText.slice(relStart, relStart + (matchEnd - matchStart));\n\n let pattern: RegExp;\n try {\n pattern = compileSearchRegExp(\n searchParams.text,\n true,\n searchParams.caseSensitive\n );\n } catch {\n return searchParams.replaceText;\n }\n\n const re = new RegExp(pattern.source, pattern.flags.replace('g', ''));\n const match = re.exec(matched);\n if (match === null || match[0].length !== matched.length) {\n return searchParams.replaceText;\n }\n return expandReplaceString(searchParams.replaceText, match);\n}\n\nfunction advancePastEmptyMatch(text: string, index: number): number {\n if (index + 1 < text.length) {\n const first = text.charCodeAt(index);\n const second = text.charCodeAt(index + 1);\n if (\n first >= 0xd800 &&\n first <= 0xdbff &&\n second >= 0xdc00 &&\n second <= 0xdfff\n ) {\n return index + 2;\n }\n }\n return index + 1;\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
//#region src/editor/platform.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Clears the cached platform/browser detection. Detection is memoized on first
|
|
4
|
+
* call, so a test process that swaps `navigator` (e.g. to exercise Linux or
|
|
5
|
+
* Safari behavior) must reset it; otherwise the value cached by an earlier test
|
|
6
|
+
* leaks across tests and no longer matches the active navigator.
|
|
7
|
+
*/
|
|
8
|
+
declare function resetPlatformDetectionForTests(): void;
|
|
2
9
|
declare function isMacLike(): boolean;
|
|
3
10
|
declare function isLinux(): boolean;
|
|
4
11
|
declare function isSafari(): boolean;
|
|
@@ -8,5 +15,5 @@ declare function isPrimaryModifier({
|
|
|
8
15
|
}: MouseEvent | KeyboardEvent, isMac?: boolean): boolean;
|
|
9
16
|
declare function isMoveCursorShortcut(e: KeyboardEvent): 'up' | 'down' | 'left' | 'right' | 'start' | 'textStart' | 'end' | undefined;
|
|
10
17
|
//#endregion
|
|
11
|
-
export { isLinux, isMacLike, isMoveCursorShortcut, isPrimaryModifier, isSafari };
|
|
18
|
+
export { isLinux, isMacLike, isMoveCursorShortcut, isPrimaryModifier, isSafari, resetPlatformDetectionForTests };
|
|
12
19
|
//# sourceMappingURL=platform.d.ts.map
|