@fairyhunter13/opentui-core 0.1.113 → 0.1.114
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/dev/keypress-debug-renderer.ts +148 -0
- package/dev/keypress-debug.ts +43 -0
- package/dev/print-env-vars.ts +32 -0
- package/dev/test-tmux-graphics-334.sh +68 -0
- package/dev/thai-debug-test.ts +68 -0
- package/docs/development.md +144 -0
- package/package.json +62 -53
- package/scripts/build.ts +400 -0
- package/scripts/publish.ts +60 -0
- package/src/3d/SpriteResourceManager.ts +286 -0
- package/src/3d/SpriteUtils.ts +70 -0
- package/src/3d/TextureUtils.ts +196 -0
- package/src/3d/ThreeRenderable.ts +197 -0
- package/src/3d/WGPURenderer.ts +294 -0
- package/src/3d/animation/ExplodingSpriteEffect.ts +513 -0
- package/src/3d/animation/PhysicsExplodingSpriteEffect.ts +429 -0
- package/src/3d/animation/SpriteAnimator.ts +633 -0
- package/src/3d/animation/SpriteParticleGenerator.ts +435 -0
- package/src/3d/canvas.ts +464 -0
- package/src/3d/index.ts +12 -0
- package/src/3d/physics/PlanckPhysicsAdapter.ts +72 -0
- package/src/3d/physics/RapierPhysicsAdapter.ts +66 -0
- package/src/3d/physics/physics-interface.ts +31 -0
- package/src/3d/shaders/supersampling.wgsl +201 -0
- package/src/3d.ts +3 -0
- package/src/NativeSpanFeed.ts +300 -0
- package/src/Renderable.ts +1704 -0
- package/src/__snapshots__/buffer.test.ts.snap +28 -0
- package/src/animation/Timeline.test.ts +2709 -0
- package/src/animation/Timeline.ts +598 -0
- package/src/ansi.ts +18 -0
- package/src/benchmark/attenuation-benchmark.ts +81 -0
- package/src/benchmark/colormatrix-benchmark.ts +128 -0
- package/src/benchmark/gain-benchmark.ts +80 -0
- package/src/benchmark/latest-all-bench-run.json +707 -0
- package/src/benchmark/latest-async-bench-run.json +336 -0
- package/src/benchmark/latest-default-bench-run.json +657 -0
- package/src/benchmark/latest-large-bench-run.json +707 -0
- package/src/benchmark/latest-quick-bench-run.json +207 -0
- package/src/benchmark/markdown-benchmark.ts +1796 -0
- package/src/benchmark/native-span-feed-async-benchmark.ts +355 -0
- package/src/benchmark/native-span-feed-benchmark.md +56 -0
- package/src/benchmark/native-span-feed-benchmark.ts +596 -0
- package/src/benchmark/native-span-feed-compare.ts +280 -0
- package/src/benchmark/renderer-benchmark.ts +754 -0
- package/src/benchmark/text-table-benchmark.ts +948 -0
- package/src/buffer.test.ts +291 -0
- package/src/buffer.ts +554 -0
- package/src/console.test.ts +612 -0
- package/src/console.ts +1254 -0
- package/src/edit-buffer.test.ts +1769 -0
- package/src/edit-buffer.ts +411 -0
- package/src/editor-view.test.ts +1032 -0
- package/src/editor-view.ts +284 -0
- package/src/examples/ascii-font-selection-demo.ts +245 -0
- package/src/examples/assets/Water_2_M_Normal.jpg +0 -0
- package/src/examples/assets/concrete.png +0 -0
- package/src/examples/assets/crate.png +0 -0
- package/src/examples/assets/crate_emissive.png +0 -0
- package/src/examples/assets/forrest_background.png +0 -0
- package/src/examples/assets/hast-example.json +1018 -0
- package/src/examples/assets/heart.png +0 -0
- package/src/examples/assets/main_char_heavy_attack.png +0 -0
- package/src/examples/assets/main_char_idle.png +0 -0
- package/src/examples/assets/main_char_jump_end.png +0 -0
- package/src/examples/assets/main_char_jump_landing.png +0 -0
- package/src/examples/assets/main_char_jump_start.png +0 -0
- package/src/examples/assets/main_char_run_loop.png +0 -0
- package/src/examples/assets/roughness_map.jpg +0 -0
- package/src/examples/build.ts +115 -0
- package/src/examples/code-demo.ts +924 -0
- package/src/examples/console-demo.ts +358 -0
- package/src/examples/core-plugin-slots-demo.ts +759 -0
- package/src/examples/diff-demo.ts +701 -0
- package/src/examples/draggable-three-demo.ts +259 -0
- package/src/examples/editor-demo.ts +322 -0
- package/src/examples/extmarks-demo.ts +196 -0
- package/src/examples/focus-restore-demo.ts +310 -0
- package/src/examples/fonts.ts +245 -0
- package/src/examples/fractal-shader-demo.ts +268 -0
- package/src/examples/framebuffer-demo.ts +674 -0
- package/src/examples/full-unicode-demo.ts +241 -0
- package/src/examples/golden-star-demo.ts +933 -0
- package/src/examples/grayscale-buffer-demo.ts +249 -0
- package/src/examples/hast-syntax-highlighting-demo.ts +129 -0
- package/src/examples/index.ts +926 -0
- package/src/examples/input-demo.ts +377 -0
- package/src/examples/input-select-layout-demo.ts +425 -0
- package/src/examples/install.sh +143 -0
- package/src/examples/keypress-debug-demo.ts +452 -0
- package/src/examples/lib/HexList.ts +122 -0
- package/src/examples/lib/PaletteGrid.ts +125 -0
- package/src/examples/lib/standalone-keys.ts +25 -0
- package/src/examples/lib/tab-controller.ts +243 -0
- package/src/examples/lights-phong-demo.ts +290 -0
- package/src/examples/link-demo.ts +220 -0
- package/src/examples/live-state-demo.ts +480 -0
- package/src/examples/markdown-demo.ts +725 -0
- package/src/examples/mouse-interaction-demo.ts +428 -0
- package/src/examples/nested-zindex-demo.ts +357 -0
- package/src/examples/opacity-example.ts +235 -0
- package/src/examples/opentui-demo.ts +1057 -0
- package/src/examples/physx-planck-2d-demo.ts +623 -0
- package/src/examples/physx-rapier-2d-demo.ts +655 -0
- package/src/examples/relative-positioning-demo.ts +323 -0
- package/src/examples/scroll-example.ts +214 -0
- package/src/examples/scrollbox-mouse-test.ts +112 -0
- package/src/examples/scrollbox-overlay-hit-test.ts +206 -0
- package/src/examples/select-demo.ts +237 -0
- package/src/examples/shader-cube-demo.ts +1015 -0
- package/src/examples/simple-layout-example.ts +591 -0
- package/src/examples/slider-demo.ts +617 -0
- package/src/examples/split-mode-demo.ts +453 -0
- package/src/examples/sprite-animation-demo.ts +443 -0
- package/src/examples/sprite-particle-generator-demo.ts +486 -0
- package/src/examples/static-sprite-demo.ts +193 -0
- package/src/examples/sticky-scroll-example.ts +308 -0
- package/src/examples/styled-text-demo.ts +282 -0
- package/src/examples/tab-select-demo.ts +219 -0
- package/src/examples/terminal-title.ts +29 -0
- package/src/examples/terminal.ts +305 -0
- package/src/examples/text-node-demo.ts +416 -0
- package/src/examples/text-selection-demo.ts +377 -0
- package/src/examples/text-table-demo.ts +503 -0
- package/src/examples/text-truncation-demo.ts +481 -0
- package/src/examples/text-wrap.ts +757 -0
- package/src/examples/texture-loading-demo.ts +259 -0
- package/src/examples/timeline-example.ts +670 -0
- package/src/examples/transparency-demo.ts +400 -0
- package/src/examples/vnode-composition-demo.ts +404 -0
- package/src/examples/wide-grapheme-overlay-demo.ts +280 -0
- package/src/index.ts +24 -0
- package/src/lib/KeyHandler.integration.test.ts +292 -0
- package/src/lib/KeyHandler.stopPropagation.test.ts +289 -0
- package/src/lib/KeyHandler.test.ts +662 -0
- package/src/lib/KeyHandler.ts +222 -0
- package/src/lib/RGBA.test.ts +984 -0
- package/src/lib/RGBA.ts +204 -0
- package/src/lib/ascii.font.ts +330 -0
- package/src/lib/border.test.ts +83 -0
- package/src/lib/border.ts +170 -0
- package/src/lib/bunfs.test.ts +27 -0
- package/src/lib/bunfs.ts +18 -0
- package/src/lib/clipboard.test.ts +41 -0
- package/src/lib/clipboard.ts +47 -0
- package/src/lib/clock.ts +35 -0
- package/src/lib/data-paths.test.ts +133 -0
- package/src/lib/data-paths.ts +109 -0
- package/src/lib/debounce.ts +106 -0
- package/src/lib/detect-links.test.ts +98 -0
- package/src/lib/detect-links.ts +56 -0
- package/src/lib/env.test.ts +228 -0
- package/src/lib/env.ts +209 -0
- package/src/lib/extmarks-history.ts +51 -0
- package/src/lib/extmarks-multiwidth.test.ts +322 -0
- package/src/lib/extmarks.test.ts +3457 -0
- package/src/lib/extmarks.ts +843 -0
- package/src/lib/fonts/block.json +405 -0
- package/src/lib/fonts/grid.json +265 -0
- package/src/lib/fonts/huge.json +741 -0
- package/src/lib/fonts/pallet.json +314 -0
- package/src/lib/fonts/shade.json +591 -0
- package/src/lib/fonts/slick.json +321 -0
- package/src/lib/fonts/tiny.json +69 -0
- package/src/lib/hast-styled-text.ts +59 -0
- package/src/lib/index.ts +21 -0
- package/src/lib/keymapping.test.ts +317 -0
- package/src/lib/keymapping.ts +115 -0
- package/src/lib/objects-in-viewport.test.ts +787 -0
- package/src/lib/objects-in-viewport.ts +153 -0
- package/src/lib/output.capture.ts +58 -0
- package/src/lib/parse.keypress-kitty.protocol.test.ts +340 -0
- package/src/lib/parse.keypress-kitty.test.ts +663 -0
- package/src/lib/parse.keypress-kitty.ts +439 -0
- package/src/lib/parse.keypress.test.ts +1849 -0
- package/src/lib/parse.keypress.ts +397 -0
- package/src/lib/parse.mouse.test.ts +552 -0
- package/src/lib/parse.mouse.ts +232 -0
- package/src/lib/paste.ts +16 -0
- package/src/lib/queue.ts +65 -0
- package/src/lib/renderable.validations.test.ts +87 -0
- package/src/lib/renderable.validations.ts +83 -0
- package/src/lib/scroll-acceleration.ts +98 -0
- package/src/lib/selection.ts +240 -0
- package/src/lib/singleton.ts +28 -0
- package/src/lib/stdin-parser.test.ts +2290 -0
- package/src/lib/stdin-parser.ts +1810 -0
- package/src/lib/styled-text.ts +178 -0
- package/src/lib/terminal-capability-detection.test.ts +202 -0
- package/src/lib/terminal-capability-detection.ts +79 -0
- package/src/lib/terminal-palette.test.ts +878 -0
- package/src/lib/terminal-palette.ts +383 -0
- package/src/lib/tree-sitter/assets/README.md +118 -0
- package/src/lib/tree-sitter/assets/update.ts +334 -0
- package/src/lib/tree-sitter/assets.d.ts +9 -0
- package/src/lib/tree-sitter/cache.test.ts +273 -0
- package/src/lib/tree-sitter/client.test.ts +1165 -0
- package/src/lib/tree-sitter/client.ts +607 -0
- package/src/lib/tree-sitter/default-parsers.ts +86 -0
- package/src/lib/tree-sitter/download-utils.ts +148 -0
- package/src/lib/tree-sitter/index.ts +28 -0
- package/src/lib/tree-sitter/parser.worker.ts +1042 -0
- package/src/lib/tree-sitter/parsers-config.ts +81 -0
- package/src/lib/tree-sitter/resolve-ft.test.ts +55 -0
- package/src/lib/tree-sitter/resolve-ft.ts +189 -0
- package/src/lib/tree-sitter/types.ts +82 -0
- package/src/lib/tree-sitter-styled-text.test.ts +1253 -0
- package/src/lib/tree-sitter-styled-text.ts +306 -0
- package/src/lib/validate-dir-name.ts +55 -0
- package/src/lib/yoga.options.test.ts +628 -0
- package/src/lib/yoga.options.ts +346 -0
- package/src/plugins/core-slot.ts +579 -0
- package/src/plugins/registry.ts +402 -0
- package/src/plugins/types.ts +46 -0
- package/src/post/effects.ts +930 -0
- package/src/post/filters.ts +489 -0
- package/src/post/matrices.ts +288 -0
- package/src/renderables/ASCIIFont.ts +219 -0
- package/src/renderables/Box.test.ts +205 -0
- package/src/renderables/Box.ts +326 -0
- package/src/renderables/Code.test.ts +2062 -0
- package/src/renderables/Code.ts +357 -0
- package/src/renderables/Diff.regression.test.ts +226 -0
- package/src/renderables/Diff.test.ts +3101 -0
- package/src/renderables/Diff.ts +1211 -0
- package/src/renderables/EditBufferRenderable.test.ts +288 -0
- package/src/renderables/EditBufferRenderable.ts +1166 -0
- package/src/renderables/FrameBuffer.ts +47 -0
- package/src/renderables/Input.test.ts +1228 -0
- package/src/renderables/Input.ts +247 -0
- package/src/renderables/LineNumberRenderable.ts +724 -0
- package/src/renderables/Markdown.ts +1393 -0
- package/src/renderables/ScrollBar.ts +422 -0
- package/src/renderables/ScrollBox.ts +883 -0
- package/src/renderables/Select.test.ts +1033 -0
- package/src/renderables/Select.ts +524 -0
- package/src/renderables/Slider.test.ts +456 -0
- package/src/renderables/Slider.ts +342 -0
- package/src/renderables/TabSelect.test.ts +197 -0
- package/src/renderables/TabSelect.ts +455 -0
- package/src/renderables/Text.selection-buffer.test.ts +123 -0
- package/src/renderables/Text.test.ts +2660 -0
- package/src/renderables/Text.ts +147 -0
- package/src/renderables/TextBufferRenderable.ts +518 -0
- package/src/renderables/TextNode.test.ts +1058 -0
- package/src/renderables/TextNode.ts +325 -0
- package/src/renderables/TextTable.test.ts +1421 -0
- package/src/renderables/TextTable.ts +1344 -0
- package/src/renderables/Textarea.ts +430 -0
- package/src/renderables/TimeToFirstDraw.ts +89 -0
- package/src/renderables/__snapshots__/Code.test.ts.snap +13 -0
- package/src/renderables/__snapshots__/Diff.test.ts.snap +785 -0
- package/src/renderables/__snapshots__/Text.test.ts.snap +421 -0
- package/src/renderables/__snapshots__/TextTable.test.ts.snap +215 -0
- package/src/renderables/__tests__/LineNumberRenderable.scrollbox-simple.test.ts +144 -0
- package/src/renderables/__tests__/LineNumberRenderable.scrollbox.test.ts +816 -0
- package/src/renderables/__tests__/LineNumberRenderable.test.ts +1865 -0
- package/src/renderables/__tests__/LineNumberRenderable.wrapping.test.ts +85 -0
- package/src/renderables/__tests__/Markdown.code-colors.test.ts +242 -0
- package/src/renderables/__tests__/Markdown.test.ts +2518 -0
- package/src/renderables/__tests__/MultiRenderable.selection.test.ts +87 -0
- package/src/renderables/__tests__/Textarea.buffer.test.ts +682 -0
- package/src/renderables/__tests__/Textarea.destroyed-events.test.ts +675 -0
- package/src/renderables/__tests__/Textarea.editing.test.ts +2041 -0
- package/src/renderables/__tests__/Textarea.error-handling.test.ts +35 -0
- package/src/renderables/__tests__/Textarea.events.test.ts +738 -0
- package/src/renderables/__tests__/Textarea.highlights.test.ts +590 -0
- package/src/renderables/__tests__/Textarea.keybinding.test.ts +3149 -0
- package/src/renderables/__tests__/Textarea.paste.test.ts +357 -0
- package/src/renderables/__tests__/Textarea.rendering.test.ts +1866 -0
- package/src/renderables/__tests__/Textarea.scroll.test.ts +733 -0
- package/src/renderables/__tests__/Textarea.selection.test.ts +1590 -0
- package/src/renderables/__tests__/Textarea.stress.test.ts +670 -0
- package/src/renderables/__tests__/Textarea.undo-redo.test.ts +383 -0
- package/src/renderables/__tests__/Textarea.visual-lines.test.ts +310 -0
- package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.code.test.ts.snap +221 -0
- package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox-simple.test.ts.snap +89 -0
- package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox.test.ts.snap +457 -0
- package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.test.ts.snap +158 -0
- package/src/renderables/__tests__/__snapshots__/Textarea.rendering.test.ts.snap +387 -0
- package/src/renderables/__tests__/markdown-parser.test.ts +217 -0
- package/src/renderables/__tests__/renderable-test-utils.ts +60 -0
- package/src/renderables/composition/README.md +8 -0
- package/src/renderables/composition/VRenderable.ts +32 -0
- package/src/renderables/composition/constructs.ts +127 -0
- package/src/renderables/composition/vnode.ts +289 -0
- package/src/renderables/index.ts +23 -0
- package/src/renderables/markdown-parser.ts +66 -0
- package/src/renderer.ts +2681 -0
- package/src/runtime-plugin-support.ts +39 -0
- package/src/runtime-plugin.ts +615 -0
- package/src/syntax-style.test.ts +841 -0
- package/src/syntax-style.ts +257 -0
- package/src/testing/README.md +210 -0
- package/src/testing/capture-spans.test.ts +194 -0
- package/src/testing/integration.test.ts +276 -0
- package/src/testing/manual-clock.ts +117 -0
- package/src/testing/mock-keys.test.ts +1378 -0
- package/src/testing/mock-keys.ts +457 -0
- package/src/testing/mock-mouse.test.ts +218 -0
- package/src/testing/mock-mouse.ts +247 -0
- package/src/testing/mock-tree-sitter-client.ts +73 -0
- package/src/testing/spy.ts +13 -0
- package/src/testing/test-recorder.test.ts +415 -0
- package/src/testing/test-recorder.ts +145 -0
- package/src/testing/test-renderer.ts +132 -0
- package/src/testing.ts +7 -0
- package/src/tests/__snapshots__/absolute-positioning.snapshot.test.ts.snap +481 -0
- package/src/tests/__snapshots__/renderable.snapshot.test.ts.snap +19 -0
- package/src/tests/__snapshots__/scrollbox.test.ts.snap +29 -0
- package/src/tests/absolute-positioning.snapshot.test.ts +638 -0
- package/src/tests/allocator-stats.test.ts +38 -0
- package/src/tests/destroy-during-render.test.ts +200 -0
- package/src/tests/destroy-on-exit.fixture.ts +36 -0
- package/src/tests/destroy-on-exit.test.ts +41 -0
- package/src/tests/hover-cursor.test.ts +98 -0
- package/src/tests/native-span-feed-async.test.ts +173 -0
- package/src/tests/native-span-feed-close.test.ts +120 -0
- package/src/tests/native-span-feed-coverage.test.ts +227 -0
- package/src/tests/native-span-feed-edge-cases.test.ts +352 -0
- package/src/tests/native-span-feed-use-after-free.test.ts +45 -0
- package/src/tests/opacity.test.ts +123 -0
- package/src/tests/renderable.snapshot.test.ts +524 -0
- package/src/tests/renderable.test.ts +1281 -0
- package/src/tests/renderer.clock.test.ts +158 -0
- package/src/tests/renderer.console-startup.test.ts +185 -0
- package/src/tests/renderer.control.test.ts +425 -0
- package/src/tests/renderer.core-slot-binding.test.ts +952 -0
- package/src/tests/renderer.cursor.test.ts +26 -0
- package/src/tests/renderer.destroy-during-render.test.ts +147 -0
- package/src/tests/renderer.focus-restore.test.ts +257 -0
- package/src/tests/renderer.focus.test.ts +294 -0
- package/src/tests/renderer.idle.test.ts +219 -0
- package/src/tests/renderer.input.test.ts +2237 -0
- package/src/tests/renderer.kitty-flags.test.ts +195 -0
- package/src/tests/renderer.mouse.test.ts +1274 -0
- package/src/tests/renderer.palette.test.ts +629 -0
- package/src/tests/renderer.selection.test.ts +49 -0
- package/src/tests/renderer.slot-registry.test.ts +684 -0
- package/src/tests/renderer.useMouse.test.ts +47 -0
- package/src/tests/runtime-plugin-node-modules-cycle.fixture.ts +76 -0
- package/src/tests/runtime-plugin-node-modules-mjs.fixture.ts +43 -0
- package/src/tests/runtime-plugin-node-modules-no-bare-rewrite.fixture.ts +67 -0
- package/src/tests/runtime-plugin-node-modules-package-type-cache.fixture.ts +72 -0
- package/src/tests/runtime-plugin-node-modules-runtime-specifier.fixture.ts +44 -0
- package/src/tests/runtime-plugin-node-modules-scoped-package-bare-rewrite.fixture.ts +85 -0
- package/src/tests/runtime-plugin-path-alias.fixture.ts +43 -0
- package/src/tests/runtime-plugin-resolve-roots.fixture.ts +65 -0
- package/src/tests/runtime-plugin-support.fixture.ts +11 -0
- package/src/tests/runtime-plugin-support.test.ts +19 -0
- package/src/tests/runtime-plugin-windows-file-url.fixture.ts +30 -0
- package/src/tests/runtime-plugin.fixture.ts +40 -0
- package/src/tests/runtime-plugin.test.ts +354 -0
- package/src/tests/scrollbox-culling-bug.test.ts +114 -0
- package/src/tests/scrollbox-hitgrid-resize.test.ts +136 -0
- package/src/tests/scrollbox-hitgrid.test.ts +909 -0
- package/src/tests/scrollbox.test.ts +1530 -0
- package/src/tests/wrap-resize-perf.test.ts +276 -0
- package/src/tests/yoga-setters.test.ts +921 -0
- package/src/text-buffer-view.test.ts +705 -0
- package/src/text-buffer-view.ts +189 -0
- package/src/text-buffer.test.ts +347 -0
- package/src/text-buffer.ts +250 -0
- package/src/types.ts +161 -0
- package/src/utils.ts +88 -0
- package/src/zig/ansi.zig +268 -0
- package/src/zig/bench/README.md +50 -0
- package/src/zig/bench/buffer-draw-text-buffer_bench.zig +887 -0
- package/src/zig/bench/edit-buffer_bench.zig +476 -0
- package/src/zig/bench/native-span-feed_bench.zig +100 -0
- package/src/zig/bench/rope-markers_bench.zig +713 -0
- package/src/zig/bench/rope_bench.zig +514 -0
- package/src/zig/bench/styled-text_bench.zig +470 -0
- package/src/zig/bench/text-buffer-coords_bench.zig +362 -0
- package/src/zig/bench/text-buffer-view_bench.zig +459 -0
- package/src/zig/bench/text-chunk-graphemes_bench.zig +273 -0
- package/src/zig/bench/utf8_bench.zig +799 -0
- package/src/zig/bench-utils.zig +431 -0
- package/src/zig/bench.zig +217 -0
- package/src/zig/buffer-methods.zig +211 -0
- package/src/zig/buffer.zig +2281 -0
- package/src/zig/build.zig +289 -0
- package/src/zig/build.zig.zon +16 -0
- package/src/zig/edit-buffer.zig +825 -0
- package/src/zig/editor-view.zig +802 -0
- package/src/zig/event-bus.zig +13 -0
- package/src/zig/event-emitter.zig +65 -0
- package/src/zig/file-logger.zig +92 -0
- package/src/zig/grapheme.zig +599 -0
- package/src/zig/lib.zig +1854 -0
- package/src/zig/link.zig +333 -0
- package/src/zig/logger.zig +43 -0
- package/src/zig/mem-registry.zig +125 -0
- package/src/zig/native-span-feed-bench-lib.zig +7 -0
- package/src/zig/native-span-feed.zig +708 -0
- package/src/zig/renderer.zig +1393 -0
- package/src/zig/rope.zig +1220 -0
- package/src/zig/syntax-style.zig +161 -0
- package/src/zig/terminal.zig +987 -0
- package/src/zig/test.zig +72 -0
- package/src/zig/tests/README.md +18 -0
- package/src/zig/tests/buffer-methods_test.zig +1109 -0
- package/src/zig/tests/buffer_test.zig +2557 -0
- package/src/zig/tests/edit-buffer-history_test.zig +271 -0
- package/src/zig/tests/edit-buffer_test.zig +1689 -0
- package/src/zig/tests/editor-view_test.zig +3299 -0
- package/src/zig/tests/event-emitter_test.zig +249 -0
- package/src/zig/tests/grapheme_test.zig +1304 -0
- package/src/zig/tests/link_test.zig +190 -0
- package/src/zig/tests/mem-registry_test.zig +473 -0
- package/src/zig/tests/memory_leak_regression_test.zig +159 -0
- package/src/zig/tests/native-span-feed_test.zig +1264 -0
- package/src/zig/tests/renderer_test.zig +1017 -0
- package/src/zig/tests/rope-nested_test.zig +712 -0
- package/src/zig/tests/rope_fuzz_test.zig +238 -0
- package/src/zig/tests/rope_test.zig +2362 -0
- package/src/zig/tests/segment-merge.test.zig +148 -0
- package/src/zig/tests/syntax-style_test.zig +557 -0
- package/src/zig/tests/terminal_test.zig +754 -0
- package/src/zig/tests/text-buffer-drawing_test.zig +3237 -0
- package/src/zig/tests/text-buffer-highlights_test.zig +666 -0
- package/src/zig/tests/text-buffer-iterators_test.zig +776 -0
- package/src/zig/tests/text-buffer-segment_test.zig +320 -0
- package/src/zig/tests/text-buffer-selection_test.zig +1035 -0
- package/src/zig/tests/text-buffer-selection_viewport_test.zig +358 -0
- package/src/zig/tests/text-buffer-view_test.zig +3649 -0
- package/src/zig/tests/text-buffer_test.zig +2191 -0
- package/src/zig/tests/unicode-width-map.zon +3909 -0
- package/src/zig/tests/utf8_no_zwj_test.zig +260 -0
- package/src/zig/tests/utf8_test.zig +4057 -0
- package/src/zig/tests/utf8_wcwidth_cursor_test.zig +267 -0
- package/src/zig/tests/utf8_wcwidth_test.zig +357 -0
- package/src/zig/tests/word-wrap-editing_test.zig +498 -0
- package/src/zig/tests/wrap-cache-perf_test.zig +113 -0
- package/src/zig/text-buffer-iterators.zig +499 -0
- package/src/zig/text-buffer-segment.zig +404 -0
- package/src/zig/text-buffer-view.zig +1371 -0
- package/src/zig/text-buffer.zig +1180 -0
- package/src/zig/utf8.zig +1948 -0
- package/src/zig/utils.zig +9 -0
- package/src/zig-structs.ts +261 -0
- package/src/zig.ts +3884 -0
- package/tsconfig.build.json +24 -0
- package/tsconfig.json +27 -0
- package/3d/SpriteResourceManager.d.ts +0 -74
- package/3d/SpriteUtils.d.ts +0 -13
- package/3d/TextureUtils.d.ts +0 -24
- package/3d/ThreeRenderable.d.ts +0 -40
- package/3d/WGPURenderer.d.ts +0 -61
- package/3d/animation/ExplodingSpriteEffect.d.ts +0 -71
- package/3d/animation/PhysicsExplodingSpriteEffect.d.ts +0 -76
- package/3d/animation/SpriteAnimator.d.ts +0 -124
- package/3d/animation/SpriteParticleGenerator.d.ts +0 -62
- package/3d/canvas.d.ts +0 -44
- package/3d/index.d.ts +0 -12
- package/3d/physics/PlanckPhysicsAdapter.d.ts +0 -19
- package/3d/physics/RapierPhysicsAdapter.d.ts +0 -19
- package/3d/physics/physics-interface.d.ts +0 -27
- package/3d.d.ts +0 -2
- package/3d.js +0 -34041
- package/3d.js.map +0 -155
- package/LICENSE +0 -21
- package/NativeSpanFeed.d.ts +0 -41
- package/Renderable.d.ts +0 -334
- package/animation/Timeline.d.ts +0 -126
- package/ansi.d.ts +0 -13
- package/buffer.d.ts +0 -111
- package/console.d.ts +0 -144
- package/edit-buffer.d.ts +0 -98
- package/editor-view.d.ts +0 -73
- package/index-9vwc3fg6.js +0 -12260
- package/index-9vwc3fg6.js.map +0 -42
- package/index-dcj62y8t.js +0 -20614
- package/index-dcj62y8t.js.map +0 -67
- package/index-f7n39gpy.js +0 -411
- package/index-f7n39gpy.js.map +0 -10
- package/index.d.ts +0 -23
- package/index.js +0 -478
- package/index.js.map +0 -9
- package/lib/KeyHandler.d.ts +0 -61
- package/lib/RGBA.d.ts +0 -25
- package/lib/ascii.font.d.ts +0 -508
- package/lib/border.d.ts +0 -51
- package/lib/bunfs.d.ts +0 -7
- package/lib/clipboard.d.ts +0 -17
- package/lib/clock.d.ts +0 -15
- package/lib/data-paths.d.ts +0 -26
- package/lib/debounce.d.ts +0 -42
- package/lib/detect-links.d.ts +0 -6
- package/lib/env.d.ts +0 -42
- package/lib/extmarks-history.d.ts +0 -17
- package/lib/extmarks.d.ts +0 -89
- package/lib/hast-styled-text.d.ts +0 -17
- package/lib/index.d.ts +0 -21
- package/lib/keymapping.d.ts +0 -25
- package/lib/objects-in-viewport.d.ts +0 -24
- package/lib/output.capture.d.ts +0 -24
- package/lib/parse.keypress-kitty.d.ts +0 -2
- package/lib/parse.keypress.d.ts +0 -26
- package/lib/parse.mouse.d.ts +0 -30
- package/lib/paste.d.ts +0 -7
- package/lib/queue.d.ts +0 -15
- package/lib/renderable.validations.d.ts +0 -12
- package/lib/scroll-acceleration.d.ts +0 -43
- package/lib/selection.d.ts +0 -63
- package/lib/singleton.d.ts +0 -7
- package/lib/stdin-parser.d.ts +0 -87
- package/lib/styled-text.d.ts +0 -63
- package/lib/terminal-capability-detection.d.ts +0 -30
- package/lib/terminal-palette.d.ts +0 -50
- package/lib/tree-sitter/assets/update.d.ts +0 -11
- package/lib/tree-sitter/client.d.ts +0 -47
- package/lib/tree-sitter/default-parsers.d.ts +0 -2
- package/lib/tree-sitter/download-utils.d.ts +0 -21
- package/lib/tree-sitter/index.d.ts +0 -8
- package/lib/tree-sitter/parser.worker.d.ts +0 -1
- package/lib/tree-sitter/parsers-config.d.ts +0 -53
- package/lib/tree-sitter/resolve-ft.d.ts +0 -5
- package/lib/tree-sitter/types.d.ts +0 -82
- package/lib/tree-sitter-styled-text.d.ts +0 -14
- package/lib/validate-dir-name.d.ts +0 -1
- package/lib/yoga.options.d.ts +0 -32
- package/parser.worker.js +0 -899
- package/parser.worker.js.map +0 -12
- package/plugins/core-slot.d.ts +0 -72
- package/plugins/registry.d.ts +0 -42
- package/plugins/types.d.ts +0 -34
- package/post/effects.d.ts +0 -147
- package/post/filters.d.ts +0 -65
- package/post/matrices.d.ts +0 -20
- package/renderables/ASCIIFont.d.ts +0 -52
- package/renderables/Box.d.ts +0 -81
- package/renderables/Code.d.ts +0 -78
- package/renderables/Diff.d.ts +0 -142
- package/renderables/EditBufferRenderable.d.ts +0 -237
- package/renderables/FrameBuffer.d.ts +0 -16
- package/renderables/Input.d.ts +0 -67
- package/renderables/LineNumberRenderable.d.ts +0 -78
- package/renderables/Markdown.d.ts +0 -185
- package/renderables/ScrollBar.d.ts +0 -77
- package/renderables/ScrollBox.d.ts +0 -124
- package/renderables/Select.d.ts +0 -115
- package/renderables/Slider.d.ts +0 -47
- package/renderables/TabSelect.d.ts +0 -96
- package/renderables/Text.d.ts +0 -36
- package/renderables/TextBufferRenderable.d.ts +0 -105
- package/renderables/TextNode.d.ts +0 -91
- package/renderables/TextTable.d.ts +0 -140
- package/renderables/Textarea.d.ts +0 -63
- package/renderables/TimeToFirstDraw.d.ts +0 -24
- package/renderables/__tests__/renderable-test-utils.d.ts +0 -12
- package/renderables/composition/VRenderable.d.ts +0 -16
- package/renderables/composition/constructs.d.ts +0 -35
- package/renderables/composition/vnode.d.ts +0 -46
- package/renderables/index.d.ts +0 -23
- package/renderables/markdown-parser.d.ts +0 -10
- package/renderer.d.ts +0 -419
- package/runtime-plugin-support.d.ts +0 -3
- package/runtime-plugin-support.js +0 -29
- package/runtime-plugin-support.js.map +0 -10
- package/runtime-plugin.d.ts +0 -16
- package/runtime-plugin.js +0 -16
- package/runtime-plugin.js.map +0 -9
- package/syntax-style.d.ts +0 -54
- package/testing/manual-clock.d.ts +0 -17
- package/testing/mock-keys.d.ts +0 -81
- package/testing/mock-mouse.d.ts +0 -38
- package/testing/mock-tree-sitter-client.d.ts +0 -23
- package/testing/spy.d.ts +0 -7
- package/testing/test-recorder.d.ts +0 -61
- package/testing/test-renderer.d.ts +0 -23
- package/testing.d.ts +0 -6
- package/testing.js +0 -697
- package/testing.js.map +0 -15
- package/text-buffer-view.d.ts +0 -42
- package/text-buffer.d.ts +0 -67
- package/types.d.ts +0 -139
- package/utils.d.ts +0 -14
- package/zig-structs.d.ts +0 -155
- package/zig.d.ts +0 -353
- /package/{assets → src/lib/tree-sitter/assets}/javascript/highlights.scm +0 -0
- /package/{assets → src/lib/tree-sitter/assets}/javascript/tree-sitter-javascript.wasm +0 -0
- /package/{assets → src/lib/tree-sitter/assets}/markdown/highlights.scm +0 -0
- /package/{assets → src/lib/tree-sitter/assets}/markdown/injections.scm +0 -0
- /package/{assets → src/lib/tree-sitter/assets}/markdown/tree-sitter-markdown.wasm +0 -0
- /package/{assets → src/lib/tree-sitter/assets}/markdown_inline/highlights.scm +0 -0
- /package/{assets → src/lib/tree-sitter/assets}/markdown_inline/tree-sitter-markdown_inline.wasm +0 -0
- /package/{assets → src/lib/tree-sitter/assets}/typescript/highlights.scm +0 -0
- /package/{assets → src/lib/tree-sitter/assets}/typescript/tree-sitter-typescript.wasm +0 -0
- /package/{assets → src/lib/tree-sitter/assets}/zig/highlights.scm +0 -0
- /package/{assets → src/lib/tree-sitter/assets}/zig/tree-sitter-zig.wasm +0 -0
|
@@ -0,0 +1,712 @@
|
|
|
1
|
+
const std = @import("std");
|
|
2
|
+
const rope_mod = @import("../rope.zig");
|
|
3
|
+
|
|
4
|
+
// NOTE: This is not strictly necessary to be supported as it is not used this way in the codebase.
|
|
5
|
+
// It can be removed if the rope needs to change in a way that would break this behavior.
|
|
6
|
+
|
|
7
|
+
const Chunk = struct {
|
|
8
|
+
data: []const u8,
|
|
9
|
+
width: u32,
|
|
10
|
+
|
|
11
|
+
pub const Metrics = struct {
|
|
12
|
+
total_width: u32 = 0,
|
|
13
|
+
total_bytes: u32 = 0,
|
|
14
|
+
|
|
15
|
+
pub fn add(self: *Metrics, other: Metrics) void {
|
|
16
|
+
self.total_width += other.total_width;
|
|
17
|
+
self.total_bytes += other.total_bytes;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
pub fn measure(self: *const Chunk) Metrics {
|
|
22
|
+
return .{
|
|
23
|
+
.total_width = self.width,
|
|
24
|
+
.total_bytes = @intCast(self.data.len),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
pub fn empty() Chunk {
|
|
29
|
+
return .{ .data = "", .width = 0 };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
pub fn is_empty(self: *const Chunk) bool {
|
|
33
|
+
return self.data.len == 0;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Static empty chunk rope node for Line.empty()
|
|
38
|
+
const empty_chunk_leaf_node = rope_mod.Rope(Chunk).Node{
|
|
39
|
+
.leaf = .{
|
|
40
|
+
.data = Chunk.empty(),
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// Line type containing a rope of chunks
|
|
45
|
+
const Line = struct {
|
|
46
|
+
chunks: rope_mod.Rope(Chunk),
|
|
47
|
+
line_id: u32,
|
|
48
|
+
|
|
49
|
+
pub const Metrics = struct {
|
|
50
|
+
total_width: u32 = 0,
|
|
51
|
+
total_lines: u32 = 1,
|
|
52
|
+
|
|
53
|
+
pub fn add(self: *Metrics, other: Metrics) void {
|
|
54
|
+
self.total_width += other.total_width;
|
|
55
|
+
self.total_lines += other.total_lines;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
pub fn measure(self: *const Line) Metrics {
|
|
60
|
+
const chunk_metrics = self.chunks.root.metrics();
|
|
61
|
+
return .{
|
|
62
|
+
.total_width = chunk_metrics.custom.total_width,
|
|
63
|
+
.total_lines = 1,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
pub fn empty() Line {
|
|
68
|
+
// Use static empty chunk rope - safe because it's immutable
|
|
69
|
+
const ChunkRope = rope_mod.Rope(Chunk);
|
|
70
|
+
return .{
|
|
71
|
+
.chunks = .{
|
|
72
|
+
.root = &empty_chunk_leaf_node,
|
|
73
|
+
.allocator = undefined, // Never used for empty
|
|
74
|
+
.empty_leaf = &empty_chunk_leaf_node,
|
|
75
|
+
.marker_cache = ChunkRope.MarkerCache.init(undefined),
|
|
76
|
+
},
|
|
77
|
+
.line_id = 0,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
pub fn is_empty(self: *const Line) bool {
|
|
82
|
+
return self.line_id == 0 and self.chunks.count() == 1;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
test "Nested Rope - create line with chunks" {
|
|
87
|
+
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
|
88
|
+
defer arena.deinit();
|
|
89
|
+
const allocator = arena.allocator();
|
|
90
|
+
|
|
91
|
+
const chunks = [_]Chunk{
|
|
92
|
+
.{ .data = "Hello ", .width = 6 },
|
|
93
|
+
.{ .data = "World", .width = 5 },
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const chunk_rope = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks);
|
|
97
|
+
|
|
98
|
+
const line = Line{
|
|
99
|
+
.chunks = chunk_rope,
|
|
100
|
+
.line_id = 1,
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
try std.testing.expectEqual(@as(u32, 2), line.chunks.count());
|
|
104
|
+
try std.testing.expectEqualStrings("Hello ", line.chunks.get(0).?.data);
|
|
105
|
+
try std.testing.expectEqualStrings("World", line.chunks.get(1).?.data);
|
|
106
|
+
|
|
107
|
+
const metrics = line.measure();
|
|
108
|
+
try std.testing.expectEqual(@as(u32, 11), metrics.total_width); // 6 + 5
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
test "Nested Rope - rope of lines with chunks" {
|
|
112
|
+
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
|
113
|
+
defer arena.deinit();
|
|
114
|
+
const allocator = arena.allocator();
|
|
115
|
+
|
|
116
|
+
const chunks1 = [_]Chunk{
|
|
117
|
+
.{ .data = "Line ", .width = 5 },
|
|
118
|
+
.{ .data = "One", .width = 3 },
|
|
119
|
+
};
|
|
120
|
+
const line1 = Line{
|
|
121
|
+
.chunks = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks1),
|
|
122
|
+
.line_id = 1,
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const chunks2 = [_]Chunk{
|
|
126
|
+
.{ .data = "Line ", .width = 5 },
|
|
127
|
+
.{ .data = "Two", .width = 3 },
|
|
128
|
+
};
|
|
129
|
+
const line2 = Line{
|
|
130
|
+
.chunks = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks2),
|
|
131
|
+
.line_id = 2,
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const lines = [_]Line{ line1, line2 };
|
|
135
|
+
var line_rope = try rope_mod.Rope(Line).from_slice(allocator, &lines);
|
|
136
|
+
|
|
137
|
+
try std.testing.expectEqual(@as(u32, 2), line_rope.count());
|
|
138
|
+
|
|
139
|
+
// Access nested data
|
|
140
|
+
const first_line = line_rope.get(0).?;
|
|
141
|
+
try std.testing.expectEqual(@as(u32, 1), first_line.line_id);
|
|
142
|
+
try std.testing.expectEqual(@as(u32, 2), first_line.chunks.count());
|
|
143
|
+
try std.testing.expectEqualStrings("Line ", first_line.chunks.get(0).?.data);
|
|
144
|
+
|
|
145
|
+
const second_line = line_rope.get(1).?;
|
|
146
|
+
try std.testing.expectEqual(@as(u32, 2), second_line.line_id);
|
|
147
|
+
try std.testing.expectEqualStrings("Two", second_line.chunks.get(1).?.data);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
test "Nested Rope - insert chunk into line" {
|
|
151
|
+
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
|
152
|
+
defer arena.deinit();
|
|
153
|
+
const allocator = arena.allocator();
|
|
154
|
+
|
|
155
|
+
const chunks = [_]Chunk{
|
|
156
|
+
.{ .data = "Hello ", .width = 6 },
|
|
157
|
+
.{ .data = "World", .width = 5 },
|
|
158
|
+
};
|
|
159
|
+
var chunk_rope = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks);
|
|
160
|
+
|
|
161
|
+
try chunk_rope.insert(1, .{ .data = "Beautiful ", .width = 10 });
|
|
162
|
+
|
|
163
|
+
try std.testing.expectEqual(@as(u32, 3), chunk_rope.count());
|
|
164
|
+
try std.testing.expectEqualStrings("Hello ", chunk_rope.get(0).?.data);
|
|
165
|
+
try std.testing.expectEqualStrings("Beautiful ", chunk_rope.get(1).?.data);
|
|
166
|
+
try std.testing.expectEqualStrings("World", chunk_rope.get(2).?.data);
|
|
167
|
+
|
|
168
|
+
const metrics = chunk_rope.root.metrics();
|
|
169
|
+
try std.testing.expectEqual(@as(u32, 21), metrics.custom.total_width); // 6 + 10 + 5
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
test "Nested Rope - delete chunk from line" {
|
|
173
|
+
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
|
174
|
+
defer arena.deinit();
|
|
175
|
+
const allocator = arena.allocator();
|
|
176
|
+
|
|
177
|
+
const chunks = [_]Chunk{
|
|
178
|
+
.{ .data = "A ", .width = 2 },
|
|
179
|
+
.{ .data = "B ", .width = 2 },
|
|
180
|
+
.{ .data = "C", .width = 1 },
|
|
181
|
+
};
|
|
182
|
+
var chunk_rope = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks);
|
|
183
|
+
|
|
184
|
+
try chunk_rope.delete(1);
|
|
185
|
+
|
|
186
|
+
try std.testing.expectEqual(@as(u32, 2), chunk_rope.count());
|
|
187
|
+
try std.testing.expectEqualStrings("A ", chunk_rope.get(0).?.data);
|
|
188
|
+
try std.testing.expectEqualStrings("C", chunk_rope.get(1).?.data);
|
|
189
|
+
|
|
190
|
+
const metrics = chunk_rope.root.metrics();
|
|
191
|
+
try std.testing.expectEqual(@as(u32, 3), metrics.custom.total_width); // 2 + 1
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
test "Nested Rope - walk through lines and chunks" {
|
|
195
|
+
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
|
196
|
+
defer arena.deinit();
|
|
197
|
+
const allocator = arena.allocator();
|
|
198
|
+
|
|
199
|
+
const chunks1 = [_]Chunk{.{ .data = "Line1", .width = 5 }};
|
|
200
|
+
const chunks2 = [_]Chunk{.{ .data = "Line2", .width = 5 }};
|
|
201
|
+
const chunks3 = [_]Chunk{.{ .data = "Line3", .width = 5 }};
|
|
202
|
+
|
|
203
|
+
const lines = [_]Line{
|
|
204
|
+
.{ .chunks = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks1), .line_id = 1 },
|
|
205
|
+
.{ .chunks = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks2), .line_id = 2 },
|
|
206
|
+
.{ .chunks = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks3), .line_id = 3 },
|
|
207
|
+
};
|
|
208
|
+
var line_rope = try rope_mod.Rope(Line).from_slice(allocator, &lines);
|
|
209
|
+
|
|
210
|
+
const LineContext = struct {
|
|
211
|
+
total_lines: u32 = 0,
|
|
212
|
+
total_width: u32 = 0,
|
|
213
|
+
|
|
214
|
+
fn walker(ctx: *anyopaque, line: *const Line, index: u32) rope_mod.Rope(Line).Node.WalkerResult {
|
|
215
|
+
_ = index;
|
|
216
|
+
const self = @as(*@This(), @ptrCast(@alignCast(ctx)));
|
|
217
|
+
self.total_lines += 1;
|
|
218
|
+
|
|
219
|
+
const metrics = line.chunks.root.metrics();
|
|
220
|
+
self.total_width += metrics.custom.total_width;
|
|
221
|
+
return .{};
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
var ctx = LineContext{};
|
|
226
|
+
try line_rope.walk(&ctx, LineContext.walker);
|
|
227
|
+
|
|
228
|
+
try std.testing.expectEqual(@as(u32, 3), ctx.total_lines);
|
|
229
|
+
try std.testing.expectEqual(@as(u32, 15), ctx.total_width); // 5 + 5 + 5
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
test "Nested Rope - complex line and chunk operations" {
|
|
233
|
+
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
|
234
|
+
defer arena.deinit();
|
|
235
|
+
const allocator = arena.allocator();
|
|
236
|
+
|
|
237
|
+
const chunks1 = [_]Chunk{
|
|
238
|
+
.{ .data = "First ", .width = 6 },
|
|
239
|
+
.{ .data = "line", .width = 4 },
|
|
240
|
+
};
|
|
241
|
+
const line1 = Line{
|
|
242
|
+
.chunks = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks1),
|
|
243
|
+
.line_id = 1,
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
var line_rope = try rope_mod.Rope(Line).from_item(allocator, line1);
|
|
247
|
+
|
|
248
|
+
const chunks2 = [_]Chunk{.{ .data = "Second line", .width = 11 }};
|
|
249
|
+
const line2 = Line{
|
|
250
|
+
.chunks = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks2),
|
|
251
|
+
.line_id = 2,
|
|
252
|
+
};
|
|
253
|
+
try line_rope.append(line2);
|
|
254
|
+
|
|
255
|
+
try std.testing.expectEqual(@as(u32, 2), line_rope.count());
|
|
256
|
+
|
|
257
|
+
// Access specific chunk in specific line
|
|
258
|
+
const first_line = line_rope.get(0).?;
|
|
259
|
+
try std.testing.expectEqual(@as(u32, 2), first_line.chunks.count());
|
|
260
|
+
try std.testing.expectEqualStrings("First ", first_line.chunks.get(0).?.data);
|
|
261
|
+
|
|
262
|
+
const metrics = line_rope.root.metrics();
|
|
263
|
+
try std.testing.expectEqual(@as(u32, 2), metrics.count);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
test "Nested Rope - metrics propagate through all levels" {
|
|
267
|
+
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
|
268
|
+
defer arena.deinit();
|
|
269
|
+
const allocator = arena.allocator();
|
|
270
|
+
|
|
271
|
+
const chunks1 = [_]Chunk{
|
|
272
|
+
.{ .data = "abc", .width = 3 },
|
|
273
|
+
.{ .data = "def", .width = 3 },
|
|
274
|
+
};
|
|
275
|
+
const chunks2 = [_]Chunk{
|
|
276
|
+
.{ .data = "12345", .width = 5 },
|
|
277
|
+
};
|
|
278
|
+
const chunks3 = [_]Chunk{
|
|
279
|
+
.{ .data = "x", .width = 1 },
|
|
280
|
+
.{ .data = "y", .width = 1 },
|
|
281
|
+
.{ .data = "z", .width = 1 },
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
const lines = [_]Line{
|
|
285
|
+
.{ .chunks = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks1), .line_id = 1 },
|
|
286
|
+
.{ .chunks = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks2), .line_id = 2 },
|
|
287
|
+
.{ .chunks = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks3), .line_id = 3 },
|
|
288
|
+
};
|
|
289
|
+
var line_rope = try rope_mod.Rope(Line).from_slice(allocator, &lines);
|
|
290
|
+
|
|
291
|
+
const line_metrics = line_rope.root.metrics();
|
|
292
|
+
try std.testing.expectEqual(@as(u32, 3), line_metrics.count);
|
|
293
|
+
|
|
294
|
+
const line1 = line_rope.get(0).?;
|
|
295
|
+
const line1_metrics = line1.measure();
|
|
296
|
+
try std.testing.expectEqual(@as(u32, 6), line1_metrics.total_width); // 3 + 3
|
|
297
|
+
|
|
298
|
+
const line2 = line_rope.get(1).?;
|
|
299
|
+
const line2_metrics = line2.measure();
|
|
300
|
+
try std.testing.expectEqual(@as(u32, 5), line2_metrics.total_width);
|
|
301
|
+
|
|
302
|
+
const line3 = line_rope.get(2).?;
|
|
303
|
+
const line3_metrics = line3.measure();
|
|
304
|
+
try std.testing.expectEqual(@as(u32, 3), line3_metrics.total_width); // 1 + 1 + 1
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
test "Nested Rope - simulate text buffer edit: insert within line" {
|
|
308
|
+
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
|
309
|
+
defer arena.deinit();
|
|
310
|
+
const allocator = arena.allocator();
|
|
311
|
+
|
|
312
|
+
const initial_chunks = [_]Chunk{
|
|
313
|
+
.{ .data = "Hello ", .width = 6 },
|
|
314
|
+
.{ .data = "World", .width = 5 },
|
|
315
|
+
};
|
|
316
|
+
var chunk_rope = try rope_mod.Rope(Chunk).from_slice(allocator, &initial_chunks);
|
|
317
|
+
|
|
318
|
+
try chunk_rope.insert(1, .{ .data = "Beautiful ", .width = 10 });
|
|
319
|
+
|
|
320
|
+
try std.testing.expectEqual(@as(u32, 3), chunk_rope.count());
|
|
321
|
+
|
|
322
|
+
try std.testing.expectEqualStrings("Hello ", chunk_rope.get(0).?.data);
|
|
323
|
+
try std.testing.expectEqualStrings("Beautiful ", chunk_rope.get(1).?.data);
|
|
324
|
+
try std.testing.expectEqualStrings("World", chunk_rope.get(2).?.data);
|
|
325
|
+
|
|
326
|
+
const metrics = chunk_rope.root.metrics();
|
|
327
|
+
try std.testing.expectEqual(@as(u32, 21), metrics.custom.total_width);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
test "Nested Rope - simulate text buffer edit: delete within line" {
|
|
331
|
+
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
|
332
|
+
defer arena.deinit();
|
|
333
|
+
const allocator = arena.allocator();
|
|
334
|
+
|
|
335
|
+
const initial_chunks = [_]Chunk{
|
|
336
|
+
.{ .data = "Hello ", .width = 6 },
|
|
337
|
+
.{ .data = "Beautiful ", .width = 10 },
|
|
338
|
+
.{ .data = "World", .width = 5 },
|
|
339
|
+
};
|
|
340
|
+
var chunk_rope = try rope_mod.Rope(Chunk).from_slice(allocator, &initial_chunks);
|
|
341
|
+
|
|
342
|
+
try chunk_rope.delete(1);
|
|
343
|
+
|
|
344
|
+
try std.testing.expectEqual(@as(u32, 2), chunk_rope.count());
|
|
345
|
+
try std.testing.expectEqualStrings("Hello ", chunk_rope.get(0).?.data);
|
|
346
|
+
try std.testing.expectEqualStrings("World", chunk_rope.get(1).?.data);
|
|
347
|
+
|
|
348
|
+
const metrics = chunk_rope.root.metrics();
|
|
349
|
+
try std.testing.expectEqual(@as(u32, 11), metrics.custom.total_width);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
test "Nested Rope - insert line into document" {
|
|
353
|
+
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
|
354
|
+
defer arena.deinit();
|
|
355
|
+
const allocator = arena.allocator();
|
|
356
|
+
|
|
357
|
+
const chunks1 = [_]Chunk{.{ .data = "Line 1", .width = 6 }};
|
|
358
|
+
const chunks3 = [_]Chunk{.{ .data = "Line 3", .width = 6 }};
|
|
359
|
+
|
|
360
|
+
const initial_lines = [_]Line{
|
|
361
|
+
.{ .chunks = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks1), .line_id = 1 },
|
|
362
|
+
.{ .chunks = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks3), .line_id = 3 },
|
|
363
|
+
};
|
|
364
|
+
var line_rope = try rope_mod.Rope(Line).from_slice(allocator, &initial_lines);
|
|
365
|
+
|
|
366
|
+
const chunks2 = [_]Chunk{.{ .data = "Line 2", .width = 6 }};
|
|
367
|
+
const line2 = Line{
|
|
368
|
+
.chunks = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks2),
|
|
369
|
+
.line_id = 2,
|
|
370
|
+
};
|
|
371
|
+
try line_rope.insert(1, line2);
|
|
372
|
+
|
|
373
|
+
try std.testing.expectEqual(@as(u32, 3), line_rope.count());
|
|
374
|
+
try std.testing.expectEqual(@as(u32, 1), line_rope.get(0).?.line_id);
|
|
375
|
+
try std.testing.expectEqual(@as(u32, 2), line_rope.get(1).?.line_id);
|
|
376
|
+
try std.testing.expectEqual(@as(u32, 3), line_rope.get(2).?.line_id);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
test "Nested Rope - delete line from document" {
|
|
380
|
+
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
|
381
|
+
defer arena.deinit();
|
|
382
|
+
const allocator = arena.allocator();
|
|
383
|
+
|
|
384
|
+
const chunks1 = [_]Chunk{.{ .data = "Line 1", .width = 6 }};
|
|
385
|
+
const chunks2 = [_]Chunk{.{ .data = "Line 2", .width = 6 }};
|
|
386
|
+
const chunks3 = [_]Chunk{.{ .data = "Line 3", .width = 6 }};
|
|
387
|
+
|
|
388
|
+
const lines = [_]Line{
|
|
389
|
+
.{ .chunks = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks1), .line_id = 1 },
|
|
390
|
+
.{ .chunks = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks2), .line_id = 2 },
|
|
391
|
+
.{ .chunks = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks3), .line_id = 3 },
|
|
392
|
+
};
|
|
393
|
+
var line_rope = try rope_mod.Rope(Line).from_slice(allocator, &lines);
|
|
394
|
+
|
|
395
|
+
try line_rope.delete(1);
|
|
396
|
+
|
|
397
|
+
try std.testing.expectEqual(@as(u32, 2), line_rope.count());
|
|
398
|
+
try std.testing.expectEqual(@as(u32, 1), line_rope.get(0).?.line_id);
|
|
399
|
+
try std.testing.expectEqual(@as(u32, 3), line_rope.get(1).?.line_id);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
test "Nested Rope - modify chunks within a specific line" {
|
|
403
|
+
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
|
404
|
+
defer arena.deinit();
|
|
405
|
+
const allocator = arena.allocator();
|
|
406
|
+
|
|
407
|
+
const initial_chunks = [_]Chunk{
|
|
408
|
+
.{ .data = "Hello", .width = 5 },
|
|
409
|
+
};
|
|
410
|
+
var chunk_rope = try rope_mod.Rope(Chunk).from_slice(allocator, &initial_chunks);
|
|
411
|
+
|
|
412
|
+
try chunk_rope.insert(1, .{ .data = " World", .width = 6 });
|
|
413
|
+
|
|
414
|
+
const line = Line{
|
|
415
|
+
.chunks = chunk_rope,
|
|
416
|
+
.line_id = 1,
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
const lines = [_]Line{line};
|
|
420
|
+
var line_rope = try rope_mod.Rope(Line).from_slice(allocator, &lines);
|
|
421
|
+
|
|
422
|
+
const retrieved_line = line_rope.get(0).?;
|
|
423
|
+
try std.testing.expectEqual(@as(u32, 2), retrieved_line.chunks.count());
|
|
424
|
+
try std.testing.expectEqualStrings("Hello", retrieved_line.chunks.get(0).?.data);
|
|
425
|
+
try std.testing.expectEqualStrings(" World", retrieved_line.chunks.get(1).?.data);
|
|
426
|
+
|
|
427
|
+
const line_metrics = retrieved_line.measure();
|
|
428
|
+
try std.testing.expectEqual(@as(u32, 11), line_metrics.total_width);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
test "Nested Rope - walk all chunks in all lines" {
|
|
432
|
+
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
|
433
|
+
defer arena.deinit();
|
|
434
|
+
const allocator = arena.allocator();
|
|
435
|
+
|
|
436
|
+
const chunks1 = [_]Chunk{
|
|
437
|
+
.{ .data = "A", .width = 1 },
|
|
438
|
+
.{ .data = "B", .width = 1 },
|
|
439
|
+
};
|
|
440
|
+
const chunks2 = [_]Chunk{
|
|
441
|
+
.{ .data = "C", .width = 1 },
|
|
442
|
+
.{ .data = "D", .width = 1 },
|
|
443
|
+
.{ .data = "E", .width = 1 },
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
const lines = [_]Line{
|
|
447
|
+
.{ .chunks = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks1), .line_id = 1 },
|
|
448
|
+
.{ .chunks = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks2), .line_id = 2 },
|
|
449
|
+
};
|
|
450
|
+
var line_rope = try rope_mod.Rope(Line).from_slice(allocator, &lines);
|
|
451
|
+
|
|
452
|
+
var total_chunks: u32 = 0;
|
|
453
|
+
var total_bytes: u32 = 0;
|
|
454
|
+
|
|
455
|
+
const LineWalker = struct {
|
|
456
|
+
fn walk(ctx: *anyopaque, line: *const Line, index: u32) rope_mod.Rope(Line).Node.WalkerResult {
|
|
457
|
+
_ = index;
|
|
458
|
+
const counters = @as(*[2]u32, @ptrCast(@alignCast(ctx)));
|
|
459
|
+
|
|
460
|
+
// Count chunks in this line
|
|
461
|
+
const ChunkWalker = struct {
|
|
462
|
+
fn walk(chunk_ctx: *anyopaque, chunk: *const Chunk, chunk_idx: u32) rope_mod.Rope(Chunk).Node.WalkerResult {
|
|
463
|
+
_ = chunk_idx;
|
|
464
|
+
const chunk_counters = @as(*[2]u32, @ptrCast(@alignCast(chunk_ctx)));
|
|
465
|
+
chunk_counters[0] += 1; // total_chunks
|
|
466
|
+
chunk_counters[1] += @intCast(chunk.data.len); // total_bytes
|
|
467
|
+
return .{};
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
|
|
471
|
+
line.chunks.walk(counters, ChunkWalker.walk) catch {};
|
|
472
|
+
return .{};
|
|
473
|
+
}
|
|
474
|
+
};
|
|
475
|
+
|
|
476
|
+
var counters = [2]u32{ total_chunks, total_bytes };
|
|
477
|
+
try line_rope.walk(&counters, LineWalker.walk);
|
|
478
|
+
total_chunks = counters[0];
|
|
479
|
+
total_bytes = counters[1];
|
|
480
|
+
|
|
481
|
+
try std.testing.expectEqual(@as(u32, 5), total_chunks); // 2 + 3
|
|
482
|
+
try std.testing.expectEqual(@as(u32, 5), total_bytes); // All single char chunks
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
test "Nested Rope - simulate full text buffer workflow" {
|
|
486
|
+
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
|
487
|
+
defer arena.deinit();
|
|
488
|
+
const allocator = arena.allocator();
|
|
489
|
+
|
|
490
|
+
const chunks1 = [_]Chunk{
|
|
491
|
+
.{ .data = "Hello ", .width = 6 },
|
|
492
|
+
.{ .data = "World", .width = 5 },
|
|
493
|
+
};
|
|
494
|
+
const line1 = Line{
|
|
495
|
+
.chunks = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks1),
|
|
496
|
+
.line_id = 1,
|
|
497
|
+
};
|
|
498
|
+
|
|
499
|
+
var document = try rope_mod.Rope(Line).from_item(allocator, line1);
|
|
500
|
+
|
|
501
|
+
const chunks2 = [_]Chunk{.{ .data = "Goodbye", .width = 7 }};
|
|
502
|
+
const line2 = Line{
|
|
503
|
+
.chunks = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks2),
|
|
504
|
+
.line_id = 2,
|
|
505
|
+
};
|
|
506
|
+
try document.append(line2);
|
|
507
|
+
|
|
508
|
+
try std.testing.expectEqual(@as(u32, 2), document.count());
|
|
509
|
+
|
|
510
|
+
const retrieved_line1 = document.get(0).?;
|
|
511
|
+
try std.testing.expectEqual(@as(u32, 2), retrieved_line1.chunks.count());
|
|
512
|
+
|
|
513
|
+
const retrieved_line2 = document.get(1).?;
|
|
514
|
+
try std.testing.expectEqual(@as(u32, 1), retrieved_line2.chunks.count());
|
|
515
|
+
|
|
516
|
+
var modified_chunks = retrieved_line1.chunks;
|
|
517
|
+
try modified_chunks.insert(1, .{ .data = "Beautiful ", .width = 10 });
|
|
518
|
+
|
|
519
|
+
const modified_line = Line{
|
|
520
|
+
.chunks = modified_chunks,
|
|
521
|
+
.line_id = 1,
|
|
522
|
+
};
|
|
523
|
+
|
|
524
|
+
// Note: In a real text buffer, you'd replace the line in the document
|
|
525
|
+
// For now, just verify the modified line has the new chunk
|
|
526
|
+
try std.testing.expectEqual(@as(u32, 3), modified_line.chunks.count());
|
|
527
|
+
try std.testing.expectEqualStrings("Beautiful ", modified_line.chunks.get(1).?.data);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
test "Nested Rope - empty lines with no chunks" {
|
|
531
|
+
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
|
532
|
+
defer arena.deinit();
|
|
533
|
+
const allocator = arena.allocator();
|
|
534
|
+
|
|
535
|
+
const empty_chunks: []const Chunk = &[_]Chunk{};
|
|
536
|
+
const empty_line = Line{
|
|
537
|
+
.chunks = try rope_mod.Rope(Chunk).from_slice(allocator, empty_chunks),
|
|
538
|
+
.line_id = 1,
|
|
539
|
+
};
|
|
540
|
+
|
|
541
|
+
const chunks = [_]Chunk{.{ .data = "Content", .width = 7 }};
|
|
542
|
+
const content_line = Line{
|
|
543
|
+
.chunks = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks),
|
|
544
|
+
.line_id = 2,
|
|
545
|
+
};
|
|
546
|
+
|
|
547
|
+
const lines = [_]Line{ empty_line, content_line };
|
|
548
|
+
var line_rope = try rope_mod.Rope(Line).from_slice(allocator, &lines);
|
|
549
|
+
|
|
550
|
+
try std.testing.expectEqual(@as(u32, 2), line_rope.count());
|
|
551
|
+
|
|
552
|
+
const empty = line_rope.get(0).?;
|
|
553
|
+
try std.testing.expectEqual(@as(u32, 0), empty.chunks.count());
|
|
554
|
+
|
|
555
|
+
const content = line_rope.get(1).?;
|
|
556
|
+
try std.testing.expectEqual(@as(u32, 1), content.chunks.count());
|
|
557
|
+
try std.testing.expectEqualStrings("Content", content.chunks.get(0).?.data);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
test "Nested Rope - large document with many lines and chunks" {
|
|
561
|
+
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
|
562
|
+
defer arena.deinit();
|
|
563
|
+
const allocator = arena.allocator();
|
|
564
|
+
|
|
565
|
+
var lines_array: [20]Line = undefined;
|
|
566
|
+
for (&lines_array, 0..) |*line, line_idx| {
|
|
567
|
+
var chunks_array: [3]Chunk = undefined;
|
|
568
|
+
for (&chunks_array, 0..) |*chunk, chunk_idx| {
|
|
569
|
+
chunk.* = .{
|
|
570
|
+
.data = "X",
|
|
571
|
+
.width = 1,
|
|
572
|
+
};
|
|
573
|
+
_ = chunk_idx;
|
|
574
|
+
}
|
|
575
|
+
line.* = Line{
|
|
576
|
+
.chunks = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks_array),
|
|
577
|
+
.line_id = @intCast(line_idx),
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
var document = try rope_mod.Rope(Line).from_slice(allocator, &lines_array);
|
|
582
|
+
|
|
583
|
+
try std.testing.expectEqual(@as(u32, 20), document.count());
|
|
584
|
+
|
|
585
|
+
const line_5 = document.get(5).?;
|
|
586
|
+
try std.testing.expectEqual(@as(u32, 5), line_5.line_id);
|
|
587
|
+
try std.testing.expectEqual(@as(u32, 3), line_5.chunks.count());
|
|
588
|
+
|
|
589
|
+
const line_15 = document.get(15).?;
|
|
590
|
+
try std.testing.expectEqual(@as(u32, 15), line_15.line_id);
|
|
591
|
+
|
|
592
|
+
try std.testing.expectEqualStrings("X", line_5.chunks.get(0).?.data);
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
test "Nested Rope - walk_from specific line" {
|
|
596
|
+
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
|
597
|
+
defer arena.deinit();
|
|
598
|
+
const allocator = arena.allocator();
|
|
599
|
+
|
|
600
|
+
var lines_array: [5]Line = undefined;
|
|
601
|
+
for (&lines_array, 0..) |*line, i| {
|
|
602
|
+
const chunks = [_]Chunk{.{ .data = "X", .width = 1 }};
|
|
603
|
+
line.* = Line{
|
|
604
|
+
.chunks = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks),
|
|
605
|
+
.line_id = @intCast(i),
|
|
606
|
+
};
|
|
607
|
+
}
|
|
608
|
+
var document = try rope_mod.Rope(Line).from_slice(allocator, &lines_array);
|
|
609
|
+
|
|
610
|
+
const Context = struct {
|
|
611
|
+
count: u32 = 0,
|
|
612
|
+
first_id: ?u32 = null,
|
|
613
|
+
|
|
614
|
+
fn walker(ctx: *anyopaque, line: *const Line, index: u32) rope_mod.Rope(Line).Node.WalkerResult {
|
|
615
|
+
_ = index;
|
|
616
|
+
const self = @as(*@This(), @ptrCast(@alignCast(ctx)));
|
|
617
|
+
if (self.first_id == null) {
|
|
618
|
+
self.first_id = line.line_id;
|
|
619
|
+
}
|
|
620
|
+
self.count += 1;
|
|
621
|
+
return .{};
|
|
622
|
+
}
|
|
623
|
+
};
|
|
624
|
+
|
|
625
|
+
var ctx = Context{};
|
|
626
|
+
try document.walk_from(3, &ctx, Context.walker);
|
|
627
|
+
|
|
628
|
+
// Should walk lines 3 and 4 (indices 3 and 4)
|
|
629
|
+
try std.testing.expectEqual(@as(u32, 2), ctx.count);
|
|
630
|
+
try std.testing.expectEqual(@as(u32, 3), ctx.first_id.?);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
test "Nested Rope - metrics aggregate correctly through all levels" {
|
|
634
|
+
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
|
635
|
+
defer arena.deinit();
|
|
636
|
+
const allocator = arena.allocator();
|
|
637
|
+
|
|
638
|
+
// Line 1: 3 chunks, total width 10
|
|
639
|
+
const chunks1 = [_]Chunk{
|
|
640
|
+
.{ .data = "abc", .width = 3 },
|
|
641
|
+
.{ .data = "def", .width = 3 },
|
|
642
|
+
.{ .data = "ghij", .width = 4 },
|
|
643
|
+
};
|
|
644
|
+
|
|
645
|
+
// Line 2: 2 chunks, total width 15
|
|
646
|
+
const chunks2 = [_]Chunk{
|
|
647
|
+
.{ .data = "12345", .width = 5 },
|
|
648
|
+
.{ .data = "6789012345", .width = 10 },
|
|
649
|
+
};
|
|
650
|
+
|
|
651
|
+
const lines = [_]Line{
|
|
652
|
+
.{ .chunks = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks1), .line_id = 1 },
|
|
653
|
+
.{ .chunks = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks2), .line_id = 2 },
|
|
654
|
+
};
|
|
655
|
+
var document = try rope_mod.Rope(Line).from_slice(allocator, &lines);
|
|
656
|
+
|
|
657
|
+
const line1 = document.get(0).?;
|
|
658
|
+
const chunk_metrics1 = line1.chunks.root.metrics();
|
|
659
|
+
try std.testing.expectEqual(@as(u32, 3), chunk_metrics1.count);
|
|
660
|
+
try std.testing.expectEqual(@as(u32, 10), chunk_metrics1.custom.total_width);
|
|
661
|
+
try std.testing.expectEqual(@as(u32, 10), chunk_metrics1.custom.total_bytes);
|
|
662
|
+
|
|
663
|
+
const line2 = document.get(1).?;
|
|
664
|
+
const chunk_metrics2 = line2.chunks.root.metrics();
|
|
665
|
+
try std.testing.expectEqual(@as(u32, 2), chunk_metrics2.count);
|
|
666
|
+
try std.testing.expectEqual(@as(u32, 15), chunk_metrics2.custom.total_width);
|
|
667
|
+
try std.testing.expectEqual(@as(u32, 15), chunk_metrics2.custom.total_bytes);
|
|
668
|
+
|
|
669
|
+
const line1_metrics = line1.measure();
|
|
670
|
+
try std.testing.expectEqual(@as(u32, 10), line1_metrics.total_width);
|
|
671
|
+
|
|
672
|
+
const doc_metrics = document.root.metrics();
|
|
673
|
+
try std.testing.expectEqual(@as(u32, 2), doc_metrics.count); // 2 lines
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
test "Nested Rope - O(log n) access to deeply nested data" {
|
|
677
|
+
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
|
678
|
+
defer arena.deinit();
|
|
679
|
+
const allocator = arena.allocator();
|
|
680
|
+
|
|
681
|
+
var lines_array: [100]Line = undefined;
|
|
682
|
+
for (&lines_array, 0..) |*line, line_idx| {
|
|
683
|
+
var chunks_array: [5]Chunk = undefined;
|
|
684
|
+
for (&chunks_array, 0..) |*chunk, chunk_idx| {
|
|
685
|
+
chunk.* = .{
|
|
686
|
+
.data = "c",
|
|
687
|
+
.width = 1,
|
|
688
|
+
};
|
|
689
|
+
_ = chunk_idx;
|
|
690
|
+
}
|
|
691
|
+
line.* = Line{
|
|
692
|
+
.chunks = try rope_mod.Rope(Chunk).from_slice(allocator, &chunks_array),
|
|
693
|
+
.line_id = @intCast(line_idx),
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
var document = try rope_mod.Rope(Line).from_slice(allocator, &lines_array);
|
|
698
|
+
|
|
699
|
+
// Access line 50, chunk 3 (deep in the tree)
|
|
700
|
+
// This tests O(log lines) + O(log chunks) access
|
|
701
|
+
const line_50 = document.get(50).?;
|
|
702
|
+
try std.testing.expectEqual(@as(u32, 50), line_50.line_id);
|
|
703
|
+
|
|
704
|
+
const chunk_3 = line_50.chunks.get(3).?;
|
|
705
|
+
try std.testing.expectEqualStrings("c", chunk_3.data);
|
|
706
|
+
|
|
707
|
+
const doc_depth = document.root.depth();
|
|
708
|
+
try std.testing.expect(doc_depth < 20); // log2(100) ≈ 7, with some buffer
|
|
709
|
+
|
|
710
|
+
const line_depth = line_50.chunks.root.depth();
|
|
711
|
+
try std.testing.expect(line_depth < 10); // log2(5) ≈ 3, with buffer
|
|
712
|
+
}
|