@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,499 @@
|
|
|
1
|
+
const std = @import("std");
|
|
2
|
+
const Allocator = std.mem.Allocator;
|
|
3
|
+
const seg_mod = @import("text-buffer-segment.zig");
|
|
4
|
+
const mem_registry_mod = @import("mem-registry.zig");
|
|
5
|
+
const utf8 = @import("utf8.zig");
|
|
6
|
+
|
|
7
|
+
const Segment = seg_mod.Segment;
|
|
8
|
+
const UnifiedRope = seg_mod.UnifiedRope;
|
|
9
|
+
const TextChunk = seg_mod.TextChunk;
|
|
10
|
+
const GraphemeInfo = seg_mod.GraphemeInfo;
|
|
11
|
+
const MemRegistry = mem_registry_mod.MemRegistry;
|
|
12
|
+
|
|
13
|
+
pub const LineInfo = struct {
|
|
14
|
+
line_idx: u32,
|
|
15
|
+
col_offset: u32,
|
|
16
|
+
width_cols: u32,
|
|
17
|
+
seg_start: u32,
|
|
18
|
+
seg_end: u32,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
pub const Coords = struct {
|
|
22
|
+
row: u32,
|
|
23
|
+
col: u32,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/// Note: Takes mutable rope for lazy marker cache rebuilding
|
|
27
|
+
pub fn walkLines(
|
|
28
|
+
rope: *UnifiedRope,
|
|
29
|
+
ctx: *anyopaque,
|
|
30
|
+
callback: *const fn (ctx: *anyopaque, line_info: LineInfo) void,
|
|
31
|
+
include_newlines_in_offset: bool,
|
|
32
|
+
) void {
|
|
33
|
+
const linestart_count = rope.markerCount(.linestart);
|
|
34
|
+
if (linestart_count == 0) return;
|
|
35
|
+
|
|
36
|
+
var i: u32 = 0;
|
|
37
|
+
while (i < linestart_count) : (i += 1) {
|
|
38
|
+
const marker = rope.getMarker(.linestart, i) orelse continue;
|
|
39
|
+
const line_start_weight = marker.global_weight;
|
|
40
|
+
const width_cols = lineWidthAt(rope, i);
|
|
41
|
+
const seg_end = if (i + 1 < linestart_count) blk: {
|
|
42
|
+
const next_marker = rope.getMarker(.linestart, i + 1) orelse break :blk marker.leaf_index + 1;
|
|
43
|
+
break :blk next_marker.leaf_index;
|
|
44
|
+
} else blk: {
|
|
45
|
+
break :blk rope.count();
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// Line i has i newlines before it (one after each previous line)
|
|
49
|
+
const col_offset = if (include_newlines_in_offset)
|
|
50
|
+
line_start_weight
|
|
51
|
+
else
|
|
52
|
+
line_start_weight - i;
|
|
53
|
+
|
|
54
|
+
callback(ctx, LineInfo{
|
|
55
|
+
.line_idx = i,
|
|
56
|
+
.col_offset = col_offset,
|
|
57
|
+
.width_cols = width_cols,
|
|
58
|
+
.seg_start = marker.leaf_index,
|
|
59
|
+
.seg_end = seg_end,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/// This is the most efficient way to iterate lines and their content
|
|
65
|
+
pub fn walkLinesAndSegments(
|
|
66
|
+
rope: *const UnifiedRope,
|
|
67
|
+
ctx: *anyopaque,
|
|
68
|
+
segment_callback: *const fn (ctx: *anyopaque, line_idx: u32, chunk: *const TextChunk, chunk_idx_in_line: u32) void,
|
|
69
|
+
line_end_callback: *const fn (ctx: *anyopaque, line_info: LineInfo) void,
|
|
70
|
+
) void {
|
|
71
|
+
if (rope.count() == 0) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const WalkContext = struct {
|
|
76
|
+
user_ctx: *anyopaque,
|
|
77
|
+
seg_callback: *const fn (ctx: *anyopaque, line_idx: u32, chunk: *const TextChunk, chunk_idx_in_line: u32) void,
|
|
78
|
+
line_callback: *const fn (ctx: *anyopaque, line_info: LineInfo) void,
|
|
79
|
+
current_line_idx: u32 = 0,
|
|
80
|
+
current_col_offset: u32 = 0,
|
|
81
|
+
line_start_seg: u32 = 0,
|
|
82
|
+
current_seg_idx: u32 = 0,
|
|
83
|
+
line_width_cols: u32 = 0,
|
|
84
|
+
chunk_idx_in_line: u32 = 0,
|
|
85
|
+
|
|
86
|
+
fn walker(walk_ctx_ptr: *anyopaque, seg: *const Segment, idx: u32) UnifiedRope.Node.WalkerResult {
|
|
87
|
+
const walk_ctx = @as(*@This(), @ptrCast(@alignCast(walk_ctx_ptr)));
|
|
88
|
+
|
|
89
|
+
if (seg.asText()) |chunk| {
|
|
90
|
+
walk_ctx.seg_callback(walk_ctx.user_ctx, walk_ctx.current_line_idx, chunk, walk_ctx.chunk_idx_in_line);
|
|
91
|
+
walk_ctx.chunk_idx_in_line += 1;
|
|
92
|
+
walk_ctx.line_width_cols += chunk.width;
|
|
93
|
+
} else if (seg.isBreak()) {
|
|
94
|
+
walk_ctx.line_callback(walk_ctx.user_ctx, LineInfo{
|
|
95
|
+
.line_idx = walk_ctx.current_line_idx,
|
|
96
|
+
.col_offset = walk_ctx.current_col_offset,
|
|
97
|
+
.width_cols = walk_ctx.line_width_cols,
|
|
98
|
+
.seg_start = walk_ctx.line_start_seg,
|
|
99
|
+
.seg_end = idx, // Don't include the break
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
walk_ctx.current_line_idx += 1;
|
|
103
|
+
walk_ctx.current_col_offset += walk_ctx.line_width_cols + 1;
|
|
104
|
+
walk_ctx.line_start_seg = idx + 1;
|
|
105
|
+
walk_ctx.line_width_cols = 0;
|
|
106
|
+
walk_ctx.chunk_idx_in_line = 0;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
walk_ctx.current_seg_idx = idx + 1;
|
|
110
|
+
return .{};
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
var walk_ctx = WalkContext{
|
|
115
|
+
.user_ctx = ctx,
|
|
116
|
+
.seg_callback = segment_callback,
|
|
117
|
+
.line_callback = line_end_callback,
|
|
118
|
+
};
|
|
119
|
+
rope.walk(&walk_ctx, WalkContext.walker) catch {};
|
|
120
|
+
|
|
121
|
+
// Emit final line if we have content after last break OR if we had at least one break
|
|
122
|
+
// (A trailing break creates an empty final line)
|
|
123
|
+
const had_breaks = walk_ctx.current_line_idx > 0;
|
|
124
|
+
const has_content_after_break = walk_ctx.line_start_seg < walk_ctx.current_seg_idx;
|
|
125
|
+
|
|
126
|
+
if (has_content_after_break or had_breaks) {
|
|
127
|
+
line_end_callback(ctx, LineInfo{
|
|
128
|
+
.line_idx = walk_ctx.current_line_idx,
|
|
129
|
+
.col_offset = walk_ctx.current_col_offset,
|
|
130
|
+
.width_cols = walk_ctx.line_width_cols,
|
|
131
|
+
.seg_start = walk_ctx.line_start_seg,
|
|
132
|
+
.seg_end = walk_ctx.current_seg_idx,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
pub fn getLineCount(rope: *const UnifiedRope) u32 {
|
|
138
|
+
const metrics = rope.root.metrics();
|
|
139
|
+
return metrics.custom.linestart_count;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
pub fn getMaxLineWidth(rope: *const UnifiedRope) u32 {
|
|
143
|
+
const metrics = rope.root.metrics();
|
|
144
|
+
return metrics.custom.max_line_width;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
pub fn getTotalWidth(rope: *const UnifiedRope) u32 {
|
|
148
|
+
const metrics = rope.root.metrics();
|
|
149
|
+
return metrics.custom.total_width;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/// Optimized O(1) implementation using linestart marker lookups
|
|
153
|
+
/// Note: Rope weight includes newlines (each .brk adds +1), but col is still display width
|
|
154
|
+
/// Takes mutable rope for lazy marker cache rebuilding
|
|
155
|
+
pub fn coordsToOffset(rope: *UnifiedRope, row: u32, col: u32) ?u32 {
|
|
156
|
+
const linestart_count = rope.markerCount(.linestart);
|
|
157
|
+
if (row >= linestart_count) return null;
|
|
158
|
+
|
|
159
|
+
const marker = rope.getMarker(.linestart, row) orelse return null;
|
|
160
|
+
const line_start_weight = marker.global_weight;
|
|
161
|
+
const line_width = lineWidthAt(rope, row);
|
|
162
|
+
|
|
163
|
+
if (col > line_width) return null;
|
|
164
|
+
|
|
165
|
+
return line_start_weight + col;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/// Optimized O(log n) implementation using binary search on linestart markers
|
|
169
|
+
/// Note: Rope weight includes newlines, so valid offsets are 0..totalWeight() inclusive
|
|
170
|
+
/// Takes mutable rope for lazy marker cache rebuilding
|
|
171
|
+
/// TODO: Should clamp to min/max offset and always return valid coords
|
|
172
|
+
pub fn offsetToCoords(rope: *UnifiedRope, offset: u32) ?Coords {
|
|
173
|
+
const linestart_count = rope.markerCount(.linestart);
|
|
174
|
+
if (linestart_count == 0) return null;
|
|
175
|
+
|
|
176
|
+
const total_weight = rope.totalWeight();
|
|
177
|
+
if (offset > total_weight) return null;
|
|
178
|
+
|
|
179
|
+
var left: u32 = 0;
|
|
180
|
+
var right: u32 = linestart_count;
|
|
181
|
+
|
|
182
|
+
while (left < right) {
|
|
183
|
+
const mid = left + (right - left) / 2;
|
|
184
|
+
const marker = rope.getMarker(.linestart, mid) orelse return null;
|
|
185
|
+
const line_start_weight = marker.global_weight;
|
|
186
|
+
|
|
187
|
+
if (offset < line_start_weight) {
|
|
188
|
+
right = mid;
|
|
189
|
+
} else {
|
|
190
|
+
const next_line_start_weight = if (mid + 1 < linestart_count) blk: {
|
|
191
|
+
const next_marker = rope.getMarker(.linestart, mid + 1) orelse return null;
|
|
192
|
+
break :blk next_marker.global_weight;
|
|
193
|
+
} else blk: {
|
|
194
|
+
// Last line: ends at total weight
|
|
195
|
+
break :blk total_weight;
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
// Offset belongs to this line if it's before the next line starts
|
|
199
|
+
// (newline offset at end of non-final line maps to col==line_width)
|
|
200
|
+
if (offset < next_line_start_weight or (offset == total_weight and mid + 1 == linestart_count)) {
|
|
201
|
+
return Coords{
|
|
202
|
+
.row = mid,
|
|
203
|
+
.col = offset - line_start_weight,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
left = mid + 1;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/// Note: Returns display width only (excludes newline weight)
|
|
214
|
+
/// Takes mutable rope for lazy marker cache rebuilding
|
|
215
|
+
pub fn lineWidthAt(rope: *UnifiedRope, row: u32) u32 {
|
|
216
|
+
const linestart_count = rope.markerCount(.linestart);
|
|
217
|
+
if (row >= linestart_count) return 0;
|
|
218
|
+
|
|
219
|
+
const line_marker = rope.getMarker(.linestart, row) orelse return 0;
|
|
220
|
+
const line_start_weight = line_marker.global_weight;
|
|
221
|
+
if (row + 1 < linestart_count) {
|
|
222
|
+
// Non-final line: width = (next_line_start - current_start - 1_for_newline)
|
|
223
|
+
const next_marker = rope.getMarker(.linestart, row + 1) orelse return 0;
|
|
224
|
+
const next_line_start_weight = next_marker.global_weight;
|
|
225
|
+
// Guard against underflow (adjacent linestart markers or empty line)
|
|
226
|
+
if (next_line_start_weight <= line_start_weight) return 0;
|
|
227
|
+
return next_line_start_weight - line_start_weight - 1;
|
|
228
|
+
} else {
|
|
229
|
+
// Final line: width = total_weight - line_start (total weight includes all previous newlines)
|
|
230
|
+
const total_weight = rope.totalWeight();
|
|
231
|
+
return total_weight - line_start_weight;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/// Takes mutable rope for lazy marker cache rebuilding
|
|
236
|
+
pub fn getGraphemeWidthAt(rope: *UnifiedRope, mem_registry: *const MemRegistry, row: u32, col: u32, tab_width: u8, width_method: utf8.WidthMethod) u32 {
|
|
237
|
+
const line_width = lineWidthAt(rope, row);
|
|
238
|
+
if (col >= line_width) return 0;
|
|
239
|
+
|
|
240
|
+
const linestart = rope.getMarker(.linestart, row) orelse return 0;
|
|
241
|
+
var seg_idx = linestart.leaf_index + 1;
|
|
242
|
+
var cols_before: u32 = 0;
|
|
243
|
+
|
|
244
|
+
while (seg_idx < rope.count()) : (seg_idx += 1) {
|
|
245
|
+
const seg = rope.get(seg_idx) orelse break;
|
|
246
|
+
if (seg.isBreak() or seg.isLineStart()) break;
|
|
247
|
+
if (seg.asText()) |chunk| {
|
|
248
|
+
const next_cols = cols_before + chunk.width;
|
|
249
|
+
if (col < next_cols) {
|
|
250
|
+
const local_col: u32 = col - cols_before;
|
|
251
|
+
const bytes = chunk.getBytes(mem_registry);
|
|
252
|
+
const is_ascii = (chunk.flags & TextChunk.Flags.ASCII_ONLY) != 0;
|
|
253
|
+
const pos = utf8.findPosByWidth(bytes, local_col, tab_width, is_ascii, false, width_method);
|
|
254
|
+
if (pos.byte_offset >= bytes.len) return 0; // at end of chunk
|
|
255
|
+
const grapheme_start_col = pos.columns_used;
|
|
256
|
+
const width = utf8.getWidthAt(bytes, pos.byte_offset, tab_width, width_method);
|
|
257
|
+
|
|
258
|
+
// Calculate remaining width: if cursor is in the middle of a wide grapheme,
|
|
259
|
+
// return only the remaining columns to reach the end of the grapheme
|
|
260
|
+
const grapheme_end_col = grapheme_start_col + width;
|
|
261
|
+
const remaining_width = grapheme_end_col - local_col;
|
|
262
|
+
return remaining_width;
|
|
263
|
+
}
|
|
264
|
+
cols_before = next_cols;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return 0;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/// Takes mutable rope for lazy marker cache rebuilding
|
|
271
|
+
pub fn getPrevGraphemeWidth(rope: *UnifiedRope, mem_registry: *const MemRegistry, row: u32, col: u32, tab_width: u8, width_method: utf8.WidthMethod) u32 {
|
|
272
|
+
if (col == 0) return 0;
|
|
273
|
+
|
|
274
|
+
const line_width = lineWidthAt(rope, row);
|
|
275
|
+
const clamped_col: u32 = @min(col, line_width);
|
|
276
|
+
|
|
277
|
+
const linestart = rope.getMarker(.linestart, row) orelse return 0;
|
|
278
|
+
var seg_idx = linestart.leaf_index + 1;
|
|
279
|
+
var cols_before: u32 = 0;
|
|
280
|
+
var prev_chunk: ?struct { chunk: TextChunk, cols_before: u32 } = null;
|
|
281
|
+
|
|
282
|
+
while (seg_idx < rope.count()) : (seg_idx += 1) {
|
|
283
|
+
const seg = rope.get(seg_idx) orelse break;
|
|
284
|
+
if (seg.isBreak() or seg.isLineStart()) break;
|
|
285
|
+
if (seg.asText()) |chunk| {
|
|
286
|
+
const next_cols = cols_before + chunk.width;
|
|
287
|
+
|
|
288
|
+
if (clamped_col <= next_cols) {
|
|
289
|
+
if (clamped_col == cols_before and prev_chunk != null) {
|
|
290
|
+
// Exactly at chunk boundary - get last grapheme from previous chunk
|
|
291
|
+
const pc = prev_chunk.?;
|
|
292
|
+
const bytes = pc.chunk.getBytes(mem_registry);
|
|
293
|
+
const prev = utf8.getPrevGraphemeStart(bytes, bytes.len, tab_width, width_method);
|
|
294
|
+
if (prev) |res| {
|
|
295
|
+
return res.width;
|
|
296
|
+
}
|
|
297
|
+
return 0;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const bytes = chunk.getBytes(mem_registry);
|
|
301
|
+
const is_ascii = (chunk.flags & TextChunk.Flags.ASCII_ONLY) != 0;
|
|
302
|
+
const local_col: u32 = clamped_col - cols_before;
|
|
303
|
+
|
|
304
|
+
const here = utf8.findPosByWidth(bytes, local_col, tab_width, is_ascii, false, width_method);
|
|
305
|
+
|
|
306
|
+
const grapheme_start_col = here.columns_used;
|
|
307
|
+
|
|
308
|
+
// Check for integer underflow: if grapheme_start_col > local_col, we're in the middle of a grapheme
|
|
309
|
+
// that spans beyond local_col. This can happen with multi-codepoint graphemes.
|
|
310
|
+
if (grapheme_start_col > local_col) {
|
|
311
|
+
// We're in the middle of a wide grapheme cluster - need to look at previous chunk or grapheme
|
|
312
|
+
if (prev_chunk) |pc| {
|
|
313
|
+
const prev_bytes = pc.chunk.getBytes(mem_registry);
|
|
314
|
+
const prev = utf8.getPrevGraphemeStart(prev_bytes, prev_bytes.len, tab_width, width_method);
|
|
315
|
+
if (prev) |res| return res.width;
|
|
316
|
+
}
|
|
317
|
+
return 0;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const offset_into_grapheme = local_col - grapheme_start_col;
|
|
321
|
+
|
|
322
|
+
if (offset_into_grapheme > 0) {
|
|
323
|
+
// We need to jump back: offset_into_grapheme + width of previous grapheme
|
|
324
|
+
const prev = utf8.getPrevGraphemeStart(bytes, @intCast(here.byte_offset), tab_width, width_method);
|
|
325
|
+
if (prev) |res| {
|
|
326
|
+
const total_distance = offset_into_grapheme + res.width;
|
|
327
|
+
return total_distance;
|
|
328
|
+
}
|
|
329
|
+
return offset_into_grapheme;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const prev = utf8.getPrevGraphemeStart(bytes, @intCast(here.byte_offset), tab_width, width_method);
|
|
333
|
+
if (prev) |res| {
|
|
334
|
+
return res.width;
|
|
335
|
+
}
|
|
336
|
+
return 0;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
prev_chunk = .{ .chunk = chunk.*, .cols_before = cols_before };
|
|
340
|
+
cols_before = next_cols;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
return 0;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
pub const CharOffsetColumnInfo = struct {
|
|
347
|
+
col: u32,
|
|
348
|
+
width: u32,
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
/// char_offset is grapheme-count based (not raw codepoint)
|
|
352
|
+
/// grapheme_idx and col_delta carry incremental state across calls
|
|
353
|
+
pub fn charOffsetToColumn(
|
|
354
|
+
char_offset: u32,
|
|
355
|
+
graphemes: []const GraphemeInfo,
|
|
356
|
+
grapheme_idx: *usize,
|
|
357
|
+
col_delta: *i64,
|
|
358
|
+
) CharOffsetColumnInfo {
|
|
359
|
+
while (grapheme_idx.* < graphemes.len) {
|
|
360
|
+
const info = graphemes[grapheme_idx.*];
|
|
361
|
+
const info_char_offset = @as(i64, info.col_offset) - col_delta.*;
|
|
362
|
+
if (info_char_offset >= @as(i64, char_offset)) break;
|
|
363
|
+
col_delta.* += @as(i64, info.width) - 1;
|
|
364
|
+
grapheme_idx.* += 1;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
var break_col_i64 = @as(i64, char_offset) + col_delta.*;
|
|
368
|
+
if (break_col_i64 < 0) break_col_i64 = 0;
|
|
369
|
+
const break_col = @as(u32, @intCast(break_col_i64));
|
|
370
|
+
|
|
371
|
+
var width: u32 = 1;
|
|
372
|
+
if (grapheme_idx.* < graphemes.len) {
|
|
373
|
+
const info = graphemes[grapheme_idx.*];
|
|
374
|
+
const info_char_offset = @as(i64, info.col_offset) - col_delta.*;
|
|
375
|
+
if (info_char_offset == @as(i64, char_offset)) {
|
|
376
|
+
width = @as(u32, info.width);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
return .{ .col = break_col, .width = width };
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/// Extract text between display-width offsets into a buffer
|
|
384
|
+
/// Automatically snaps to grapheme boundaries:
|
|
385
|
+
/// - start_offset excludes graphemes that start before it
|
|
386
|
+
/// - end_offset includes graphemes that start before it
|
|
387
|
+
/// Returns number of bytes written to out_buffer
|
|
388
|
+
pub fn extractTextBetweenOffsets(
|
|
389
|
+
rope: *const UnifiedRope,
|
|
390
|
+
mem_registry: *const MemRegistry,
|
|
391
|
+
tab_width: u8,
|
|
392
|
+
start_offset: u32,
|
|
393
|
+
end_offset: u32,
|
|
394
|
+
out_buffer: []u8,
|
|
395
|
+
width_method: utf8.WidthMethod,
|
|
396
|
+
) usize {
|
|
397
|
+
if (start_offset >= end_offset) return 0;
|
|
398
|
+
if (out_buffer.len == 0) return 0;
|
|
399
|
+
|
|
400
|
+
const line_count = rope.root.metrics().custom.linestart_count;
|
|
401
|
+
|
|
402
|
+
var out_index: usize = 0;
|
|
403
|
+
var col_offset: u32 = 0;
|
|
404
|
+
|
|
405
|
+
_ = width_method; // Just ignore for now, will use .unicode as default
|
|
406
|
+
|
|
407
|
+
const Context = struct {
|
|
408
|
+
rope: *const UnifiedRope,
|
|
409
|
+
mem_registry: *const MemRegistry,
|
|
410
|
+
tab_width: u8,
|
|
411
|
+
out_buffer: []u8,
|
|
412
|
+
out_index: *usize,
|
|
413
|
+
col_offset: *u32,
|
|
414
|
+
start: u32,
|
|
415
|
+
end: u32,
|
|
416
|
+
line_count: u32,
|
|
417
|
+
line_had_content: bool = false,
|
|
418
|
+
|
|
419
|
+
fn segment_callback(ctx_ptr: *anyopaque, line_idx: u32, chunk: *const TextChunk, chunk_idx_in_line: u32) void {
|
|
420
|
+
_ = line_idx;
|
|
421
|
+
_ = chunk_idx_in_line;
|
|
422
|
+
const ctx = @as(*@This(), @ptrCast(@alignCast(ctx_ptr)));
|
|
423
|
+
|
|
424
|
+
const chunk_start_offset = ctx.col_offset.*;
|
|
425
|
+
const chunk_end_offset = chunk_start_offset + chunk.width;
|
|
426
|
+
|
|
427
|
+
// Skip chunk if it's entirely outside range
|
|
428
|
+
if (chunk_end_offset <= ctx.start or chunk_start_offset >= ctx.end) {
|
|
429
|
+
ctx.col_offset.* = chunk_end_offset;
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
ctx.line_had_content = true;
|
|
434
|
+
|
|
435
|
+
const chunk_bytes = chunk.getBytes(ctx.mem_registry);
|
|
436
|
+
const is_ascii_only = (chunk.flags & TextChunk.Flags.ASCII_ONLY) != 0;
|
|
437
|
+
|
|
438
|
+
const local_start_col: u32 = if (ctx.start > chunk_start_offset) ctx.start - chunk_start_offset else 0;
|
|
439
|
+
const local_end_col: u32 = @min(ctx.end - chunk_start_offset, chunk.width);
|
|
440
|
+
|
|
441
|
+
var byte_start: u32 = 0;
|
|
442
|
+
var byte_end: u32 = @intCast(chunk_bytes.len);
|
|
443
|
+
|
|
444
|
+
if (local_start_col > 0) {
|
|
445
|
+
const start_result = utf8.findPosByWidth(chunk_bytes, local_start_col, ctx.tab_width, is_ascii_only, false, .unicode);
|
|
446
|
+
byte_start = start_result.byte_offset;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
if (local_end_col < chunk.width) {
|
|
450
|
+
const end_result = utf8.findPosByWidth(chunk_bytes, local_end_col, ctx.tab_width, is_ascii_only, true, .unicode);
|
|
451
|
+
byte_end = end_result.byte_offset;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
if (byte_start < byte_end and byte_start < chunk_bytes.len) {
|
|
455
|
+
const actual_end = @min(byte_end, @as(u32, @intCast(chunk_bytes.len)));
|
|
456
|
+
const selected_bytes = chunk_bytes[byte_start..actual_end];
|
|
457
|
+
const copy_len = @min(selected_bytes.len, ctx.out_buffer.len - ctx.out_index.*);
|
|
458
|
+
|
|
459
|
+
if (copy_len > 0) {
|
|
460
|
+
@memcpy(ctx.out_buffer[ctx.out_index.* .. ctx.out_index.* + copy_len], selected_bytes[0..copy_len]);
|
|
461
|
+
ctx.out_index.* += copy_len;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
ctx.col_offset.* = chunk_end_offset;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
fn line_end_callback(ctx_ptr: *anyopaque, line_info: LineInfo) void {
|
|
469
|
+
const ctx = @as(*@This(), @ptrCast(@alignCast(ctx_ptr)));
|
|
470
|
+
|
|
471
|
+
// Add newline if we had content and range extends beyond this line's newline
|
|
472
|
+
if (ctx.line_had_content and line_info.line_idx < ctx.line_count - 1 and ctx.col_offset.* + 1 < ctx.end and ctx.out_index.* < ctx.out_buffer.len) {
|
|
473
|
+
ctx.out_buffer[ctx.out_index.*] = '\n';
|
|
474
|
+
ctx.out_index.* += 1;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// Account for newline in display offset
|
|
478
|
+
ctx.col_offset.* += 1;
|
|
479
|
+
|
|
480
|
+
ctx.line_had_content = false;
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
var ctx = Context{
|
|
485
|
+
.rope = rope,
|
|
486
|
+
.mem_registry = mem_registry,
|
|
487
|
+
.tab_width = tab_width,
|
|
488
|
+
.out_buffer = out_buffer,
|
|
489
|
+
.out_index = &out_index,
|
|
490
|
+
.col_offset = &col_offset,
|
|
491
|
+
.start = start_offset,
|
|
492
|
+
.end = end_offset,
|
|
493
|
+
.line_count = line_count,
|
|
494
|
+
};
|
|
495
|
+
|
|
496
|
+
walkLinesAndSegments(rope, &ctx, Context.segment_callback, Context.line_end_callback);
|
|
497
|
+
|
|
498
|
+
return out_index;
|
|
499
|
+
}
|