@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,705 @@
1
+ import { describe, expect, it, beforeEach, afterEach } from "bun:test"
2
+ import { TextBuffer } from "./text-buffer.js"
3
+ import { TextBufferView } from "./text-buffer-view.js"
4
+ import { StyledText, stringToStyledText } from "./lib/styled-text.js"
5
+ import { RGBA } from "./lib/RGBA.js"
6
+
7
+ describe("TextBufferView", () => {
8
+ let buffer: TextBuffer
9
+ let view: TextBufferView
10
+
11
+ beforeEach(() => {
12
+ buffer = TextBuffer.create("wcwidth")
13
+ view = TextBufferView.create(buffer)
14
+ })
15
+
16
+ afterEach(() => {
17
+ view.destroy()
18
+ buffer.destroy()
19
+ })
20
+
21
+ describe("lineInfo getter with wrapping", () => {
22
+ it("should return line info for empty buffer", () => {
23
+ const emptyText = stringToStyledText("")
24
+ buffer.setStyledText(emptyText)
25
+
26
+ const lineInfo = view.lineInfo
27
+ expect(lineInfo.lineStartCols).toEqual([0])
28
+ expect(lineInfo.lineWidthCols).toEqual([0])
29
+ })
30
+
31
+ it("should return single line info for simple text without newlines", () => {
32
+ const styledText = stringToStyledText("Hello World")
33
+ buffer.setStyledText(styledText)
34
+
35
+ const lineInfo = view.lineInfo
36
+ expect(lineInfo.lineStartCols).toEqual([0])
37
+ expect(lineInfo.lineWidthCols.length).toBe(1)
38
+ expect(lineInfo.lineWidthCols[0]).toBeGreaterThan(0)
39
+ })
40
+
41
+ it("should handle single newline correctly", () => {
42
+ const styledText = stringToStyledText("Hello\nWorld")
43
+ buffer.setStyledText(styledText)
44
+
45
+ const lineInfo = view.lineInfo
46
+ // With newline-aware offsets: "Hello" (0-4) + newline (5) + "World" starts at 6
47
+ expect(lineInfo.lineStartCols).toEqual([0, 6])
48
+ expect(lineInfo.lineWidthCols.length).toBe(2)
49
+ expect(lineInfo.lineWidthCols[0]).toBeGreaterThan(0)
50
+ expect(lineInfo.lineWidthCols[1]).toBeGreaterThan(0)
51
+ })
52
+
53
+ it("should return virtual line info when text wrapping is enabled", () => {
54
+ const longText = "This is a very long text that should wrap when the text wrapping is enabled."
55
+ const styledText = stringToStyledText(longText)
56
+ buffer.setStyledText(styledText)
57
+
58
+ const unwrappedInfo = view.lineInfo
59
+ expect(unwrappedInfo.lineStartCols).toEqual([0])
60
+ expect(unwrappedInfo.lineWidthCols.length).toBe(1)
61
+ expect(unwrappedInfo.lineWidthCols[0]).toBe(76)
62
+
63
+ view.setWrapMode("char") // Enable wrapping
64
+ view.setWrapWidth(20)
65
+
66
+ const wrappedInfo = view.lineInfo
67
+
68
+ expect(wrappedInfo.lineStartCols.length).toBeGreaterThan(1)
69
+ expect(wrappedInfo.lineWidthCols.length).toBeGreaterThan(1)
70
+
71
+ for (const width of wrappedInfo.lineWidthCols) {
72
+ expect(width).toBeLessThanOrEqual(20)
73
+ }
74
+
75
+ for (let i = 1; i < wrappedInfo.lineStartCols.length; i++) {
76
+ expect(wrappedInfo.lineStartCols[i]).toBeGreaterThan(wrappedInfo.lineStartCols[i - 1])
77
+ }
78
+ })
79
+
80
+ it("should return correct lineInfo for word wrapping", () => {
81
+ const text = "Hello world this is a test"
82
+ const styledText = stringToStyledText(text)
83
+ buffer.setStyledText(styledText)
84
+
85
+ view.setWrapMode("word")
86
+ view.setWrapWidth(12)
87
+
88
+ const lineInfo = view.lineInfo
89
+
90
+ expect(lineInfo.lineStartCols.length).toBeGreaterThan(1)
91
+
92
+ for (const width of lineInfo.lineWidthCols) {
93
+ expect(width).toBeLessThanOrEqual(12)
94
+ }
95
+ })
96
+
97
+ it("should return correct lineInfo for char wrapping", () => {
98
+ const text = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
99
+ const styledText = stringToStyledText(text)
100
+ buffer.setStyledText(styledText)
101
+
102
+ view.setWrapMode("char")
103
+ view.setWrapWidth(10)
104
+
105
+ const lineInfo = view.lineInfo
106
+
107
+ expect(lineInfo.lineStartCols).toEqual([0, 10, 20])
108
+ expect(lineInfo.lineWidthCols).toEqual([10, 10, 6])
109
+ })
110
+
111
+ it("should update lineInfo when wrap width changes", () => {
112
+ const text = "The quick brown fox jumps over the lazy dog"
113
+ const styledText = stringToStyledText(text)
114
+ buffer.setStyledText(styledText)
115
+
116
+ view.setWrapMode("char") // Enable wrapping
117
+ view.setWrapWidth(15)
118
+
119
+ const lineInfo1 = view.lineInfo
120
+ const lineCount1 = lineInfo1.lineStartCols.length
121
+
122
+ view.setWrapWidth(30)
123
+
124
+ const lineInfo2 = view.lineInfo
125
+ const lineCount2 = lineInfo2.lineStartCols.length
126
+
127
+ expect(lineCount2).toBeLessThan(lineCount1)
128
+ })
129
+
130
+ it("should return original lineInfo when wrap is disabled", () => {
131
+ const text = "Line 1\nLine 2\nLine 3"
132
+ const styledText = stringToStyledText(text)
133
+ buffer.setStyledText(styledText)
134
+
135
+ const originalInfo = view.lineInfo
136
+ // With newline-aware offsets: Line 0 (0-5) + newline (6) + Line 1 (7-12) + newline (13) + Line 2 (14-19)
137
+ expect(originalInfo.lineStartCols).toEqual([0, 7, 14])
138
+
139
+ view.setWrapMode("char") // Enable wrapping
140
+ view.setWrapWidth(5)
141
+
142
+ const wrappedInfo = view.lineInfo
143
+ expect(wrappedInfo.lineStartCols.length).toBeGreaterThan(3)
144
+
145
+ view.setWrapMode("none") // Disable wrapping
146
+ view.setWrapWidth(null)
147
+
148
+ const unwrappedInfo = view.lineInfo
149
+ expect(unwrappedInfo.lineStartCols).toEqual([0, 7, 14])
150
+ })
151
+
152
+ it("should return extended wrap info", () => {
153
+ const text = "Line 1 content\nLine 2"
154
+ const styledText = stringToStyledText(text)
155
+ buffer.setStyledText(styledText)
156
+
157
+ view.setWrapMode("char")
158
+ view.setWrapWidth(10)
159
+
160
+ // Line 1 content (14 chars) wraps into two lines:
161
+ // "Line 1 con" (10)
162
+ // "tent" (4)
163
+ // Line 2 (6 chars) fits on one line
164
+
165
+ const info = view.lineInfo
166
+
167
+ expect(info.lineSources.length).toBe(3)
168
+ expect(info.lineWraps.length).toBe(3)
169
+
170
+ // First visual line: source line 0, wrap 0
171
+ expect(info.lineSources[0]).toBe(0)
172
+ expect(info.lineWraps[0]).toBe(0)
173
+
174
+ // Second visual line: source line 0, wrap 1 (continuation)
175
+ expect(info.lineSources[1]).toBe(0)
176
+ expect(info.lineWraps[1]).toBe(1)
177
+
178
+ // Third visual line: source line 1, wrap 0
179
+ expect(info.lineSources[2]).toBe(1)
180
+ expect(info.lineWraps[2]).toBe(0)
181
+ })
182
+ })
183
+
184
+ describe("getSelectedText", () => {
185
+ it("should return empty string when no selection", () => {
186
+ const styledText = stringToStyledText("Hello World")
187
+ buffer.setStyledText(styledText)
188
+
189
+ const selectedText = view.getSelectedText()
190
+ expect(selectedText).toBe("")
191
+ })
192
+
193
+ it("should return selected text for simple selection", () => {
194
+ const styledText = stringToStyledText("Hello World")
195
+ buffer.setStyledText(styledText)
196
+
197
+ view.setSelection(6, 11)
198
+ const selectedText = view.getSelectedText()
199
+ expect(selectedText).toBe("World")
200
+ })
201
+
202
+ it("should return selected text with newlines", () => {
203
+ const styledText = stringToStyledText("Line 1\nLine 2\nLine 3")
204
+ buffer.setStyledText(styledText)
205
+
206
+ // Rope offsets: "Line 1" (0-5) + newline (6) + "Line 2" (7-12) + newline (13) + "Line 3" (14-19)
207
+ // Selection [0, 9) = "Line 1" (0-5) + newline (6) + "Li" (7-8) = 9 chars
208
+ view.setSelection(0, 9)
209
+ const selectedText = view.getSelectedText()
210
+ expect(selectedText).toBe("Line 1\nLi")
211
+ })
212
+
213
+ it("should handle Unicode characters in selection", () => {
214
+ const styledText = stringToStyledText("Hello 世界 🌟")
215
+ buffer.setStyledText(styledText)
216
+
217
+ view.setSelection(6, 12)
218
+ const selectedText = view.getSelectedText()
219
+ expect(selectedText).toBe("世界 🌟")
220
+ })
221
+
222
+ it("should handle selection reset", () => {
223
+ const styledText = stringToStyledText("Hello World")
224
+ buffer.setStyledText(styledText)
225
+
226
+ view.setSelection(6, 11)
227
+ expect(view.getSelectedText()).toBe("World")
228
+
229
+ view.resetSelection()
230
+ expect(view.getSelectedText()).toBe("")
231
+ })
232
+ })
233
+
234
+ describe("selection state", () => {
235
+ it("should track selection state", () => {
236
+ const styledText = stringToStyledText("Hello World")
237
+ buffer.setStyledText(styledText)
238
+
239
+ expect(view.hasSelection()).toBe(false)
240
+
241
+ view.setSelection(0, 5)
242
+ expect(view.hasSelection()).toBe(true)
243
+
244
+ const selection = view.getSelection()
245
+ expect(selection).toEqual({ start: 0, end: 5 })
246
+
247
+ view.resetSelection()
248
+ expect(view.hasSelection()).toBe(false)
249
+ })
250
+
251
+ it("should update selection end position", () => {
252
+ const styledText = stringToStyledText("Hello World")
253
+ buffer.setStyledText(styledText)
254
+
255
+ view.setSelection(0, 5)
256
+ expect(view.getSelectedText()).toBe("Hello")
257
+
258
+ view.updateSelection(11)
259
+ expect(view.getSelectedText()).toBe("Hello World")
260
+
261
+ const selection = view.getSelection()
262
+ expect(selection).toEqual({ start: 0, end: 11 })
263
+ })
264
+
265
+ it("should shrink selection with updateSelection", () => {
266
+ const styledText = stringToStyledText("Hello World")
267
+ buffer.setStyledText(styledText)
268
+
269
+ view.setSelection(0, 11)
270
+ expect(view.getSelectedText()).toBe("Hello World")
271
+
272
+ view.updateSelection(5)
273
+ expect(view.getSelectedText()).toBe("Hello")
274
+
275
+ const selection = view.getSelection()
276
+ expect(selection).toEqual({ start: 0, end: 5 })
277
+ })
278
+
279
+ it("should do nothing when updateSelection called with no selection", () => {
280
+ const styledText = stringToStyledText("Hello World")
281
+ buffer.setStyledText(styledText)
282
+
283
+ expect(view.hasSelection()).toBe(false)
284
+
285
+ view.updateSelection(5)
286
+ expect(view.hasSelection()).toBe(false)
287
+ expect(view.getSelectedText()).toBe("")
288
+ })
289
+
290
+ it("should update local selection focus position", () => {
291
+ const styledText = stringToStyledText("Hello World")
292
+ buffer.setStyledText(styledText)
293
+
294
+ const changed1 = view.setLocalSelection(0, 0, 5, 0)
295
+ expect(changed1).toBe(true)
296
+ expect(view.getSelectedText()).toBe("Hello")
297
+
298
+ const changed2 = view.updateLocalSelection(0, 0, 11, 0)
299
+ expect(changed2).toBe(true)
300
+ expect(view.getSelectedText()).toBe("Hello World")
301
+ })
302
+
303
+ it("should update local selection across lines", () => {
304
+ const styledText = stringToStyledText("Line 1\nLine 2\nLine 3")
305
+ buffer.setStyledText(styledText)
306
+
307
+ view.setLocalSelection(2, 0, 2, 0)
308
+
309
+ const changed = view.updateLocalSelection(2, 0, 4, 1)
310
+ expect(changed).toBe(true)
311
+
312
+ const selectedText = view.getSelectedText()
313
+ expect(selectedText).toContain("ne 1")
314
+ expect(selectedText).toContain("Line")
315
+ })
316
+
317
+ it("should fallback to setLocalSelection when updateLocalSelection called with no existing anchor", () => {
318
+ const styledText = stringToStyledText("Hello World")
319
+ buffer.setStyledText(styledText)
320
+
321
+ const changed = view.updateLocalSelection(0, 0, 5, 0)
322
+ expect(changed).toBe(true)
323
+ expect(view.hasSelection()).toBe(true)
324
+ expect(view.getSelectedText()).toBe("Hello")
325
+ })
326
+
327
+ it("should preserve anchor when updating local selection", () => {
328
+ const styledText = stringToStyledText("Hello World")
329
+ buffer.setStyledText(styledText)
330
+
331
+ view.setLocalSelection(0, 0, 5, 0)
332
+ expect(view.getSelectedText()).toBe("Hello")
333
+
334
+ view.updateLocalSelection(0, 0, 6, 0)
335
+ expect(view.getSelectedText()).toBe("Hello ")
336
+
337
+ view.updateLocalSelection(0, 0, 11, 0)
338
+ expect(view.getSelectedText()).toBe("Hello World")
339
+
340
+ view.updateLocalSelection(0, 0, 3, 0)
341
+ expect(view.getSelectedText()).toBe("Hel")
342
+ })
343
+
344
+ it("should handle backward selection with updateLocalSelection", () => {
345
+ const styledText = stringToStyledText("Hello World")
346
+ buffer.setStyledText(styledText)
347
+
348
+ view.setLocalSelection(11, 0, 11, 0)
349
+
350
+ const changed = view.updateLocalSelection(11, 0, 6, 0)
351
+ expect(changed).toBe(true)
352
+ expect(view.getSelectedText()).toBe("World")
353
+ })
354
+ })
355
+
356
+ describe("getPlainText", () => {
357
+ it("should return empty string for empty buffer", () => {
358
+ const emptyText = stringToStyledText("")
359
+ buffer.setStyledText(emptyText)
360
+
361
+ const plainText = view.getPlainText()
362
+ expect(plainText).toBe("")
363
+ })
364
+
365
+ it("should return plain text without styling", () => {
366
+ const styledText = stringToStyledText("Hello World")
367
+ buffer.setStyledText(styledText)
368
+
369
+ const plainText = view.getPlainText()
370
+ expect(plainText).toBe("Hello World")
371
+ })
372
+
373
+ it("should handle text with newlines", () => {
374
+ const styledText = stringToStyledText("Line 1\nLine 2\nLine 3")
375
+ buffer.setStyledText(styledText)
376
+
377
+ const plainText = view.getPlainText()
378
+ expect(plainText).toBe("Line 1\nLine 2\nLine 3")
379
+ })
380
+ })
381
+
382
+ describe("undo/redo with line info", () => {
383
+ it("should update lineInfo correctly after undo", () => {
384
+ // This test verifies that marker cache is invalidated after undo
385
+ const styledText = stringToStyledText("Line 1 content\nLine 2")
386
+ buffer.setStyledText(styledText)
387
+
388
+ const lineInfoBefore = view.lineInfo
389
+ expect(lineInfoBefore.lineStartCols).toEqual([0, 15])
390
+ expect(lineInfoBefore.lineWidthCols[0]).toBe(14)
391
+ expect(lineInfoBefore.lineWidthCols[1]).toBe(6)
392
+
393
+ // Modify the buffer (this would normally go through EditBuffer with undo tracking)
394
+ // For this test, we'll just verify the view updates correctly
395
+ const modifiedText = stringToStyledText("Line 1 \nLine 2")
396
+ buffer.setStyledText(modifiedText)
397
+
398
+ const lineInfoAfterModify = view.lineInfo
399
+ expect(lineInfoAfterModify.lineStartCols).toEqual([0, 8])
400
+ expect(lineInfoAfterModify.lineWidthCols[0]).toBe(7)
401
+
402
+ // Restore original (simulating undo)
403
+ buffer.setStyledText(styledText)
404
+
405
+ const lineInfoAfterRestore = view.lineInfo
406
+ expect(lineInfoAfterRestore.lineStartCols).toEqual([0, 15])
407
+ expect(lineInfoAfterRestore.lineWidthCols[0]).toBe(14)
408
+ })
409
+
410
+ it("should handle line info correctly through multiple undo/redo cycles", () => {
411
+ const text1 = stringToStyledText("Short\nLine 2")
412
+ const text2 = stringToStyledText("This is a longer line\nLine 2")
413
+ const text3 = stringToStyledText("X\nLine 2")
414
+
415
+ buffer.setStyledText(text1)
416
+ const info1 = view.lineInfo
417
+ expect(info1.lineWidthCols[0]).toBe(5)
418
+
419
+ buffer.setStyledText(text2)
420
+ const info2 = view.lineInfo
421
+ expect(info2.lineWidthCols[0]).toBe(21)
422
+
423
+ buffer.setStyledText(text3)
424
+ const info3 = view.lineInfo
425
+ expect(info3.lineWidthCols[0]).toBe(1)
426
+
427
+ // Go back to text2 (simulating undo)
428
+ buffer.setStyledText(text2)
429
+ const info2Again = view.lineInfo
430
+ expect(info2Again.lineWidthCols[0]).toBe(21)
431
+
432
+ // Go back to text1 (simulating another undo)
433
+ buffer.setStyledText(text1)
434
+ const info1Again = view.lineInfo
435
+ expect(info1Again.lineWidthCols[0]).toBe(5)
436
+
437
+ // Forward to text2 (simulating redo)
438
+ buffer.setStyledText(text2)
439
+ const info2Redo = view.lineInfo
440
+ expect(info2Redo.lineWidthCols[0]).toBe(21)
441
+ })
442
+
443
+ it("should correctly track line starts after undo with multiline text", () => {
444
+ const original = stringToStyledText("Line 1 content\nLine 2 content\nLine 3")
445
+ const modified = stringToStyledText("Line 1 \nLine 2 content\nLine 3")
446
+
447
+ buffer.setStyledText(original)
448
+ const originalInfo = view.lineInfo
449
+ expect(originalInfo.lineStartCols).toEqual([0, 15, 30])
450
+
451
+ buffer.setStyledText(modified)
452
+ const modifiedInfo = view.lineInfo
453
+ expect(modifiedInfo.lineStartCols).toEqual([0, 8, 23])
454
+
455
+ // Restore (undo)
456
+ buffer.setStyledText(original)
457
+ const restoredInfo = view.lineInfo
458
+ expect(restoredInfo.lineStartCols).toEqual([0, 15, 30])
459
+ })
460
+ })
461
+
462
+ describe("wrapped view offset stability", () => {
463
+ it("should return line info for empty buffer", () => {
464
+ const emptyText = stringToStyledText("")
465
+ buffer.setStyledText(emptyText)
466
+
467
+ const lineInfo = view.lineInfo
468
+ expect(lineInfo.lineStartCols).toEqual([0])
469
+ expect(lineInfo.lineWidthCols).toEqual([0])
470
+ })
471
+
472
+ it("should maintain stable char offsets with wide characters", () => {
473
+ const text = "A世B界C" // A(1) 世(2) B(1) 界(2) C(1) = 7 total width
474
+ const styledText = stringToStyledText(text)
475
+ buffer.setStyledText(styledText)
476
+
477
+ view.setWrapMode("char")
478
+ view.setWrapWidth(4)
479
+
480
+ const lineInfo = view.lineInfo
481
+ // Should wrap at display width boundaries
482
+ expect(lineInfo.lineStartCols[0]).toBe(0)
483
+ expect(lineInfo.lineStartCols.length).toBeGreaterThan(1)
484
+
485
+ // Each line should respect wrap width in display columns
486
+ for (const width of lineInfo.lineWidthCols) {
487
+ expect(width).toBeLessThanOrEqual(4)
488
+ }
489
+ })
490
+
491
+ it("should maintain stable selection with wrapped wide characters", () => {
492
+ const text = "世界世界世界" // 6 CJK characters = 12 display width
493
+ const styledText = stringToStyledText(text)
494
+ buffer.setStyledText(styledText)
495
+
496
+ view.setWrapMode("char")
497
+ view.setWrapWidth(6)
498
+
499
+ // Select first 3 CJK characters (6 display width)
500
+ view.setSelection(0, 6)
501
+ const selected = view.getSelectedText()
502
+ expect(selected).toBe("世界世")
503
+ })
504
+
505
+ it("should handle tabs correctly in wrapped view", () => {
506
+ const text = "A\tB\tC"
507
+ const styledText = stringToStyledText(text)
508
+ buffer.setStyledText(styledText)
509
+
510
+ view.setWrapMode("char")
511
+ view.setWrapWidth(10)
512
+
513
+ const lineInfo = view.lineInfo
514
+ // Tabs expand to display width, offsets should account for this
515
+ expect(lineInfo.lineStartCols.length).toBeGreaterThanOrEqual(1)
516
+ })
517
+
518
+ it("should handle emoji in wrapped view", () => {
519
+ const text = "🌟🌟🌟🌟🌟" // 5 emoji = 10 display width (assuming 2 each)
520
+ const styledText = stringToStyledText(text)
521
+ buffer.setStyledText(styledText)
522
+
523
+ view.setWrapMode("char")
524
+ view.setWrapWidth(6)
525
+
526
+ const lineInfo = view.lineInfo
527
+ expect(lineInfo.lineStartCols.length).toBeGreaterThan(1)
528
+
529
+ // Each wrapped line should respect display width limits
530
+ for (const width of lineInfo.lineWidthCols) {
531
+ expect(width).toBeLessThanOrEqual(6)
532
+ }
533
+ })
534
+
535
+ it("should maintain selection across wrapped lines", () => {
536
+ const text = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
537
+ const styledText = stringToStyledText(text)
538
+ buffer.setStyledText(styledText)
539
+
540
+ view.setWrapMode("char")
541
+ view.setWrapWidth(10)
542
+
543
+ // Select across wrap boundary: chars 8-12 (IJK)
544
+ view.setSelection(8, 13)
545
+ const selected = view.getSelectedText()
546
+ expect(selected).toBe("IJKLM")
547
+ })
548
+ })
549
+
550
+ describe("measureForDimensions", () => {
551
+ it("should measure without modifying cache", () => {
552
+ const styledText = stringToStyledText("ABCDEFGHIJKLMNOPQRST")
553
+ buffer.setStyledText(styledText)
554
+
555
+ view.setWrapMode("char")
556
+ view.setWrapWidth(100) // Large width
557
+
558
+ // Measure with different width
559
+ const measureResult = view.measureForDimensions(10, 10)
560
+ expect(measureResult).not.toBeNull()
561
+ expect(measureResult!.lineCount).toBe(2)
562
+ expect(measureResult!.widthColsMax).toBe(10)
563
+
564
+ // Verify cache wasn't modified (should be 1 line with wrap width 100)
565
+ const lineInfo = view.lineInfo
566
+ expect(lineInfo.lineStartCols.length).toBe(1)
567
+ })
568
+
569
+ it("should measure char wrap correctly", () => {
570
+ const styledText = stringToStyledText("ABCDEFGHIJKLMNOPQRST")
571
+ buffer.setStyledText(styledText)
572
+
573
+ view.setWrapMode("char")
574
+
575
+ // Test different widths
576
+ const result1 = view.measureForDimensions(10, 10)
577
+ expect(result1).not.toBeNull()
578
+ expect(result1!.lineCount).toBe(2)
579
+ expect(result1!.widthColsMax).toBe(10)
580
+
581
+ const result2 = view.measureForDimensions(5, 10)
582
+ expect(result2).not.toBeNull()
583
+ expect(result2!.lineCount).toBe(4)
584
+ expect(result2!.widthColsMax).toBe(5)
585
+
586
+ const result3 = view.measureForDimensions(20, 10)
587
+ expect(result3).not.toBeNull()
588
+ expect(result3!.lineCount).toBe(1)
589
+ expect(result3!.widthColsMax).toBe(20)
590
+ })
591
+
592
+ it("should handle no wrap mode", () => {
593
+ const styledText = stringToStyledText("Hello\nWorld\nTest")
594
+ buffer.setStyledText(styledText)
595
+
596
+ view.setWrapMode("none")
597
+
598
+ const result = view.measureForDimensions(3, 10)
599
+ expect(result).not.toBeNull()
600
+ expect(result!.lineCount).toBe(3)
601
+ expect(result!.widthColsMax).toBeGreaterThanOrEqual(4)
602
+ })
603
+
604
+ it("should handle word wrap", () => {
605
+ const styledText = stringToStyledText("Hello wonderful world")
606
+ buffer.setStyledText(styledText)
607
+
608
+ view.setWrapMode("word")
609
+
610
+ const result = view.measureForDimensions(10, 10)
611
+ expect(result).not.toBeNull()
612
+ expect(result!.lineCount).toBeGreaterThanOrEqual(2)
613
+ expect(result!.widthColsMax).toBeLessThanOrEqual(10)
614
+ })
615
+
616
+ it("should handle empty buffer", () => {
617
+ const styledText = stringToStyledText("")
618
+ buffer.setStyledText(styledText)
619
+
620
+ view.setWrapMode("char")
621
+
622
+ const result = view.measureForDimensions(10, 10)
623
+ expect(result).not.toBeNull()
624
+ expect(result!.lineCount).toBe(1)
625
+ expect(result!.widthColsMax).toBe(0)
626
+ })
627
+
628
+ it("should handle multiple lines with wrapping", () => {
629
+ const styledText = stringToStyledText("Short\nAVeryLongLineHere\nMedium")
630
+ buffer.setStyledText(styledText)
631
+
632
+ view.setWrapMode("char")
633
+
634
+ const result = view.measureForDimensions(10, 10)
635
+ expect(result).not.toBeNull()
636
+ // "Short" (1), "AVeryLongLineHere" (2), "Medium" (1) = 4 lines
637
+ expect(result!.lineCount).toBe(4)
638
+ expect(result!.widthColsMax).toBe(10)
639
+ })
640
+
641
+ it("should cache measure results for same width", () => {
642
+ const styledText = stringToStyledText("ABCDEFGHIJKLMNOPQRST")
643
+ buffer.setStyledText(styledText)
644
+
645
+ view.setWrapMode("char")
646
+
647
+ // First call - cache miss
648
+ const result1 = view.measureForDimensions(10, 10)
649
+ expect(result1).not.toBeNull()
650
+ expect(result1!.lineCount).toBe(2)
651
+
652
+ // Second call with same width - should return cached result
653
+ const result2 = view.measureForDimensions(10, 10)
654
+ expect(result2).not.toBeNull()
655
+ expect(result2!.lineCount).toBe(2)
656
+ expect(result2!.widthColsMax).toBe(result1!.widthColsMax)
657
+ })
658
+
659
+ it("should invalidate cache when content changes", () => {
660
+ const styledText1 = stringToStyledText("ABCDEFGHIJ")
661
+ buffer.setStyledText(styledText1)
662
+
663
+ view.setWrapMode("char")
664
+
665
+ // Measure with width 5 - should be 2 lines
666
+ const result1 = view.measureForDimensions(5, 10)
667
+ expect(result1!.lineCount).toBe(2)
668
+
669
+ // Change content to be longer
670
+ const styledText2 = stringToStyledText("ABCDEFGHIJKLMNOPQRST")
671
+ buffer.setStyledText(styledText2)
672
+
673
+ // Same width should now return different result
674
+ const result2 = view.measureForDimensions(5, 10)
675
+ expect(result2!.lineCount).toBe(4)
676
+ })
677
+
678
+ it("should invalidate cache when wrap mode changes", () => {
679
+ const styledText = stringToStyledText("Hello world test string here")
680
+ buffer.setStyledText(styledText)
681
+
682
+ view.setWrapMode("word")
683
+ const resultWord = view.measureForDimensions(10, 10)
684
+
685
+ view.setWrapMode("char")
686
+ const resultChar = view.measureForDimensions(10, 10)
687
+
688
+ // Word and char wrap should produce different results
689
+ expect(resultWord!.lineCount).not.toBe(resultChar!.lineCount)
690
+ })
691
+
692
+ it("should handle width 0 for intrinsic measurement", () => {
693
+ const styledText = stringToStyledText("Hello World")
694
+ buffer.setStyledText(styledText)
695
+
696
+ view.setWrapMode("word")
697
+
698
+ // Width 0 means get intrinsic width (no wrapping)
699
+ const result = view.measureForDimensions(0, 10)
700
+ expect(result).not.toBeNull()
701
+ expect(result!.lineCount).toBe(1)
702
+ expect(result!.widthColsMax).toBe(11) // "Hello World" = 11 chars
703
+ })
704
+ })
705
+ })