@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.
Files changed (591) hide show
  1. package/dev/keypress-debug-renderer.ts +148 -0
  2. package/dev/keypress-debug.ts +43 -0
  3. package/dev/print-env-vars.ts +32 -0
  4. package/dev/test-tmux-graphics-334.sh +68 -0
  5. package/dev/thai-debug-test.ts +68 -0
  6. package/docs/development.md +144 -0
  7. package/package.json +62 -53
  8. package/scripts/build.ts +400 -0
  9. package/scripts/publish.ts +60 -0
  10. package/src/3d/SpriteResourceManager.ts +286 -0
  11. package/src/3d/SpriteUtils.ts +70 -0
  12. package/src/3d/TextureUtils.ts +196 -0
  13. package/src/3d/ThreeRenderable.ts +197 -0
  14. package/src/3d/WGPURenderer.ts +294 -0
  15. package/src/3d/animation/ExplodingSpriteEffect.ts +513 -0
  16. package/src/3d/animation/PhysicsExplodingSpriteEffect.ts +429 -0
  17. package/src/3d/animation/SpriteAnimator.ts +633 -0
  18. package/src/3d/animation/SpriteParticleGenerator.ts +435 -0
  19. package/src/3d/canvas.ts +464 -0
  20. package/src/3d/index.ts +12 -0
  21. package/src/3d/physics/PlanckPhysicsAdapter.ts +72 -0
  22. package/src/3d/physics/RapierPhysicsAdapter.ts +66 -0
  23. package/src/3d/physics/physics-interface.ts +31 -0
  24. package/src/3d/shaders/supersampling.wgsl +201 -0
  25. package/src/3d.ts +3 -0
  26. package/src/NativeSpanFeed.ts +300 -0
  27. package/src/Renderable.ts +1704 -0
  28. package/src/__snapshots__/buffer.test.ts.snap +28 -0
  29. package/src/animation/Timeline.test.ts +2709 -0
  30. package/src/animation/Timeline.ts +598 -0
  31. package/src/ansi.ts +18 -0
  32. package/src/benchmark/attenuation-benchmark.ts +81 -0
  33. package/src/benchmark/colormatrix-benchmark.ts +128 -0
  34. package/src/benchmark/gain-benchmark.ts +80 -0
  35. package/src/benchmark/latest-all-bench-run.json +707 -0
  36. package/src/benchmark/latest-async-bench-run.json +336 -0
  37. package/src/benchmark/latest-default-bench-run.json +657 -0
  38. package/src/benchmark/latest-large-bench-run.json +707 -0
  39. package/src/benchmark/latest-quick-bench-run.json +207 -0
  40. package/src/benchmark/markdown-benchmark.ts +1796 -0
  41. package/src/benchmark/native-span-feed-async-benchmark.ts +355 -0
  42. package/src/benchmark/native-span-feed-benchmark.md +56 -0
  43. package/src/benchmark/native-span-feed-benchmark.ts +596 -0
  44. package/src/benchmark/native-span-feed-compare.ts +280 -0
  45. package/src/benchmark/renderer-benchmark.ts +754 -0
  46. package/src/benchmark/text-table-benchmark.ts +948 -0
  47. package/src/buffer.test.ts +291 -0
  48. package/src/buffer.ts +554 -0
  49. package/src/console.test.ts +612 -0
  50. package/src/console.ts +1254 -0
  51. package/src/edit-buffer.test.ts +1769 -0
  52. package/src/edit-buffer.ts +411 -0
  53. package/src/editor-view.test.ts +1032 -0
  54. package/src/editor-view.ts +284 -0
  55. package/src/examples/ascii-font-selection-demo.ts +245 -0
  56. package/src/examples/assets/Water_2_M_Normal.jpg +0 -0
  57. package/src/examples/assets/concrete.png +0 -0
  58. package/src/examples/assets/crate.png +0 -0
  59. package/src/examples/assets/crate_emissive.png +0 -0
  60. package/src/examples/assets/forrest_background.png +0 -0
  61. package/src/examples/assets/hast-example.json +1018 -0
  62. package/src/examples/assets/heart.png +0 -0
  63. package/src/examples/assets/main_char_heavy_attack.png +0 -0
  64. package/src/examples/assets/main_char_idle.png +0 -0
  65. package/src/examples/assets/main_char_jump_end.png +0 -0
  66. package/src/examples/assets/main_char_jump_landing.png +0 -0
  67. package/src/examples/assets/main_char_jump_start.png +0 -0
  68. package/src/examples/assets/main_char_run_loop.png +0 -0
  69. package/src/examples/assets/roughness_map.jpg +0 -0
  70. package/src/examples/build.ts +115 -0
  71. package/src/examples/code-demo.ts +924 -0
  72. package/src/examples/console-demo.ts +358 -0
  73. package/src/examples/core-plugin-slots-demo.ts +759 -0
  74. package/src/examples/diff-demo.ts +701 -0
  75. package/src/examples/draggable-three-demo.ts +259 -0
  76. package/src/examples/editor-demo.ts +322 -0
  77. package/src/examples/extmarks-demo.ts +196 -0
  78. package/src/examples/focus-restore-demo.ts +310 -0
  79. package/src/examples/fonts.ts +245 -0
  80. package/src/examples/fractal-shader-demo.ts +268 -0
  81. package/src/examples/framebuffer-demo.ts +674 -0
  82. package/src/examples/full-unicode-demo.ts +241 -0
  83. package/src/examples/golden-star-demo.ts +933 -0
  84. package/src/examples/grayscale-buffer-demo.ts +249 -0
  85. package/src/examples/hast-syntax-highlighting-demo.ts +129 -0
  86. package/src/examples/index.ts +926 -0
  87. package/src/examples/input-demo.ts +377 -0
  88. package/src/examples/input-select-layout-demo.ts +425 -0
  89. package/src/examples/install.sh +143 -0
  90. package/src/examples/keypress-debug-demo.ts +452 -0
  91. package/src/examples/lib/HexList.ts +122 -0
  92. package/src/examples/lib/PaletteGrid.ts +125 -0
  93. package/src/examples/lib/standalone-keys.ts +25 -0
  94. package/src/examples/lib/tab-controller.ts +243 -0
  95. package/src/examples/lights-phong-demo.ts +290 -0
  96. package/src/examples/link-demo.ts +220 -0
  97. package/src/examples/live-state-demo.ts +480 -0
  98. package/src/examples/markdown-demo.ts +725 -0
  99. package/src/examples/mouse-interaction-demo.ts +428 -0
  100. package/src/examples/nested-zindex-demo.ts +357 -0
  101. package/src/examples/opacity-example.ts +235 -0
  102. package/src/examples/opentui-demo.ts +1057 -0
  103. package/src/examples/physx-planck-2d-demo.ts +623 -0
  104. package/src/examples/physx-rapier-2d-demo.ts +655 -0
  105. package/src/examples/relative-positioning-demo.ts +323 -0
  106. package/src/examples/scroll-example.ts +214 -0
  107. package/src/examples/scrollbox-mouse-test.ts +112 -0
  108. package/src/examples/scrollbox-overlay-hit-test.ts +206 -0
  109. package/src/examples/select-demo.ts +237 -0
  110. package/src/examples/shader-cube-demo.ts +1015 -0
  111. package/src/examples/simple-layout-example.ts +591 -0
  112. package/src/examples/slider-demo.ts +617 -0
  113. package/src/examples/split-mode-demo.ts +453 -0
  114. package/src/examples/sprite-animation-demo.ts +443 -0
  115. package/src/examples/sprite-particle-generator-demo.ts +486 -0
  116. package/src/examples/static-sprite-demo.ts +193 -0
  117. package/src/examples/sticky-scroll-example.ts +308 -0
  118. package/src/examples/styled-text-demo.ts +282 -0
  119. package/src/examples/tab-select-demo.ts +219 -0
  120. package/src/examples/terminal-title.ts +29 -0
  121. package/src/examples/terminal.ts +305 -0
  122. package/src/examples/text-node-demo.ts +416 -0
  123. package/src/examples/text-selection-demo.ts +377 -0
  124. package/src/examples/text-table-demo.ts +503 -0
  125. package/src/examples/text-truncation-demo.ts +481 -0
  126. package/src/examples/text-wrap.ts +757 -0
  127. package/src/examples/texture-loading-demo.ts +259 -0
  128. package/src/examples/timeline-example.ts +670 -0
  129. package/src/examples/transparency-demo.ts +400 -0
  130. package/src/examples/vnode-composition-demo.ts +404 -0
  131. package/src/examples/wide-grapheme-overlay-demo.ts +280 -0
  132. package/src/index.ts +24 -0
  133. package/src/lib/KeyHandler.integration.test.ts +292 -0
  134. package/src/lib/KeyHandler.stopPropagation.test.ts +289 -0
  135. package/src/lib/KeyHandler.test.ts +662 -0
  136. package/src/lib/KeyHandler.ts +222 -0
  137. package/src/lib/RGBA.test.ts +984 -0
  138. package/src/lib/RGBA.ts +204 -0
  139. package/src/lib/ascii.font.ts +330 -0
  140. package/src/lib/border.test.ts +83 -0
  141. package/src/lib/border.ts +170 -0
  142. package/src/lib/bunfs.test.ts +27 -0
  143. package/src/lib/bunfs.ts +18 -0
  144. package/src/lib/clipboard.test.ts +41 -0
  145. package/src/lib/clipboard.ts +47 -0
  146. package/src/lib/clock.ts +35 -0
  147. package/src/lib/data-paths.test.ts +133 -0
  148. package/src/lib/data-paths.ts +109 -0
  149. package/src/lib/debounce.ts +106 -0
  150. package/src/lib/detect-links.test.ts +98 -0
  151. package/src/lib/detect-links.ts +56 -0
  152. package/src/lib/env.test.ts +228 -0
  153. package/src/lib/env.ts +209 -0
  154. package/src/lib/extmarks-history.ts +51 -0
  155. package/src/lib/extmarks-multiwidth.test.ts +322 -0
  156. package/src/lib/extmarks.test.ts +3457 -0
  157. package/src/lib/extmarks.ts +843 -0
  158. package/src/lib/fonts/block.json +405 -0
  159. package/src/lib/fonts/grid.json +265 -0
  160. package/src/lib/fonts/huge.json +741 -0
  161. package/src/lib/fonts/pallet.json +314 -0
  162. package/src/lib/fonts/shade.json +591 -0
  163. package/src/lib/fonts/slick.json +321 -0
  164. package/src/lib/fonts/tiny.json +69 -0
  165. package/src/lib/hast-styled-text.ts +59 -0
  166. package/src/lib/index.ts +21 -0
  167. package/src/lib/keymapping.test.ts +317 -0
  168. package/src/lib/keymapping.ts +115 -0
  169. package/src/lib/objects-in-viewport.test.ts +787 -0
  170. package/src/lib/objects-in-viewport.ts +153 -0
  171. package/src/lib/output.capture.ts +58 -0
  172. package/src/lib/parse.keypress-kitty.protocol.test.ts +340 -0
  173. package/src/lib/parse.keypress-kitty.test.ts +663 -0
  174. package/src/lib/parse.keypress-kitty.ts +439 -0
  175. package/src/lib/parse.keypress.test.ts +1849 -0
  176. package/src/lib/parse.keypress.ts +397 -0
  177. package/src/lib/parse.mouse.test.ts +552 -0
  178. package/src/lib/parse.mouse.ts +232 -0
  179. package/src/lib/paste.ts +16 -0
  180. package/src/lib/queue.ts +65 -0
  181. package/src/lib/renderable.validations.test.ts +87 -0
  182. package/src/lib/renderable.validations.ts +83 -0
  183. package/src/lib/scroll-acceleration.ts +98 -0
  184. package/src/lib/selection.ts +240 -0
  185. package/src/lib/singleton.ts +28 -0
  186. package/src/lib/stdin-parser.test.ts +2290 -0
  187. package/src/lib/stdin-parser.ts +1810 -0
  188. package/src/lib/styled-text.ts +178 -0
  189. package/src/lib/terminal-capability-detection.test.ts +202 -0
  190. package/src/lib/terminal-capability-detection.ts +79 -0
  191. package/src/lib/terminal-palette.test.ts +878 -0
  192. package/src/lib/terminal-palette.ts +383 -0
  193. package/src/lib/tree-sitter/assets/README.md +118 -0
  194. package/src/lib/tree-sitter/assets/update.ts +334 -0
  195. package/src/lib/tree-sitter/assets.d.ts +9 -0
  196. package/src/lib/tree-sitter/cache.test.ts +273 -0
  197. package/src/lib/tree-sitter/client.test.ts +1165 -0
  198. package/src/lib/tree-sitter/client.ts +607 -0
  199. package/src/lib/tree-sitter/default-parsers.ts +86 -0
  200. package/src/lib/tree-sitter/download-utils.ts +148 -0
  201. package/src/lib/tree-sitter/index.ts +28 -0
  202. package/src/lib/tree-sitter/parser.worker.ts +1042 -0
  203. package/src/lib/tree-sitter/parsers-config.ts +81 -0
  204. package/src/lib/tree-sitter/resolve-ft.test.ts +55 -0
  205. package/src/lib/tree-sitter/resolve-ft.ts +189 -0
  206. package/src/lib/tree-sitter/types.ts +82 -0
  207. package/src/lib/tree-sitter-styled-text.test.ts +1253 -0
  208. package/src/lib/tree-sitter-styled-text.ts +306 -0
  209. package/src/lib/validate-dir-name.ts +55 -0
  210. package/src/lib/yoga.options.test.ts +628 -0
  211. package/src/lib/yoga.options.ts +346 -0
  212. package/src/plugins/core-slot.ts +579 -0
  213. package/src/plugins/registry.ts +402 -0
  214. package/src/plugins/types.ts +46 -0
  215. package/src/post/effects.ts +930 -0
  216. package/src/post/filters.ts +489 -0
  217. package/src/post/matrices.ts +288 -0
  218. package/src/renderables/ASCIIFont.ts +219 -0
  219. package/src/renderables/Box.test.ts +205 -0
  220. package/src/renderables/Box.ts +326 -0
  221. package/src/renderables/Code.test.ts +2062 -0
  222. package/src/renderables/Code.ts +357 -0
  223. package/src/renderables/Diff.regression.test.ts +226 -0
  224. package/src/renderables/Diff.test.ts +3101 -0
  225. package/src/renderables/Diff.ts +1211 -0
  226. package/src/renderables/EditBufferRenderable.test.ts +288 -0
  227. package/src/renderables/EditBufferRenderable.ts +1166 -0
  228. package/src/renderables/FrameBuffer.ts +47 -0
  229. package/src/renderables/Input.test.ts +1228 -0
  230. package/src/renderables/Input.ts +247 -0
  231. package/src/renderables/LineNumberRenderable.ts +724 -0
  232. package/src/renderables/Markdown.ts +1393 -0
  233. package/src/renderables/ScrollBar.ts +422 -0
  234. package/src/renderables/ScrollBox.ts +883 -0
  235. package/src/renderables/Select.test.ts +1033 -0
  236. package/src/renderables/Select.ts +524 -0
  237. package/src/renderables/Slider.test.ts +456 -0
  238. package/src/renderables/Slider.ts +342 -0
  239. package/src/renderables/TabSelect.test.ts +197 -0
  240. package/src/renderables/TabSelect.ts +455 -0
  241. package/src/renderables/Text.selection-buffer.test.ts +123 -0
  242. package/src/renderables/Text.test.ts +2660 -0
  243. package/src/renderables/Text.ts +147 -0
  244. package/src/renderables/TextBufferRenderable.ts +518 -0
  245. package/src/renderables/TextNode.test.ts +1058 -0
  246. package/src/renderables/TextNode.ts +325 -0
  247. package/src/renderables/TextTable.test.ts +1421 -0
  248. package/src/renderables/TextTable.ts +1344 -0
  249. package/src/renderables/Textarea.ts +430 -0
  250. package/src/renderables/TimeToFirstDraw.ts +89 -0
  251. package/src/renderables/__snapshots__/Code.test.ts.snap +13 -0
  252. package/src/renderables/__snapshots__/Diff.test.ts.snap +785 -0
  253. package/src/renderables/__snapshots__/Text.test.ts.snap +421 -0
  254. package/src/renderables/__snapshots__/TextTable.test.ts.snap +215 -0
  255. package/src/renderables/__tests__/LineNumberRenderable.scrollbox-simple.test.ts +144 -0
  256. package/src/renderables/__tests__/LineNumberRenderable.scrollbox.test.ts +816 -0
  257. package/src/renderables/__tests__/LineNumberRenderable.test.ts +1865 -0
  258. package/src/renderables/__tests__/LineNumberRenderable.wrapping.test.ts +85 -0
  259. package/src/renderables/__tests__/Markdown.code-colors.test.ts +242 -0
  260. package/src/renderables/__tests__/Markdown.test.ts +2518 -0
  261. package/src/renderables/__tests__/MultiRenderable.selection.test.ts +87 -0
  262. package/src/renderables/__tests__/Textarea.buffer.test.ts +682 -0
  263. package/src/renderables/__tests__/Textarea.destroyed-events.test.ts +675 -0
  264. package/src/renderables/__tests__/Textarea.editing.test.ts +2041 -0
  265. package/src/renderables/__tests__/Textarea.error-handling.test.ts +35 -0
  266. package/src/renderables/__tests__/Textarea.events.test.ts +738 -0
  267. package/src/renderables/__tests__/Textarea.highlights.test.ts +590 -0
  268. package/src/renderables/__tests__/Textarea.keybinding.test.ts +3149 -0
  269. package/src/renderables/__tests__/Textarea.paste.test.ts +357 -0
  270. package/src/renderables/__tests__/Textarea.rendering.test.ts +1866 -0
  271. package/src/renderables/__tests__/Textarea.scroll.test.ts +733 -0
  272. package/src/renderables/__tests__/Textarea.selection.test.ts +1590 -0
  273. package/src/renderables/__tests__/Textarea.stress.test.ts +670 -0
  274. package/src/renderables/__tests__/Textarea.undo-redo.test.ts +383 -0
  275. package/src/renderables/__tests__/Textarea.visual-lines.test.ts +310 -0
  276. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.code.test.ts.snap +221 -0
  277. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox-simple.test.ts.snap +89 -0
  278. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox.test.ts.snap +457 -0
  279. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.test.ts.snap +158 -0
  280. package/src/renderables/__tests__/__snapshots__/Textarea.rendering.test.ts.snap +387 -0
  281. package/src/renderables/__tests__/markdown-parser.test.ts +217 -0
  282. package/src/renderables/__tests__/renderable-test-utils.ts +60 -0
  283. package/src/renderables/composition/README.md +8 -0
  284. package/src/renderables/composition/VRenderable.ts +32 -0
  285. package/src/renderables/composition/constructs.ts +127 -0
  286. package/src/renderables/composition/vnode.ts +289 -0
  287. package/src/renderables/index.ts +23 -0
  288. package/src/renderables/markdown-parser.ts +66 -0
  289. package/src/renderer.ts +2681 -0
  290. package/src/runtime-plugin-support.ts +39 -0
  291. package/src/runtime-plugin.ts +615 -0
  292. package/src/syntax-style.test.ts +841 -0
  293. package/src/syntax-style.ts +257 -0
  294. package/src/testing/README.md +210 -0
  295. package/src/testing/capture-spans.test.ts +194 -0
  296. package/src/testing/integration.test.ts +276 -0
  297. package/src/testing/manual-clock.ts +117 -0
  298. package/src/testing/mock-keys.test.ts +1378 -0
  299. package/src/testing/mock-keys.ts +457 -0
  300. package/src/testing/mock-mouse.test.ts +218 -0
  301. package/src/testing/mock-mouse.ts +247 -0
  302. package/src/testing/mock-tree-sitter-client.ts +73 -0
  303. package/src/testing/spy.ts +13 -0
  304. package/src/testing/test-recorder.test.ts +415 -0
  305. package/src/testing/test-recorder.ts +145 -0
  306. package/src/testing/test-renderer.ts +132 -0
  307. package/src/testing.ts +7 -0
  308. package/src/tests/__snapshots__/absolute-positioning.snapshot.test.ts.snap +481 -0
  309. package/src/tests/__snapshots__/renderable.snapshot.test.ts.snap +19 -0
  310. package/src/tests/__snapshots__/scrollbox.test.ts.snap +29 -0
  311. package/src/tests/absolute-positioning.snapshot.test.ts +638 -0
  312. package/src/tests/allocator-stats.test.ts +38 -0
  313. package/src/tests/destroy-during-render.test.ts +200 -0
  314. package/src/tests/destroy-on-exit.fixture.ts +36 -0
  315. package/src/tests/destroy-on-exit.test.ts +41 -0
  316. package/src/tests/hover-cursor.test.ts +98 -0
  317. package/src/tests/native-span-feed-async.test.ts +173 -0
  318. package/src/tests/native-span-feed-close.test.ts +120 -0
  319. package/src/tests/native-span-feed-coverage.test.ts +227 -0
  320. package/src/tests/native-span-feed-edge-cases.test.ts +352 -0
  321. package/src/tests/native-span-feed-use-after-free.test.ts +45 -0
  322. package/src/tests/opacity.test.ts +123 -0
  323. package/src/tests/renderable.snapshot.test.ts +524 -0
  324. package/src/tests/renderable.test.ts +1281 -0
  325. package/src/tests/renderer.clock.test.ts +158 -0
  326. package/src/tests/renderer.console-startup.test.ts +185 -0
  327. package/src/tests/renderer.control.test.ts +425 -0
  328. package/src/tests/renderer.core-slot-binding.test.ts +952 -0
  329. package/src/tests/renderer.cursor.test.ts +26 -0
  330. package/src/tests/renderer.destroy-during-render.test.ts +147 -0
  331. package/src/tests/renderer.focus-restore.test.ts +257 -0
  332. package/src/tests/renderer.focus.test.ts +294 -0
  333. package/src/tests/renderer.idle.test.ts +219 -0
  334. package/src/tests/renderer.input.test.ts +2237 -0
  335. package/src/tests/renderer.kitty-flags.test.ts +195 -0
  336. package/src/tests/renderer.mouse.test.ts +1274 -0
  337. package/src/tests/renderer.palette.test.ts +629 -0
  338. package/src/tests/renderer.selection.test.ts +49 -0
  339. package/src/tests/renderer.slot-registry.test.ts +684 -0
  340. package/src/tests/renderer.useMouse.test.ts +47 -0
  341. package/src/tests/runtime-plugin-node-modules-cycle.fixture.ts +76 -0
  342. package/src/tests/runtime-plugin-node-modules-mjs.fixture.ts +43 -0
  343. package/src/tests/runtime-plugin-node-modules-no-bare-rewrite.fixture.ts +67 -0
  344. package/src/tests/runtime-plugin-node-modules-package-type-cache.fixture.ts +72 -0
  345. package/src/tests/runtime-plugin-node-modules-runtime-specifier.fixture.ts +44 -0
  346. package/src/tests/runtime-plugin-node-modules-scoped-package-bare-rewrite.fixture.ts +85 -0
  347. package/src/tests/runtime-plugin-path-alias.fixture.ts +43 -0
  348. package/src/tests/runtime-plugin-resolve-roots.fixture.ts +65 -0
  349. package/src/tests/runtime-plugin-support.fixture.ts +11 -0
  350. package/src/tests/runtime-plugin-support.test.ts +19 -0
  351. package/src/tests/runtime-plugin-windows-file-url.fixture.ts +30 -0
  352. package/src/tests/runtime-plugin.fixture.ts +40 -0
  353. package/src/tests/runtime-plugin.test.ts +354 -0
  354. package/src/tests/scrollbox-culling-bug.test.ts +114 -0
  355. package/src/tests/scrollbox-hitgrid-resize.test.ts +136 -0
  356. package/src/tests/scrollbox-hitgrid.test.ts +909 -0
  357. package/src/tests/scrollbox.test.ts +1530 -0
  358. package/src/tests/wrap-resize-perf.test.ts +276 -0
  359. package/src/tests/yoga-setters.test.ts +921 -0
  360. package/src/text-buffer-view.test.ts +705 -0
  361. package/src/text-buffer-view.ts +189 -0
  362. package/src/text-buffer.test.ts +347 -0
  363. package/src/text-buffer.ts +250 -0
  364. package/src/types.ts +161 -0
  365. package/src/utils.ts +88 -0
  366. package/src/zig/ansi.zig +268 -0
  367. package/src/zig/bench/README.md +50 -0
  368. package/src/zig/bench/buffer-draw-text-buffer_bench.zig +887 -0
  369. package/src/zig/bench/edit-buffer_bench.zig +476 -0
  370. package/src/zig/bench/native-span-feed_bench.zig +100 -0
  371. package/src/zig/bench/rope-markers_bench.zig +713 -0
  372. package/src/zig/bench/rope_bench.zig +514 -0
  373. package/src/zig/bench/styled-text_bench.zig +470 -0
  374. package/src/zig/bench/text-buffer-coords_bench.zig +362 -0
  375. package/src/zig/bench/text-buffer-view_bench.zig +459 -0
  376. package/src/zig/bench/text-chunk-graphemes_bench.zig +273 -0
  377. package/src/zig/bench/utf8_bench.zig +799 -0
  378. package/src/zig/bench-utils.zig +431 -0
  379. package/src/zig/bench.zig +217 -0
  380. package/src/zig/buffer-methods.zig +211 -0
  381. package/src/zig/buffer.zig +2281 -0
  382. package/src/zig/build.zig +289 -0
  383. package/src/zig/build.zig.zon +16 -0
  384. package/src/zig/edit-buffer.zig +825 -0
  385. package/src/zig/editor-view.zig +802 -0
  386. package/src/zig/event-bus.zig +13 -0
  387. package/src/zig/event-emitter.zig +65 -0
  388. package/src/zig/file-logger.zig +92 -0
  389. package/src/zig/grapheme.zig +599 -0
  390. package/src/zig/lib.zig +1854 -0
  391. package/src/zig/link.zig +333 -0
  392. package/src/zig/logger.zig +43 -0
  393. package/src/zig/mem-registry.zig +125 -0
  394. package/src/zig/native-span-feed-bench-lib.zig +7 -0
  395. package/src/zig/native-span-feed.zig +708 -0
  396. package/src/zig/renderer.zig +1393 -0
  397. package/src/zig/rope.zig +1220 -0
  398. package/src/zig/syntax-style.zig +161 -0
  399. package/src/zig/terminal.zig +987 -0
  400. package/src/zig/test.zig +72 -0
  401. package/src/zig/tests/README.md +18 -0
  402. package/src/zig/tests/buffer-methods_test.zig +1109 -0
  403. package/src/zig/tests/buffer_test.zig +2557 -0
  404. package/src/zig/tests/edit-buffer-history_test.zig +271 -0
  405. package/src/zig/tests/edit-buffer_test.zig +1689 -0
  406. package/src/zig/tests/editor-view_test.zig +3299 -0
  407. package/src/zig/tests/event-emitter_test.zig +249 -0
  408. package/src/zig/tests/grapheme_test.zig +1304 -0
  409. package/src/zig/tests/link_test.zig +190 -0
  410. package/src/zig/tests/mem-registry_test.zig +473 -0
  411. package/src/zig/tests/memory_leak_regression_test.zig +159 -0
  412. package/src/zig/tests/native-span-feed_test.zig +1264 -0
  413. package/src/zig/tests/renderer_test.zig +1017 -0
  414. package/src/zig/tests/rope-nested_test.zig +712 -0
  415. package/src/zig/tests/rope_fuzz_test.zig +238 -0
  416. package/src/zig/tests/rope_test.zig +2362 -0
  417. package/src/zig/tests/segment-merge.test.zig +148 -0
  418. package/src/zig/tests/syntax-style_test.zig +557 -0
  419. package/src/zig/tests/terminal_test.zig +754 -0
  420. package/src/zig/tests/text-buffer-drawing_test.zig +3237 -0
  421. package/src/zig/tests/text-buffer-highlights_test.zig +666 -0
  422. package/src/zig/tests/text-buffer-iterators_test.zig +776 -0
  423. package/src/zig/tests/text-buffer-segment_test.zig +320 -0
  424. package/src/zig/tests/text-buffer-selection_test.zig +1035 -0
  425. package/src/zig/tests/text-buffer-selection_viewport_test.zig +358 -0
  426. package/src/zig/tests/text-buffer-view_test.zig +3649 -0
  427. package/src/zig/tests/text-buffer_test.zig +2191 -0
  428. package/src/zig/tests/unicode-width-map.zon +3909 -0
  429. package/src/zig/tests/utf8_no_zwj_test.zig +260 -0
  430. package/src/zig/tests/utf8_test.zig +4057 -0
  431. package/src/zig/tests/utf8_wcwidth_cursor_test.zig +267 -0
  432. package/src/zig/tests/utf8_wcwidth_test.zig +357 -0
  433. package/src/zig/tests/word-wrap-editing_test.zig +498 -0
  434. package/src/zig/tests/wrap-cache-perf_test.zig +113 -0
  435. package/src/zig/text-buffer-iterators.zig +499 -0
  436. package/src/zig/text-buffer-segment.zig +404 -0
  437. package/src/zig/text-buffer-view.zig +1371 -0
  438. package/src/zig/text-buffer.zig +1180 -0
  439. package/src/zig/utf8.zig +1948 -0
  440. package/src/zig/utils.zig +9 -0
  441. package/src/zig-structs.ts +261 -0
  442. package/src/zig.ts +3884 -0
  443. package/tsconfig.build.json +24 -0
  444. package/tsconfig.json +27 -0
  445. package/3d/SpriteResourceManager.d.ts +0 -74
  446. package/3d/SpriteUtils.d.ts +0 -13
  447. package/3d/TextureUtils.d.ts +0 -24
  448. package/3d/ThreeRenderable.d.ts +0 -40
  449. package/3d/WGPURenderer.d.ts +0 -61
  450. package/3d/animation/ExplodingSpriteEffect.d.ts +0 -71
  451. package/3d/animation/PhysicsExplodingSpriteEffect.d.ts +0 -76
  452. package/3d/animation/SpriteAnimator.d.ts +0 -124
  453. package/3d/animation/SpriteParticleGenerator.d.ts +0 -62
  454. package/3d/canvas.d.ts +0 -44
  455. package/3d/index.d.ts +0 -12
  456. package/3d/physics/PlanckPhysicsAdapter.d.ts +0 -19
  457. package/3d/physics/RapierPhysicsAdapter.d.ts +0 -19
  458. package/3d/physics/physics-interface.d.ts +0 -27
  459. package/3d.d.ts +0 -2
  460. package/3d.js +0 -34041
  461. package/3d.js.map +0 -155
  462. package/LICENSE +0 -21
  463. package/NativeSpanFeed.d.ts +0 -41
  464. package/Renderable.d.ts +0 -334
  465. package/animation/Timeline.d.ts +0 -126
  466. package/ansi.d.ts +0 -13
  467. package/buffer.d.ts +0 -111
  468. package/console.d.ts +0 -144
  469. package/edit-buffer.d.ts +0 -98
  470. package/editor-view.d.ts +0 -73
  471. package/index-9vwc3fg6.js +0 -12260
  472. package/index-9vwc3fg6.js.map +0 -42
  473. package/index-dcj62y8t.js +0 -20614
  474. package/index-dcj62y8t.js.map +0 -67
  475. package/index-f7n39gpy.js +0 -411
  476. package/index-f7n39gpy.js.map +0 -10
  477. package/index.d.ts +0 -23
  478. package/index.js +0 -478
  479. package/index.js.map +0 -9
  480. package/lib/KeyHandler.d.ts +0 -61
  481. package/lib/RGBA.d.ts +0 -25
  482. package/lib/ascii.font.d.ts +0 -508
  483. package/lib/border.d.ts +0 -51
  484. package/lib/bunfs.d.ts +0 -7
  485. package/lib/clipboard.d.ts +0 -17
  486. package/lib/clock.d.ts +0 -15
  487. package/lib/data-paths.d.ts +0 -26
  488. package/lib/debounce.d.ts +0 -42
  489. package/lib/detect-links.d.ts +0 -6
  490. package/lib/env.d.ts +0 -42
  491. package/lib/extmarks-history.d.ts +0 -17
  492. package/lib/extmarks.d.ts +0 -89
  493. package/lib/hast-styled-text.d.ts +0 -17
  494. package/lib/index.d.ts +0 -21
  495. package/lib/keymapping.d.ts +0 -25
  496. package/lib/objects-in-viewport.d.ts +0 -24
  497. package/lib/output.capture.d.ts +0 -24
  498. package/lib/parse.keypress-kitty.d.ts +0 -2
  499. package/lib/parse.keypress.d.ts +0 -26
  500. package/lib/parse.mouse.d.ts +0 -30
  501. package/lib/paste.d.ts +0 -7
  502. package/lib/queue.d.ts +0 -15
  503. package/lib/renderable.validations.d.ts +0 -12
  504. package/lib/scroll-acceleration.d.ts +0 -43
  505. package/lib/selection.d.ts +0 -63
  506. package/lib/singleton.d.ts +0 -7
  507. package/lib/stdin-parser.d.ts +0 -87
  508. package/lib/styled-text.d.ts +0 -63
  509. package/lib/terminal-capability-detection.d.ts +0 -30
  510. package/lib/terminal-palette.d.ts +0 -50
  511. package/lib/tree-sitter/assets/update.d.ts +0 -11
  512. package/lib/tree-sitter/client.d.ts +0 -47
  513. package/lib/tree-sitter/default-parsers.d.ts +0 -2
  514. package/lib/tree-sitter/download-utils.d.ts +0 -21
  515. package/lib/tree-sitter/index.d.ts +0 -8
  516. package/lib/tree-sitter/parser.worker.d.ts +0 -1
  517. package/lib/tree-sitter/parsers-config.d.ts +0 -53
  518. package/lib/tree-sitter/resolve-ft.d.ts +0 -5
  519. package/lib/tree-sitter/types.d.ts +0 -82
  520. package/lib/tree-sitter-styled-text.d.ts +0 -14
  521. package/lib/validate-dir-name.d.ts +0 -1
  522. package/lib/yoga.options.d.ts +0 -32
  523. package/parser.worker.js +0 -899
  524. package/parser.worker.js.map +0 -12
  525. package/plugins/core-slot.d.ts +0 -72
  526. package/plugins/registry.d.ts +0 -42
  527. package/plugins/types.d.ts +0 -34
  528. package/post/effects.d.ts +0 -147
  529. package/post/filters.d.ts +0 -65
  530. package/post/matrices.d.ts +0 -20
  531. package/renderables/ASCIIFont.d.ts +0 -52
  532. package/renderables/Box.d.ts +0 -81
  533. package/renderables/Code.d.ts +0 -78
  534. package/renderables/Diff.d.ts +0 -142
  535. package/renderables/EditBufferRenderable.d.ts +0 -237
  536. package/renderables/FrameBuffer.d.ts +0 -16
  537. package/renderables/Input.d.ts +0 -67
  538. package/renderables/LineNumberRenderable.d.ts +0 -78
  539. package/renderables/Markdown.d.ts +0 -185
  540. package/renderables/ScrollBar.d.ts +0 -77
  541. package/renderables/ScrollBox.d.ts +0 -124
  542. package/renderables/Select.d.ts +0 -115
  543. package/renderables/Slider.d.ts +0 -47
  544. package/renderables/TabSelect.d.ts +0 -96
  545. package/renderables/Text.d.ts +0 -36
  546. package/renderables/TextBufferRenderable.d.ts +0 -105
  547. package/renderables/TextNode.d.ts +0 -91
  548. package/renderables/TextTable.d.ts +0 -140
  549. package/renderables/Textarea.d.ts +0 -63
  550. package/renderables/TimeToFirstDraw.d.ts +0 -24
  551. package/renderables/__tests__/renderable-test-utils.d.ts +0 -12
  552. package/renderables/composition/VRenderable.d.ts +0 -16
  553. package/renderables/composition/constructs.d.ts +0 -35
  554. package/renderables/composition/vnode.d.ts +0 -46
  555. package/renderables/index.d.ts +0 -23
  556. package/renderables/markdown-parser.d.ts +0 -10
  557. package/renderer.d.ts +0 -419
  558. package/runtime-plugin-support.d.ts +0 -3
  559. package/runtime-plugin-support.js +0 -29
  560. package/runtime-plugin-support.js.map +0 -10
  561. package/runtime-plugin.d.ts +0 -16
  562. package/runtime-plugin.js +0 -16
  563. package/runtime-plugin.js.map +0 -9
  564. package/syntax-style.d.ts +0 -54
  565. package/testing/manual-clock.d.ts +0 -17
  566. package/testing/mock-keys.d.ts +0 -81
  567. package/testing/mock-mouse.d.ts +0 -38
  568. package/testing/mock-tree-sitter-client.d.ts +0 -23
  569. package/testing/spy.d.ts +0 -7
  570. package/testing/test-recorder.d.ts +0 -61
  571. package/testing/test-renderer.d.ts +0 -23
  572. package/testing.d.ts +0 -6
  573. package/testing.js +0 -697
  574. package/testing.js.map +0 -15
  575. package/text-buffer-view.d.ts +0 -42
  576. package/text-buffer.d.ts +0 -67
  577. package/types.d.ts +0 -139
  578. package/utils.d.ts +0 -14
  579. package/zig-structs.d.ts +0 -155
  580. package/zig.d.ts +0 -353
  581. /package/{assets → src/lib/tree-sitter/assets}/javascript/highlights.scm +0 -0
  582. /package/{assets → src/lib/tree-sitter/assets}/javascript/tree-sitter-javascript.wasm +0 -0
  583. /package/{assets → src/lib/tree-sitter/assets}/markdown/highlights.scm +0 -0
  584. /package/{assets → src/lib/tree-sitter/assets}/markdown/injections.scm +0 -0
  585. /package/{assets → src/lib/tree-sitter/assets}/markdown/tree-sitter-markdown.wasm +0 -0
  586. /package/{assets → src/lib/tree-sitter/assets}/markdown_inline/highlights.scm +0 -0
  587. /package/{assets → src/lib/tree-sitter/assets}/markdown_inline/tree-sitter-markdown_inline.wasm +0 -0
  588. /package/{assets → src/lib/tree-sitter/assets}/typescript/highlights.scm +0 -0
  589. /package/{assets → src/lib/tree-sitter/assets}/typescript/tree-sitter-typescript.wasm +0 -0
  590. /package/{assets → src/lib/tree-sitter/assets}/zig/highlights.scm +0 -0
  591. /package/{assets → src/lib/tree-sitter/assets}/zig/tree-sitter-zig.wasm +0 -0
@@ -0,0 +1,682 @@
1
+ import { describe, expect, it, beforeEach, afterEach } from "bun:test"
2
+ import { createTestRenderer, type TestRenderer, type MockInput } from "../../testing/test-renderer.js"
3
+ import { createTextareaRenderable } from "./renderable-test-utils.js"
4
+
5
+ let currentRenderer: TestRenderer
6
+ let renderOnce: () => Promise<void>
7
+ let currentMockInput: MockInput
8
+
9
+ describe("Textarea - Buffer Tests", () => {
10
+ beforeEach(async () => {
11
+ ;({
12
+ renderer: currentRenderer,
13
+ renderOnce,
14
+ mockInput: currentMockInput,
15
+ } = await createTestRenderer({
16
+ width: 80,
17
+ height: 24,
18
+ }))
19
+ })
20
+
21
+ afterEach(() => {
22
+ currentRenderer.destroy()
23
+ })
24
+
25
+ describe("getTextRange", () => {
26
+ it("should get text range by display-width offsets", async () => {
27
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
28
+ initialValue: "Hello, World!\nThis is line 2.",
29
+ width: 40,
30
+ height: 10,
31
+ })
32
+
33
+ const range1 = editor.getTextRange(0, 5)
34
+ expect(range1).toBe("Hello")
35
+
36
+ const range2 = editor.getTextRange(7, 12)
37
+ expect(range2).toBe("World")
38
+
39
+ const range3 = editor.getTextRange(0, 13)
40
+ expect(range3).toBe("Hello, World!")
41
+
42
+ const range4 = editor.getTextRange(14, 21)
43
+ expect(range4).toBe("This is")
44
+ })
45
+
46
+ it("should get text range by row/col coordinates", async () => {
47
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
48
+ initialValue: "Hello, World!\nThis is line 2.",
49
+ width: 40,
50
+ height: 10,
51
+ })
52
+
53
+ const range1 = editor.getTextRangeByCoords(0, 0, 0, 5)
54
+ expect(range1).toBe("Hello")
55
+
56
+ const range2 = editor.getTextRangeByCoords(0, 7, 0, 12)
57
+ expect(range2).toBe("World")
58
+
59
+ const range3 = editor.getTextRangeByCoords(1, 0, 1, 7)
60
+ expect(range3).toBe("This is")
61
+
62
+ const range4 = editor.getTextRangeByCoords(0, 0, 1, 7)
63
+ expect(range4).toBe("Hello, World!\nThis is")
64
+ })
65
+
66
+ it("should handle empty ranges with getTextRangeByCoords", async () => {
67
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
68
+ initialValue: "Hello, World!",
69
+ width: 40,
70
+ height: 10,
71
+ })
72
+
73
+ const rangeEmpty = editor.getTextRangeByCoords(0, 5, 0, 5)
74
+ expect(rangeEmpty).toBe("")
75
+
76
+ const rangeInvalid = editor.getTextRangeByCoords(0, 10, 0, 5)
77
+ expect(rangeInvalid).toBe("")
78
+ })
79
+
80
+ it("should handle ranges spanning multiple lines with getTextRangeByCoords", async () => {
81
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
82
+ initialValue: "Line 1\nLine 2\nLine 3",
83
+ width: 40,
84
+ height: 10,
85
+ })
86
+
87
+ const range1 = editor.getTextRangeByCoords(0, 5, 1, 4)
88
+ expect(range1).toBe("1\nLine")
89
+
90
+ const range2 = editor.getTextRangeByCoords(0, 0, 2, 6)
91
+ expect(range2).toBe("Line 1\nLine 2\nLine 3")
92
+
93
+ const range3 = editor.getTextRangeByCoords(1, 0, 2, 6)
94
+ expect(range3).toBe("Line 2\nLine 3")
95
+ })
96
+
97
+ it("should handle Unicode characters with getTextRangeByCoords", async () => {
98
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
99
+ initialValue: "Hello 🌟 World",
100
+ width: 40,
101
+ height: 10,
102
+ })
103
+
104
+ const range1 = editor.getTextRangeByCoords(0, 0, 0, 6)
105
+ expect(range1).toBe("Hello ")
106
+
107
+ const range2 = editor.getTextRangeByCoords(0, 6, 0, 8)
108
+ expect(range2).toBe("🌟")
109
+
110
+ const range3 = editor.getTextRangeByCoords(0, 8, 0, 14)
111
+ expect(range3).toBe(" World")
112
+ })
113
+
114
+ it("should handle CJK characters with getTextRangeByCoords", async () => {
115
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
116
+ initialValue: "Hello 世界",
117
+ width: 40,
118
+ height: 10,
119
+ })
120
+
121
+ const range1 = editor.getTextRangeByCoords(0, 0, 0, 6)
122
+ expect(range1).toBe("Hello ")
123
+
124
+ const range2 = editor.getTextRangeByCoords(0, 6, 0, 10)
125
+ expect(range2).toBe("世界")
126
+ })
127
+
128
+ it("should get text range by coords after editing operations", async () => {
129
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
130
+ initialValue: "ABC\nDEF",
131
+ width: 40,
132
+ height: 10,
133
+ })
134
+
135
+ editor.focus()
136
+
137
+ const range1 = editor.getTextRangeByCoords(0, 0, 1, 3)
138
+ expect(range1).toBe("ABC\nDEF")
139
+
140
+ editor.gotoLine(1)
141
+ currentMockInput.pressBackspace()
142
+ expect(editor.plainText).toBe("ABCDEF")
143
+
144
+ const range2 = editor.getTextRangeByCoords(0, 1, 0, 5)
145
+ expect(range2).toBe("BCDE")
146
+
147
+ const range3 = editor.getTextRangeByCoords(0, 0, 0, 6)
148
+ expect(range3).toBe("ABCDEF")
149
+ })
150
+
151
+ it("should handle out-of-bounds coordinates with getTextRangeByCoords", async () => {
152
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
153
+ initialValue: "Short",
154
+ width: 40,
155
+ height: 10,
156
+ })
157
+
158
+ const range1 = editor.getTextRangeByCoords(10, 0, 20, 0)
159
+ expect(range1).toBe("")
160
+
161
+ const range2 = editor.getTextRangeByCoords(0, 0, 0, 5)
162
+ expect(range2).toBe("Short")
163
+
164
+ const range3 = editor.getTextRangeByCoords(0, 100, 0, 200)
165
+ expect(range3).toBe("")
166
+ })
167
+
168
+ it("should match offset-based and coords-based methods", async () => {
169
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
170
+ initialValue: "Line 1\nLine 2\nLine 3",
171
+ width: 40,
172
+ height: 10,
173
+ })
174
+
175
+ const offsetBased = editor.getTextRange(0, 6)
176
+ const coordsBased = editor.getTextRangeByCoords(0, 0, 0, 6)
177
+ expect(coordsBased).toBe(offsetBased)
178
+ expect(coordsBased).toBe("Line 1")
179
+
180
+ const offsetBased2 = editor.getTextRange(7, 13)
181
+ const coordsBased2 = editor.getTextRangeByCoords(1, 0, 1, 6)
182
+ expect(coordsBased2).toBe(offsetBased2)
183
+ expect(coordsBased2).toBe("Line 2")
184
+
185
+ const offsetBased3 = editor.getTextRange(5, 12)
186
+ const coordsBased3 = editor.getTextRangeByCoords(0, 5, 1, 5)
187
+ expect(coordsBased3).toBe(offsetBased3)
188
+ expect(coordsBased3).toBe("1\nLine ")
189
+ })
190
+
191
+ it("should handle empty ranges", async () => {
192
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
193
+ initialValue: "Hello, World!",
194
+ width: 40,
195
+ height: 10,
196
+ })
197
+
198
+ const rangeEmpty = editor.getTextRange(5, 5)
199
+ expect(rangeEmpty).toBe("")
200
+
201
+ const rangeInvalid = editor.getTextRange(10, 5)
202
+ expect(rangeInvalid).toBe("")
203
+ })
204
+
205
+ it("should handle ranges spanning multiple lines", async () => {
206
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
207
+ initialValue: "Line 1\nLine 2\nLine 3",
208
+ width: 40,
209
+ height: 10,
210
+ })
211
+
212
+ const range1 = editor.getTextRange(0, 13)
213
+ expect(range1).toBe("Line 1\nLine 2")
214
+
215
+ const range2 = editor.getTextRange(5, 12)
216
+ expect(range2).toBe("1\nLine ")
217
+ })
218
+
219
+ it("should handle Unicode characters in ranges", async () => {
220
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
221
+ initialValue: "Hello 🌟 World",
222
+ width: 40,
223
+ height: 10,
224
+ })
225
+
226
+ const range1 = editor.getTextRange(0, 6)
227
+ expect(range1).toBe("Hello ")
228
+
229
+ const range2 = editor.getTextRange(6, 8)
230
+ expect(range2).toBe("🌟")
231
+
232
+ const range3 = editor.getTextRange(8, 14)
233
+ expect(range3).toBe(" World")
234
+ })
235
+
236
+ it("should handle CJK characters in ranges", async () => {
237
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
238
+ initialValue: "Hello 世界",
239
+ width: 40,
240
+ height: 10,
241
+ })
242
+
243
+ const range1 = editor.getTextRange(0, 6)
244
+ expect(range1).toBe("Hello ")
245
+
246
+ const range2 = editor.getTextRange(6, 10)
247
+ expect(range2).toBe("世界")
248
+ })
249
+
250
+ it("should get text range after editing operations", async () => {
251
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
252
+ initialValue: "ABC",
253
+ width: 40,
254
+ height: 10,
255
+ })
256
+
257
+ editor.focus()
258
+
259
+ editor.gotoLine(9999)
260
+ editor.insertText("DEF")
261
+ expect(editor.plainText).toBe("ABCDEF")
262
+
263
+ const range1 = editor.getTextRange(0, 6)
264
+ expect(range1).toBe("ABCDEF")
265
+
266
+ const range2 = editor.getTextRange(0, 3)
267
+ expect(range2).toBe("ABC")
268
+
269
+ const range3 = editor.getTextRange(3, 6)
270
+ expect(range3).toBe("DEF")
271
+ })
272
+
273
+ it("should get text range across chunk boundaries after line joins", async () => {
274
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
275
+ initialValue: "ABC\nDEF",
276
+ width: 40,
277
+ height: 10,
278
+ })
279
+
280
+ editor.focus()
281
+ editor.gotoLine(1)
282
+
283
+ currentMockInput.pressBackspace()
284
+ expect(editor.plainText).toBe("ABCDEF")
285
+
286
+ const range1 = editor.getTextRange(1, 5)
287
+ expect(range1).toBe("BCDE")
288
+
289
+ const range2 = editor.getTextRange(0, 6)
290
+ expect(range2).toBe("ABCDEF")
291
+ })
292
+
293
+ it("should handle range at buffer boundaries", async () => {
294
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
295
+ initialValue: "Test",
296
+ width: 40,
297
+ height: 10,
298
+ })
299
+
300
+ const range1 = editor.getTextRange(0, 2)
301
+ expect(range1).toBe("Te")
302
+
303
+ const range2 = editor.getTextRange(2, 4)
304
+ expect(range2).toBe("st")
305
+
306
+ const range3 = editor.getTextRange(0, 4)
307
+ expect(range3).toBe("Test")
308
+ })
309
+
310
+ it("should return empty string for out-of-bounds ranges", async () => {
311
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
312
+ initialValue: "Short",
313
+ width: 40,
314
+ height: 10,
315
+ })
316
+
317
+ const range1 = editor.getTextRange(100, 200)
318
+ expect(range1).toBe("")
319
+
320
+ const range2 = editor.getTextRange(0, 1000)
321
+ expect(range2).toBe("Short")
322
+ })
323
+ })
324
+
325
+ describe("Visual Cursor with Offset", () => {
326
+ it("should have visualCursor with offset property", async () => {
327
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
328
+ initialValue: "",
329
+ width: 40,
330
+ height: 10,
331
+ })
332
+
333
+ editor.focus()
334
+
335
+ const visualCursor = editor.visualCursor
336
+ expect(visualCursor).not.toBe(null)
337
+ expect(visualCursor!.offset).toBeDefined()
338
+ expect(visualCursor!.offset).toBe(0)
339
+ })
340
+
341
+ it("should update offset after inserting text", async () => {
342
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
343
+ initialValue: "",
344
+ width: 40,
345
+ height: 10,
346
+ })
347
+
348
+ editor.focus()
349
+
350
+ editor.insertText("Hello")
351
+
352
+ const visualCursor = editor.visualCursor
353
+ expect(visualCursor).not.toBe(null)
354
+ expect(visualCursor!.offset).toBe(5)
355
+ })
356
+
357
+ it("should update offset correctly for multi-line content", async () => {
358
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
359
+ initialValue: "ABC\nDEF",
360
+ width: 40,
361
+ height: 10,
362
+ })
363
+
364
+ editor.focus()
365
+
366
+ // Cursor at start
367
+ let visualCursor = editor.visualCursor
368
+ expect(visualCursor!.offset).toBe(0)
369
+
370
+ // Move to end of first line
371
+ for (let i = 0; i < 3; i++) {
372
+ editor.moveCursorRight()
373
+ }
374
+ visualCursor = editor.visualCursor
375
+ expect(visualCursor!.offset).toBe(3)
376
+
377
+ // Move to second line (across newline)
378
+ editor.moveCursorRight()
379
+ visualCursor = editor.visualCursor
380
+ expect(visualCursor!.offset).toBe(4)
381
+ expect(visualCursor!.logicalRow).toBe(1)
382
+ expect(visualCursor!.logicalCol).toBe(0)
383
+
384
+ // Move to end of second line
385
+ for (let i = 0; i < 3; i++) {
386
+ editor.moveCursorRight()
387
+ }
388
+ visualCursor = editor.visualCursor
389
+ expect(visualCursor!.offset).toBe(7)
390
+ })
391
+
392
+ it("should set cursor by offset", async () => {
393
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
394
+ initialValue: "Hello World",
395
+ width: 40,
396
+ height: 10,
397
+ })
398
+
399
+ editor.focus()
400
+
401
+ // Set cursor to offset 6 (after "Hello ")
402
+ editor.editBuffer.setCursorByOffset(6)
403
+
404
+ const visualCursor = editor.visualCursor
405
+ expect(visualCursor).not.toBe(null)
406
+ expect(visualCursor!.offset).toBe(6)
407
+ expect(visualCursor!.logicalRow).toBe(0)
408
+ expect(visualCursor!.logicalCol).toBe(6)
409
+
410
+ // Set cursor to offset 2
411
+ editor.editBuffer.setCursorByOffset(2)
412
+
413
+ const newVisualCursor = editor.visualCursor
414
+ expect(newVisualCursor).not.toBe(null)
415
+ expect(newVisualCursor!.offset).toBe(2)
416
+ expect(newVisualCursor!.logicalRow).toBe(0)
417
+ expect(newVisualCursor!.logicalCol).toBe(2)
418
+ })
419
+
420
+ it("should set cursor by offset in multi-line content", async () => {
421
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
422
+ initialValue: "Line1\nLine2\nLine3",
423
+ width: 40,
424
+ height: 10,
425
+ })
426
+
427
+ editor.focus()
428
+
429
+ // Set cursor to offset 6 (start of "Line2")
430
+ editor.editBuffer.setCursorByOffset(6)
431
+
432
+ const visualCursor = editor.visualCursor
433
+ expect(visualCursor).not.toBe(null)
434
+ expect(visualCursor!.offset).toBe(6)
435
+ expect(visualCursor!.logicalRow).toBe(1)
436
+ expect(visualCursor!.logicalCol).toBe(0)
437
+
438
+ // Set cursor to offset 8 (L[i]ne2, at 'n')
439
+ editor.editBuffer.setCursorByOffset(8)
440
+
441
+ const newVisualCursor = editor.visualCursor
442
+ expect(newVisualCursor).not.toBe(null)
443
+ expect(newVisualCursor!.offset).toBe(8)
444
+ expect(newVisualCursor!.logicalRow).toBe(1)
445
+ expect(newVisualCursor!.logicalCol).toBe(2)
446
+ })
447
+
448
+ it("should maintain offset consistency when using editorView.setCursorByOffset", async () => {
449
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
450
+ initialValue: "ABCDEF",
451
+ width: 40,
452
+ height: 10,
453
+ })
454
+
455
+ editor.focus()
456
+
457
+ // Use editorView instead of editBuffer
458
+ editor.editorView.setCursorByOffset(3)
459
+
460
+ const visualCursor = editor.visualCursor
461
+ expect(visualCursor).not.toBe(null)
462
+ expect(visualCursor!.offset).toBe(3)
463
+ expect(visualCursor!.logicalRow).toBe(0)
464
+ expect(visualCursor!.logicalCol).toBe(3)
465
+ })
466
+
467
+ it("should set cursor to end of content using cursorOffset setter and Bun.stringWidth", async () => {
468
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
469
+ initialValue: "",
470
+ width: 40,
471
+ height: 10,
472
+ })
473
+
474
+ editor.focus()
475
+
476
+ const content = "Hello World"
477
+ editor.setText(content)
478
+ editor.cursorOffset = Bun.stringWidth(content)
479
+
480
+ const visualCursor = editor.visualCursor
481
+ expect(visualCursor).not.toBe(null)
482
+ expect(visualCursor!.offset).toBe(Bun.stringWidth(content))
483
+ expect(visualCursor!.logicalRow).toBe(0)
484
+ expect(visualCursor!.logicalCol).toBe(content.length)
485
+ expect(visualCursor!.visualCol).toBe(content.length)
486
+
487
+ // Verify cursor is at the end
488
+ expect(editor.cursorOffset).toBe(11)
489
+ expect(editor.plainText).toBe("Hello World")
490
+ })
491
+ })
492
+
493
+ describe("EditBufferRenderable Methods", () => {
494
+ describe("deleteRange", () => {
495
+ it("should delete range within a single line", async () => {
496
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
497
+ initialValue: "Hello World",
498
+ width: 40,
499
+ height: 10,
500
+ })
501
+
502
+ editor.deleteRange(0, 6, 0, 11)
503
+ await renderOnce()
504
+
505
+ expect(editor.plainText).toBe("Hello ")
506
+ })
507
+
508
+ it("should delete range across multiple lines", async () => {
509
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
510
+ initialValue: "Line 1\nLine 2\nLine 3",
511
+ width: 40,
512
+ height: 10,
513
+ })
514
+
515
+ editor.deleteRange(0, 5, 2, 5)
516
+ await renderOnce()
517
+
518
+ expect(editor.plainText).toBe("Line 3")
519
+ })
520
+
521
+ it("should delete entire line", async () => {
522
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
523
+ initialValue: "First\nSecond\nThird",
524
+ width: 40,
525
+ height: 10,
526
+ })
527
+
528
+ editor.deleteRange(1, 0, 1, 6)
529
+ await renderOnce()
530
+
531
+ expect(editor.plainText).toBe("First\n\nThird")
532
+ })
533
+
534
+ it("should mark yoga node as dirty and request render", async () => {
535
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
536
+ initialValue: "Test text",
537
+ width: 40,
538
+ height: 10,
539
+ })
540
+
541
+ const initialHeight = editor.height
542
+ editor.deleteRange(0, 0, 0, 5)
543
+ await renderOnce()
544
+
545
+ expect(editor.plainText).toBe("text")
546
+ })
547
+
548
+ it("should handle empty range deletion", async () => {
549
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
550
+ initialValue: "Hello",
551
+ width: 40,
552
+ height: 10,
553
+ })
554
+
555
+ editor.deleteRange(0, 2, 0, 2)
556
+ await renderOnce()
557
+
558
+ expect(editor.plainText).toBe("Hello")
559
+ })
560
+ })
561
+
562
+ describe("insertText", () => {
563
+ it("should insert text at cursor position", async () => {
564
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
565
+ initialValue: "Hello",
566
+ width: 40,
567
+ height: 10,
568
+ })
569
+
570
+ editor.insertText(" World")
571
+ await renderOnce()
572
+
573
+ expect(editor.plainText).toBe(" WorldHello")
574
+ })
575
+
576
+ it("should insert text in middle of content", async () => {
577
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
578
+ initialValue: "HelloWorld",
579
+ width: 40,
580
+ height: 10,
581
+ })
582
+
583
+ editor.editBuffer.setCursor(0, 5)
584
+ editor.insertText(" ")
585
+ await renderOnce()
586
+
587
+ expect(editor.plainText).toBe("Hello World")
588
+ })
589
+
590
+ it("should insert multiline text", async () => {
591
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
592
+ initialValue: "Start",
593
+ width: 40,
594
+ height: 10,
595
+ })
596
+
597
+ editor.editBuffer.setCursor(0, 5)
598
+ editor.insertText("\nEnd")
599
+ await renderOnce()
600
+
601
+ expect(editor.plainText).toBe("Start\nEnd")
602
+ })
603
+
604
+ it("should mark yoga node as dirty and request render", async () => {
605
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
606
+ initialValue: "",
607
+ width: 40,
608
+ height: 10,
609
+ })
610
+
611
+ editor.insertText("Test")
612
+ await renderOnce()
613
+
614
+ expect(editor.plainText).toBe("Test")
615
+ })
616
+
617
+ it("should insert multiline text and update content", async () => {
618
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
619
+ initialValue: "Line 1",
620
+ width: 40,
621
+ height: 10,
622
+ })
623
+
624
+ editor.editBuffer.setCursor(0, 6)
625
+ editor.insertText("\nLine 2\nLine 3")
626
+ await renderOnce()
627
+
628
+ expect(editor.plainText).toBe("Line 1\nLine 2\nLine 3")
629
+ expect(editor.logicalCursor.row).toBe(2)
630
+ })
631
+ })
632
+
633
+ describe("Combined deleteRange and insertText", () => {
634
+ it("should replace text by deleting range then inserting", async () => {
635
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
636
+ initialValue: "Hello World",
637
+ width: 40,
638
+ height: 10,
639
+ })
640
+
641
+ editor.deleteRange(0, 6, 0, 11)
642
+ editor.editBuffer.setCursor(0, 6)
643
+ editor.insertText("Friend")
644
+ await renderOnce()
645
+
646
+ expect(editor.plainText).toBe("Hello Friend")
647
+ })
648
+
649
+ it("should handle complex editing operations", async () => {
650
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
651
+ initialValue: "Line 1\nLine 2\nLine 3",
652
+ width: 40,
653
+ height: 10,
654
+ })
655
+
656
+ editor.deleteRange(1, 0, 1, 6)
657
+ editor.editBuffer.setCursor(1, 0)
658
+ editor.insertText("Modified")
659
+ await renderOnce()
660
+
661
+ expect(editor.plainText).toBe("Line 1\nModified\nLine 3")
662
+ })
663
+
664
+ it("should work after multiple operations", async () => {
665
+ const { textarea: editor } = await createTextareaRenderable(currentRenderer, renderOnce, {
666
+ initialValue: "Start",
667
+ width: 40,
668
+ height: 10,
669
+ })
670
+
671
+ editor.editBuffer.setCursor(0, 5)
672
+ editor.insertText(" Middle")
673
+ editor.editBuffer.setCursor(0, 12)
674
+ editor.insertText(" End")
675
+ editor.deleteRange(0, 0, 0, 5)
676
+ await renderOnce()
677
+
678
+ expect(editor.plainText).toBe(" Middle End")
679
+ })
680
+ })
681
+ })
682
+ })