@fairyhunter13/opentui-core 0.1.88 → 0.1.90

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 (570) 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 +141 -0
  7. package/docs/env-vars.md +140 -0
  8. package/docs/getting-started.md +353 -0
  9. package/docs/renderables-vs-constructs.md +159 -0
  10. package/docs/tree-sitter.md +311 -0
  11. package/package.json +61 -52
  12. package/scripts/build.ts +400 -0
  13. package/scripts/publish.ts +60 -0
  14. package/src/3d/SpriteResourceManager.ts +286 -0
  15. package/src/3d/SpriteUtils.ts +71 -0
  16. package/src/3d/TextureUtils.ts +196 -0
  17. package/src/3d/ThreeRenderable.ts +197 -0
  18. package/src/3d/WGPURenderer.ts +294 -0
  19. package/src/3d/animation/ExplodingSpriteEffect.ts +513 -0
  20. package/src/3d/animation/PhysicsExplodingSpriteEffect.ts +429 -0
  21. package/src/3d/animation/SpriteAnimator.ts +633 -0
  22. package/src/3d/animation/SpriteParticleGenerator.ts +435 -0
  23. package/src/3d/canvas.ts +464 -0
  24. package/src/3d/index.ts +12 -0
  25. package/src/3d/physics/PlanckPhysicsAdapter.ts +72 -0
  26. package/src/3d/physics/RapierPhysicsAdapter.ts +66 -0
  27. package/src/3d/physics/physics-interface.ts +31 -0
  28. package/src/3d/shaders/supersampling.wgsl +201 -0
  29. package/src/3d.ts +3 -0
  30. package/src/NativeSpanFeed.ts +300 -0
  31. package/src/Renderable.ts +1698 -0
  32. package/src/__snapshots__/buffer.test.ts.snap +28 -0
  33. package/src/animation/Timeline.test.ts +2709 -0
  34. package/src/animation/Timeline.ts +598 -0
  35. package/src/ansi.ts +18 -0
  36. package/src/benchmark/latest-all-bench-run.json +707 -0
  37. package/src/benchmark/latest-async-bench-run.json +336 -0
  38. package/src/benchmark/latest-default-bench-run.json +657 -0
  39. package/src/benchmark/latest-large-bench-run.json +707 -0
  40. package/src/benchmark/latest-quick-bench-run.json +207 -0
  41. package/src/benchmark/markdown-benchmark.ts +1804 -0
  42. package/src/benchmark/native-span-feed-async-benchmark.ts +355 -0
  43. package/src/benchmark/native-span-feed-benchmark.md +56 -0
  44. package/src/benchmark/native-span-feed-benchmark.ts +596 -0
  45. package/src/benchmark/native-span-feed-compare.ts +280 -0
  46. package/src/benchmark/renderer-benchmark.ts +754 -0
  47. package/src/benchmark/text-table-benchmark.ts +947 -0
  48. package/src/buffer.test.ts +291 -0
  49. package/src/buffer.ts +519 -0
  50. package/src/console.test.ts +612 -0
  51. package/src/console.ts +1255 -0
  52. package/src/edit-buffer.test.ts +1769 -0
  53. package/src/edit-buffer.ts +411 -0
  54. package/src/editor-view.test.ts +1032 -0
  55. package/src/editor-view.ts +284 -0
  56. package/src/examples/ascii-font-selection-demo.ts +245 -0
  57. package/src/examples/assets/Water_2_M_Normal.jpg +0 -0
  58. package/src/examples/assets/concrete.png +0 -0
  59. package/src/examples/assets/crate.png +0 -0
  60. package/src/examples/assets/crate_emissive.png +0 -0
  61. package/src/examples/assets/forrest_background.png +0 -0
  62. package/src/examples/assets/hast-example.json +1018 -0
  63. package/src/examples/assets/heart.png +0 -0
  64. package/src/examples/assets/main_char_heavy_attack.png +0 -0
  65. package/src/examples/assets/main_char_idle.png +0 -0
  66. package/src/examples/assets/main_char_jump_end.png +0 -0
  67. package/src/examples/assets/main_char_jump_landing.png +0 -0
  68. package/src/examples/assets/main_char_jump_start.png +0 -0
  69. package/src/examples/assets/main_char_run_loop.png +0 -0
  70. package/src/examples/assets/roughness_map.jpg +0 -0
  71. package/src/examples/build.ts +115 -0
  72. package/src/examples/code-demo.ts +584 -0
  73. package/src/examples/console-demo.ts +358 -0
  74. package/src/examples/core-plugin-slots-demo.ts +759 -0
  75. package/src/examples/diff-demo.ts +699 -0
  76. package/src/examples/draggable-three-demo.ts +259 -0
  77. package/src/examples/editor-demo.ts +322 -0
  78. package/src/examples/extmarks-demo.ts +204 -0
  79. package/src/examples/focus-restore-demo.ts +310 -0
  80. package/src/examples/fonts.ts +245 -0
  81. package/src/examples/fractal-shader-demo.ts +268 -0
  82. package/src/examples/framebuffer-demo.ts +674 -0
  83. package/src/examples/full-unicode-demo.ts +181 -0
  84. package/src/examples/golden-star-demo.ts +933 -0
  85. package/src/examples/grayscale-buffer-demo.ts +249 -0
  86. package/src/examples/hast-syntax-highlighting-demo.ts +129 -0
  87. package/src/examples/index.ts +925 -0
  88. package/src/examples/input-demo.ts +377 -0
  89. package/src/examples/input-select-layout-demo.ts +425 -0
  90. package/src/examples/install.sh +143 -0
  91. package/src/examples/keypress-debug-demo.ts +452 -0
  92. package/src/examples/lib/HexList.ts +122 -0
  93. package/src/examples/lib/PaletteGrid.ts +125 -0
  94. package/src/examples/lib/standalone-keys.ts +25 -0
  95. package/src/examples/lib/tab-controller.ts +243 -0
  96. package/src/examples/lights-phong-demo.ts +290 -0
  97. package/src/examples/link-demo.ts +220 -0
  98. package/src/examples/live-state-demo.ts +480 -0
  99. package/src/examples/markdown-demo.ts +620 -0
  100. package/src/examples/mouse-interaction-demo.ts +428 -0
  101. package/src/examples/nested-zindex-demo.ts +357 -0
  102. package/src/examples/opacity-example.ts +235 -0
  103. package/src/examples/opentui-demo.ts +1057 -0
  104. package/src/examples/physx-planck-2d-demo.ts +507 -0
  105. package/src/examples/physx-rapier-2d-demo.ts +526 -0
  106. package/src/examples/relative-positioning-demo.ts +323 -0
  107. package/src/examples/scroll-example.ts +214 -0
  108. package/src/examples/scrollbox-mouse-test.ts +112 -0
  109. package/src/examples/scrollbox-overlay-hit-test.ts +206 -0
  110. package/src/examples/select-demo.ts +237 -0
  111. package/src/examples/shader-cube-demo.ts +772 -0
  112. package/src/examples/simple-layout-example.ts +591 -0
  113. package/src/examples/slider-demo.ts +617 -0
  114. package/src/examples/split-mode-demo.ts +445 -0
  115. package/src/examples/sprite-animation-demo.ts +443 -0
  116. package/src/examples/sprite-particle-generator-demo.ts +486 -0
  117. package/src/examples/static-sprite-demo.ts +193 -0
  118. package/src/examples/sticky-scroll-example.ts +308 -0
  119. package/src/examples/styled-text-demo.ts +282 -0
  120. package/src/examples/tab-select-demo.ts +219 -0
  121. package/src/examples/terminal-title.ts +29 -0
  122. package/src/examples/terminal.ts +305 -0
  123. package/src/examples/text-node-demo.ts +416 -0
  124. package/src/examples/text-selection-demo.ts +377 -0
  125. package/src/examples/text-table-demo.ts +503 -0
  126. package/src/examples/text-truncation-demo.ts +481 -0
  127. package/src/examples/text-wrap.ts +757 -0
  128. package/src/examples/texture-loading-demo.ts +259 -0
  129. package/src/examples/timeline-example.ts +670 -0
  130. package/src/examples/transparency-demo.ts +241 -0
  131. package/src/examples/vnode-composition-demo.ts +404 -0
  132. package/src/index.ts +22 -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 +168 -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 +31 -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 +280 -0
  168. package/src/lib/keymapping.ts +87 -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 +1676 -0
  187. package/src/lib/stdin-parser.ts +1248 -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 +331 -0
  195. package/src/lib/tree-sitter/assets.d.ts +9 -0
  196. package/src/lib/tree-sitter/cache.test.ts +270 -0
  197. package/src/lib/tree-sitter/client.test.ts +1061 -0
  198. package/src/lib/tree-sitter/client.ts +615 -0
  199. package/src/lib/tree-sitter/default-parsers.ts +80 -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 +1001 -0
  203. package/src/lib/tree-sitter/parsers-config.ts +75 -0
  204. package/src/lib/tree-sitter/resolve-ft.ts +62 -0
  205. package/src/lib/tree-sitter/types.ts +81 -0
  206. package/src/lib/tree-sitter-styled-text.test.ts +1253 -0
  207. package/src/lib/tree-sitter-styled-text.ts +306 -0
  208. package/src/lib/validate-dir-name.ts +55 -0
  209. package/src/lib/yoga.options.test.ts +628 -0
  210. package/src/lib/yoga.options.ts +346 -0
  211. package/src/plugins/core-slot.ts +579 -0
  212. package/src/plugins/registry.ts +377 -0
  213. package/src/plugins/types.ts +46 -0
  214. package/src/post/filters.ts +888 -0
  215. package/src/renderables/ASCIIFont.ts +219 -0
  216. package/src/renderables/Box.test.ts +160 -0
  217. package/src/renderables/Box.ts +295 -0
  218. package/src/renderables/Code.test.ts +2062 -0
  219. package/src/renderables/Code.ts +357 -0
  220. package/src/renderables/Diff.regression.test.ts +226 -0
  221. package/src/renderables/Diff.test.ts +3027 -0
  222. package/src/renderables/Diff.ts +1209 -0
  223. package/src/renderables/EditBufferRenderable.ts +764 -0
  224. package/src/renderables/FrameBuffer.ts +47 -0
  225. package/src/renderables/Input.test.ts +1228 -0
  226. package/src/renderables/Input.ts +245 -0
  227. package/src/renderables/LineNumberRenderable.ts +675 -0
  228. package/src/renderables/Markdown.ts +1106 -0
  229. package/src/renderables/ScrollBar.ts +422 -0
  230. package/src/renderables/ScrollBox.ts +883 -0
  231. package/src/renderables/Select.test.ts +1010 -0
  232. package/src/renderables/Select.ts +523 -0
  233. package/src/renderables/Slider.test.ts +456 -0
  234. package/src/renderables/Slider.ts +347 -0
  235. package/src/renderables/TabSelect.test.ts +197 -0
  236. package/src/renderables/TabSelect.ts +455 -0
  237. package/src/renderables/Text.selection-buffer.test.ts +123 -0
  238. package/src/renderables/Text.test.ts +2660 -0
  239. package/src/renderables/Text.ts +147 -0
  240. package/src/renderables/TextBufferRenderable.ts +518 -0
  241. package/src/renderables/TextNode.test.ts +1058 -0
  242. package/src/renderables/TextNode.ts +325 -0
  243. package/src/renderables/TextTable.test.ts +1421 -0
  244. package/src/renderables/TextTable.ts +1344 -0
  245. package/src/renderables/Textarea.ts +732 -0
  246. package/src/renderables/TimeToFirstDraw.ts +89 -0
  247. package/src/renderables/__snapshots__/Code.test.ts.snap +13 -0
  248. package/src/renderables/__snapshots__/Diff.test.ts.snap +785 -0
  249. package/src/renderables/__snapshots__/Text.test.ts.snap +421 -0
  250. package/src/renderables/__snapshots__/TextTable.test.ts.snap +215 -0
  251. package/src/renderables/__tests__/LineNumberRenderable.scrollbox-simple.test.ts +144 -0
  252. package/src/renderables/__tests__/LineNumberRenderable.scrollbox.test.ts +816 -0
  253. package/src/renderables/__tests__/LineNumberRenderable.test.ts +1787 -0
  254. package/src/renderables/__tests__/LineNumberRenderable.wrapping.test.ts +85 -0
  255. package/src/renderables/__tests__/Markdown.test.ts +2287 -0
  256. package/src/renderables/__tests__/MultiRenderable.selection.test.ts +87 -0
  257. package/src/renderables/__tests__/Textarea.buffer.test.ts +682 -0
  258. package/src/renderables/__tests__/Textarea.destroyed-events.test.ts +675 -0
  259. package/src/renderables/__tests__/Textarea.editing.test.ts +2041 -0
  260. package/src/renderables/__tests__/Textarea.error-handling.test.ts +35 -0
  261. package/src/renderables/__tests__/Textarea.events.test.ts +738 -0
  262. package/src/renderables/__tests__/Textarea.highlights.test.ts +590 -0
  263. package/src/renderables/__tests__/Textarea.keybinding.test.ts +3149 -0
  264. package/src/renderables/__tests__/Textarea.paste.test.ts +357 -0
  265. package/src/renderables/__tests__/Textarea.rendering.test.ts +1864 -0
  266. package/src/renderables/__tests__/Textarea.scroll.test.ts +733 -0
  267. package/src/renderables/__tests__/Textarea.selection.test.ts +1590 -0
  268. package/src/renderables/__tests__/Textarea.stress.test.ts +670 -0
  269. package/src/renderables/__tests__/Textarea.undo-redo.test.ts +383 -0
  270. package/src/renderables/__tests__/Textarea.visual-lines.test.ts +310 -0
  271. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.code.test.ts.snap +221 -0
  272. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox-simple.test.ts.snap +89 -0
  273. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox.test.ts.snap +457 -0
  274. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.test.ts.snap +158 -0
  275. package/src/renderables/__tests__/__snapshots__/Textarea.rendering.test.ts.snap +387 -0
  276. package/src/renderables/__tests__/markdown-parser.test.ts +217 -0
  277. package/src/renderables/__tests__/renderable-test-utils.ts +60 -0
  278. package/src/renderables/composition/README.md +8 -0
  279. package/src/renderables/composition/VRenderable.ts +32 -0
  280. package/src/renderables/composition/constructs.ts +127 -0
  281. package/src/renderables/composition/vnode.ts +289 -0
  282. package/src/renderables/index.ts +22 -0
  283. package/src/renderables/markdown-parser.ts +66 -0
  284. package/src/renderer.ts +2363 -0
  285. package/src/runtime-plugin-support.ts +39 -0
  286. package/src/runtime-plugin.ts +144 -0
  287. package/src/syntax-style.test.ts +841 -0
  288. package/src/syntax-style.ts +264 -0
  289. package/src/testing/README.md +210 -0
  290. package/src/testing/capture-spans.test.ts +194 -0
  291. package/src/testing/integration.test.ts +276 -0
  292. package/src/testing/manual-clock.ts +106 -0
  293. package/src/testing/mock-keys.test.ts +1356 -0
  294. package/src/testing/mock-keys.ts +449 -0
  295. package/src/testing/mock-mouse.test.ts +218 -0
  296. package/src/testing/mock-mouse.ts +247 -0
  297. package/src/testing/mock-tree-sitter-client.ts +73 -0
  298. package/src/testing/spy.ts +13 -0
  299. package/src/testing/test-recorder.test.ts +415 -0
  300. package/src/testing/test-recorder.ts +145 -0
  301. package/src/testing/test-renderer.ts +116 -0
  302. package/src/testing.ts +7 -0
  303. package/src/tests/__snapshots__/absolute-positioning.snapshot.test.ts.snap +481 -0
  304. package/src/tests/__snapshots__/renderable.snapshot.test.ts.snap +19 -0
  305. package/src/tests/__snapshots__/scrollbox.test.ts.snap +29 -0
  306. package/src/tests/absolute-positioning.snapshot.test.ts +638 -0
  307. package/src/tests/allocator-stats.test.ts +38 -0
  308. package/src/tests/destroy-during-render.test.ts +200 -0
  309. package/src/tests/hover-cursor.test.ts +98 -0
  310. package/src/tests/native-span-feed-async.test.ts +173 -0
  311. package/src/tests/native-span-feed-close.test.ts +120 -0
  312. package/src/tests/native-span-feed-coverage.test.ts +227 -0
  313. package/src/tests/native-span-feed-edge-cases.test.ts +352 -0
  314. package/src/tests/native-span-feed-use-after-free.test.ts +45 -0
  315. package/src/tests/opacity.test.ts +123 -0
  316. package/src/tests/renderable.snapshot.test.ts +524 -0
  317. package/src/tests/renderable.test.ts +1281 -0
  318. package/src/tests/renderer.console-startup.test.ts +65 -0
  319. package/src/tests/renderer.control.test.ts +364 -0
  320. package/src/tests/renderer.core-slot-binding.test.ts +952 -0
  321. package/src/tests/renderer.cursor.test.ts +26 -0
  322. package/src/tests/renderer.destroy-during-render.test.ts +110 -0
  323. package/src/tests/renderer.focus-restore.test.ts +228 -0
  324. package/src/tests/renderer.focus.test.ts +251 -0
  325. package/src/tests/renderer.idle.test.ts +219 -0
  326. package/src/tests/renderer.input.test.ts +2145 -0
  327. package/src/tests/renderer.kitty-flags.test.ts +195 -0
  328. package/src/tests/renderer.mouse.test.ts +1269 -0
  329. package/src/tests/renderer.palette.test.ts +629 -0
  330. package/src/tests/renderer.selection.test.ts +49 -0
  331. package/src/tests/renderer.slot-registry.test.ts +649 -0
  332. package/src/tests/renderer.useMouse.test.ts +50 -0
  333. package/src/tests/runtime-plugin-support.fixture.ts +11 -0
  334. package/src/tests/runtime-plugin-support.test.ts +28 -0
  335. package/src/tests/runtime-plugin.fixture.ts +40 -0
  336. package/src/tests/runtime-plugin.test.ts +190 -0
  337. package/src/tests/scrollbox-culling-bug.test.ts +114 -0
  338. package/src/tests/scrollbox-hitgrid-resize.test.ts +136 -0
  339. package/src/tests/scrollbox-hitgrid.test.ts +909 -0
  340. package/src/tests/scrollbox.test.ts +1530 -0
  341. package/src/tests/wrap-resize-perf.test.ts +229 -0
  342. package/src/tests/yoga-setters.test.ts +921 -0
  343. package/src/text-buffer-view.test.ts +705 -0
  344. package/src/text-buffer-view.ts +189 -0
  345. package/src/text-buffer.test.ts +347 -0
  346. package/src/text-buffer.ts +250 -0
  347. package/src/types.ts +152 -0
  348. package/src/utils.ts +88 -0
  349. package/src/zig/ansi.zig +268 -0
  350. package/src/zig/bench/README.md +50 -0
  351. package/src/zig/bench/buffer-draw-text-buffer_bench.zig +887 -0
  352. package/src/zig/bench/edit-buffer_bench.zig +476 -0
  353. package/src/zig/bench/native-span-feed_bench.zig +100 -0
  354. package/src/zig/bench/rope-markers_bench.zig +713 -0
  355. package/src/zig/bench/rope_bench.zig +514 -0
  356. package/src/zig/bench/styled-text_bench.zig +470 -0
  357. package/src/zig/bench/text-buffer-coords_bench.zig +362 -0
  358. package/src/zig/bench/text-buffer-view_bench.zig +459 -0
  359. package/src/zig/bench/text-chunk-graphemes_bench.zig +273 -0
  360. package/src/zig/bench/utf8_bench.zig +799 -0
  361. package/src/zig/bench-utils.zig +431 -0
  362. package/src/zig/bench.zig +217 -0
  363. package/src/zig/buffer.zig +2223 -0
  364. package/src/zig/build.zig +289 -0
  365. package/src/zig/build.zig.zon +16 -0
  366. package/src/zig/edit-buffer.zig +825 -0
  367. package/src/zig/editor-view.zig +802 -0
  368. package/src/zig/event-bus.zig +13 -0
  369. package/src/zig/event-emitter.zig +65 -0
  370. package/src/zig/file-logger.zig +92 -0
  371. package/src/zig/grapheme.zig +599 -0
  372. package/src/zig/lib.zig +1834 -0
  373. package/src/zig/link.zig +333 -0
  374. package/src/zig/logger.zig +43 -0
  375. package/src/zig/mem-registry.zig +125 -0
  376. package/src/zig/native-span-feed-bench-lib.zig +7 -0
  377. package/src/zig/native-span-feed.zig +708 -0
  378. package/src/zig/renderer.zig +1386 -0
  379. package/src/zig/rope.zig +1220 -0
  380. package/src/zig/syntax-style.zig +161 -0
  381. package/src/zig/terminal.zig +975 -0
  382. package/src/zig/test.zig +70 -0
  383. package/src/zig/tests/README.md +18 -0
  384. package/src/zig/tests/buffer_test.zig +2526 -0
  385. package/src/zig/tests/edit-buffer-history_test.zig +271 -0
  386. package/src/zig/tests/edit-buffer_test.zig +1689 -0
  387. package/src/zig/tests/editor-view_test.zig +3299 -0
  388. package/src/zig/tests/event-emitter_test.zig +249 -0
  389. package/src/zig/tests/grapheme_test.zig +1304 -0
  390. package/src/zig/tests/link_test.zig +190 -0
  391. package/src/zig/tests/mem-registry_test.zig +473 -0
  392. package/src/zig/tests/memory_leak_regression_test.zig +159 -0
  393. package/src/zig/tests/native-span-feed_test.zig +1264 -0
  394. package/src/zig/tests/renderer_test.zig +1010 -0
  395. package/src/zig/tests/rope-nested_test.zig +712 -0
  396. package/src/zig/tests/rope_fuzz_test.zig +238 -0
  397. package/src/zig/tests/rope_test.zig +2362 -0
  398. package/src/zig/tests/segment-merge.test.zig +148 -0
  399. package/src/zig/tests/syntax-style_test.zig +557 -0
  400. package/src/zig/tests/terminal_test.zig +719 -0
  401. package/src/zig/tests/text-buffer-drawing_test.zig +3237 -0
  402. package/src/zig/tests/text-buffer-highlights_test.zig +666 -0
  403. package/src/zig/tests/text-buffer-iterators_test.zig +776 -0
  404. package/src/zig/tests/text-buffer-segment_test.zig +320 -0
  405. package/src/zig/tests/text-buffer-selection_test.zig +1035 -0
  406. package/src/zig/tests/text-buffer-selection_viewport_test.zig +358 -0
  407. package/src/zig/tests/text-buffer-view_test.zig +3649 -0
  408. package/src/zig/tests/text-buffer_test.zig +2191 -0
  409. package/src/zig/tests/unicode-width-map.zon +3909 -0
  410. package/src/zig/tests/utf8_no_zwj_test.zig +260 -0
  411. package/src/zig/tests/utf8_test.zig +4057 -0
  412. package/src/zig/tests/utf8_wcwidth_cursor_test.zig +267 -0
  413. package/src/zig/tests/utf8_wcwidth_test.zig +357 -0
  414. package/src/zig/tests/word-wrap-editing_test.zig +498 -0
  415. package/src/zig/tests/wrap-cache-perf_test.zig +113 -0
  416. package/src/zig/text-buffer-iterators.zig +499 -0
  417. package/src/zig/text-buffer-segment.zig +404 -0
  418. package/src/zig/text-buffer-view.zig +1371 -0
  419. package/src/zig/text-buffer.zig +1180 -0
  420. package/src/zig/utf8.zig +1948 -0
  421. package/src/zig/utils.zig +9 -0
  422. package/src/zig-structs.ts +261 -0
  423. package/src/zig.ts +3843 -0
  424. package/tsconfig.build.json +22 -0
  425. package/tsconfig.json +28 -0
  426. package/3d/SpriteResourceManager.d.ts +0 -74
  427. package/3d/SpriteUtils.d.ts +0 -13
  428. package/3d/TextureUtils.d.ts +0 -24
  429. package/3d/ThreeRenderable.d.ts +0 -40
  430. package/3d/WGPURenderer.d.ts +0 -61
  431. package/3d/animation/ExplodingSpriteEffect.d.ts +0 -71
  432. package/3d/animation/PhysicsExplodingSpriteEffect.d.ts +0 -76
  433. package/3d/animation/SpriteAnimator.d.ts +0 -124
  434. package/3d/animation/SpriteParticleGenerator.d.ts +0 -62
  435. package/3d/canvas.d.ts +0 -44
  436. package/3d/index.d.ts +0 -12
  437. package/3d/physics/PlanckPhysicsAdapter.d.ts +0 -19
  438. package/3d/physics/RapierPhysicsAdapter.d.ts +0 -19
  439. package/3d/physics/physics-interface.d.ts +0 -27
  440. package/3d.d.ts +0 -2
  441. package/3d.js +0 -34042
  442. package/3d.js.map +0 -155
  443. package/LICENSE +0 -21
  444. package/NativeSpanFeed.d.ts +0 -41
  445. package/Renderable.d.ts +0 -334
  446. package/animation/Timeline.d.ts +0 -126
  447. package/ansi.d.ts +0 -13
  448. package/buffer.d.ts +0 -107
  449. package/console.d.ts +0 -143
  450. package/edit-buffer.d.ts +0 -98
  451. package/editor-view.d.ts +0 -73
  452. package/index-e4hzc2j2.js +0 -113
  453. package/index-e4hzc2j2.js.map +0 -10
  454. package/index-nkrr8a4c.js +0 -18415
  455. package/index-nkrr8a4c.js.map +0 -64
  456. package/index-nyw5p3ep.js +0 -12619
  457. package/index-nyw5p3ep.js.map +0 -43
  458. package/index.d.ts +0 -21
  459. package/index.js +0 -430
  460. package/index.js.map +0 -9
  461. package/lib/KeyHandler.d.ts +0 -61
  462. package/lib/RGBA.d.ts +0 -25
  463. package/lib/ascii.font.d.ts +0 -508
  464. package/lib/border.d.ts +0 -49
  465. package/lib/bunfs.d.ts +0 -7
  466. package/lib/clipboard.d.ts +0 -17
  467. package/lib/clock.d.ts +0 -15
  468. package/lib/data-paths.d.ts +0 -26
  469. package/lib/debounce.d.ts +0 -42
  470. package/lib/detect-links.d.ts +0 -6
  471. package/lib/env.d.ts +0 -42
  472. package/lib/extmarks-history.d.ts +0 -17
  473. package/lib/extmarks.d.ts +0 -89
  474. package/lib/hast-styled-text.d.ts +0 -17
  475. package/lib/index.d.ts +0 -21
  476. package/lib/keymapping.d.ts +0 -25
  477. package/lib/objects-in-viewport.d.ts +0 -24
  478. package/lib/output.capture.d.ts +0 -24
  479. package/lib/parse.keypress-kitty.d.ts +0 -2
  480. package/lib/parse.keypress.d.ts +0 -26
  481. package/lib/parse.mouse.d.ts +0 -30
  482. package/lib/paste.d.ts +0 -7
  483. package/lib/queue.d.ts +0 -15
  484. package/lib/renderable.validations.d.ts +0 -12
  485. package/lib/scroll-acceleration.d.ts +0 -43
  486. package/lib/selection.d.ts +0 -63
  487. package/lib/singleton.d.ts +0 -7
  488. package/lib/stdin-parser.d.ts +0 -76
  489. package/lib/styled-text.d.ts +0 -63
  490. package/lib/terminal-capability-detection.d.ts +0 -30
  491. package/lib/terminal-palette.d.ts +0 -50
  492. package/lib/tree-sitter/assets/update.d.ts +0 -11
  493. package/lib/tree-sitter/client.d.ts +0 -47
  494. package/lib/tree-sitter/default-parsers.d.ts +0 -2
  495. package/lib/tree-sitter/download-utils.d.ts +0 -21
  496. package/lib/tree-sitter/index.d.ts +0 -8
  497. package/lib/tree-sitter/parser.worker.d.ts +0 -1
  498. package/lib/tree-sitter/parsers-config.d.ts +0 -38
  499. package/lib/tree-sitter/resolve-ft.d.ts +0 -2
  500. package/lib/tree-sitter/types.d.ts +0 -81
  501. package/lib/tree-sitter-styled-text.d.ts +0 -14
  502. package/lib/validate-dir-name.d.ts +0 -1
  503. package/lib/yoga.options.d.ts +0 -32
  504. package/parser.worker.js +0 -869
  505. package/parser.worker.js.map +0 -12
  506. package/plugins/core-slot.d.ts +0 -72
  507. package/plugins/registry.d.ts +0 -38
  508. package/plugins/types.d.ts +0 -34
  509. package/post/filters.d.ts +0 -105
  510. package/renderables/ASCIIFont.d.ts +0 -52
  511. package/renderables/Box.d.ts +0 -72
  512. package/renderables/Code.d.ts +0 -78
  513. package/renderables/Diff.d.ts +0 -142
  514. package/renderables/EditBufferRenderable.d.ts +0 -162
  515. package/renderables/FrameBuffer.d.ts +0 -16
  516. package/renderables/Input.d.ts +0 -67
  517. package/renderables/LineNumberRenderable.d.ts +0 -74
  518. package/renderables/Markdown.d.ts +0 -173
  519. package/renderables/ScrollBar.d.ts +0 -77
  520. package/renderables/ScrollBox.d.ts +0 -124
  521. package/renderables/Select.d.ts +0 -115
  522. package/renderables/Slider.d.ts +0 -44
  523. package/renderables/TabSelect.d.ts +0 -96
  524. package/renderables/Text.d.ts +0 -36
  525. package/renderables/TextBufferRenderable.d.ts +0 -105
  526. package/renderables/TextNode.d.ts +0 -91
  527. package/renderables/TextTable.d.ts +0 -140
  528. package/renderables/Textarea.d.ts +0 -114
  529. package/renderables/TimeToFirstDraw.d.ts +0 -24
  530. package/renderables/__tests__/renderable-test-utils.d.ts +0 -12
  531. package/renderables/composition/VRenderable.d.ts +0 -16
  532. package/renderables/composition/constructs.d.ts +0 -35
  533. package/renderables/composition/vnode.d.ts +0 -46
  534. package/renderables/index.d.ts +0 -22
  535. package/renderables/markdown-parser.d.ts +0 -10
  536. package/renderer.d.ts +0 -388
  537. package/runtime-plugin-support.d.ts +0 -3
  538. package/runtime-plugin-support.js +0 -29
  539. package/runtime-plugin-support.js.map +0 -10
  540. package/runtime-plugin.d.ts +0 -11
  541. package/runtime-plugin.js +0 -16
  542. package/runtime-plugin.js.map +0 -9
  543. package/syntax-style.d.ts +0 -54
  544. package/testing/manual-clock.d.ts +0 -16
  545. package/testing/mock-keys.d.ts +0 -81
  546. package/testing/mock-mouse.d.ts +0 -38
  547. package/testing/mock-tree-sitter-client.d.ts +0 -23
  548. package/testing/spy.d.ts +0 -7
  549. package/testing/test-recorder.d.ts +0 -61
  550. package/testing/test-renderer.d.ts +0 -23
  551. package/testing.d.ts +0 -6
  552. package/testing.js +0 -675
  553. package/testing.js.map +0 -15
  554. package/text-buffer-view.d.ts +0 -42
  555. package/text-buffer.d.ts +0 -67
  556. package/types.d.ts +0 -131
  557. package/utils.d.ts +0 -14
  558. package/zig-structs.d.ts +0 -155
  559. package/zig.d.ts +0 -351
  560. /package/{assets → src/lib/tree-sitter/assets}/javascript/highlights.scm +0 -0
  561. /package/{assets → src/lib/tree-sitter/assets}/javascript/tree-sitter-javascript.wasm +0 -0
  562. /package/{assets → src/lib/tree-sitter/assets}/markdown/highlights.scm +0 -0
  563. /package/{assets → src/lib/tree-sitter/assets}/markdown/injections.scm +0 -0
  564. /package/{assets → src/lib/tree-sitter/assets}/markdown/tree-sitter-markdown.wasm +0 -0
  565. /package/{assets → src/lib/tree-sitter/assets}/markdown_inline/highlights.scm +0 -0
  566. /package/{assets → src/lib/tree-sitter/assets}/markdown_inline/tree-sitter-markdown_inline.wasm +0 -0
  567. /package/{assets → src/lib/tree-sitter/assets}/typescript/highlights.scm +0 -0
  568. /package/{assets → src/lib/tree-sitter/assets}/typescript/tree-sitter-typescript.wasm +0 -0
  569. /package/{assets → src/lib/tree-sitter/assets}/zig/highlights.scm +0 -0
  570. /package/{assets → src/lib/tree-sitter/assets}/zig/tree-sitter-zig.wasm +0 -0
@@ -0,0 +1,719 @@
1
+ const std = @import("std");
2
+ const builtin = @import("builtin");
3
+ const testing = std.testing;
4
+ const ansi = @import("../ansi.zig");
5
+ const Terminal = @import("../terminal.zig");
6
+ const utf8 = @import("../utf8.zig");
7
+
8
+ test "parseXtversion - kitty format" {
9
+ var term = Terminal.init(.{});
10
+ const response = "\x1bP>|kitty(0.40.1)\x1b\\";
11
+ term.processCapabilityResponse(response);
12
+
13
+ try testing.expectEqualStrings("kitty", term.getTerminalName());
14
+ try testing.expectEqualStrings("0.40.1", term.getTerminalVersion());
15
+ try testing.expect(term.term_info.from_xtversion);
16
+ try testing.expect(term.caps.osc52);
17
+ }
18
+
19
+ test "parseXtversion - ghostty format" {
20
+ var term = Terminal.init(.{});
21
+ const response = "\x1bP>|ghostty 1.1.3\x1b\\";
22
+ term.processCapabilityResponse(response);
23
+
24
+ try testing.expectEqualStrings("ghostty", term.getTerminalName());
25
+ try testing.expectEqualStrings("1.1.3", term.getTerminalVersion());
26
+ try testing.expect(term.term_info.from_xtversion);
27
+ try testing.expect(term.caps.osc52);
28
+ }
29
+
30
+ test "parseXtversion - tmux format" {
31
+ var term = Terminal.init(.{});
32
+ const response = "\x1bP>|tmux 3.5a\x1b\\";
33
+ term.processCapabilityResponse(response);
34
+
35
+ try testing.expectEqualStrings("tmux", term.getTerminalName());
36
+ try testing.expectEqualStrings("3.5a", term.getTerminalVersion());
37
+ try testing.expect(term.term_info.from_xtversion);
38
+ try testing.expect(term.caps.osc52);
39
+ }
40
+
41
+ test "parseXtversion - with prefix data" {
42
+ var term = Terminal.init(.{});
43
+ const response = "\x1b[1;1R\x1bP>|tmux 3.5a\x1b\\";
44
+ term.processCapabilityResponse(response);
45
+
46
+ try testing.expectEqualStrings("tmux", term.getTerminalName());
47
+ try testing.expectEqualStrings("3.5a", term.getTerminalVersion());
48
+ try testing.expect(term.term_info.from_xtversion);
49
+ }
50
+
51
+ test "parseXtversion - full kitty response" {
52
+ var term = Terminal.init(.{});
53
+ const response = "\x1b[?1016;2$y\x1b[?2027;0$y\x1b[?2031;2$y\x1b[?1004;1$y\x1b[?2026;2$y\x1b[1;2R\x1b[1;3R\x1bP>|kitty(0.40.1)\x1b\\\x1b[?0u\x1b_Gi=1;EINVAL:Zero width/height not allowed\x1b\\\x1b[?62;c";
54
+ term.processCapabilityResponse(response);
55
+
56
+ try testing.expectEqualStrings("kitty", term.getTerminalName());
57
+ try testing.expectEqualStrings("0.40.1", term.getTerminalVersion());
58
+ try testing.expect(term.term_info.from_xtversion);
59
+ try testing.expect(term.caps.kitty_keyboard);
60
+ try testing.expect(term.caps.kitty_graphics);
61
+ try testing.expect(term.caps.osc52);
62
+ }
63
+
64
+ test "parseXtversion - full ghostty response" {
65
+ var term = Terminal.init(.{});
66
+ const response = "\x1b[?1016;1$y\x1b[?2027;1$y\x1b[?2031;2$y\x1b[?1004;1$y\x1b[?2004;2$y\x1b[?2026;2$y\x1b[1;1R\x1b[1;1R\x1bP>|ghostty 1.1.3\x1b\\\x1b[?0u\x1b_Gi=1;OK\x1b\\\x1b[?62;22c";
67
+ term.processCapabilityResponse(response);
68
+
69
+ try testing.expectEqualStrings("ghostty", term.getTerminalName());
70
+ try testing.expectEqualStrings("1.1.3", term.getTerminalVersion());
71
+ try testing.expect(term.term_info.from_xtversion);
72
+ }
73
+
74
+ test "environment variables - should be overridden by xtversion" {
75
+ var term = Terminal.init(.{});
76
+
77
+ // First check environment (simulated by setting values directly)
78
+ term.term_info.name_len = 6;
79
+ @memcpy(term.term_info.name[0..6], "vscode");
80
+ term.term_info.version_len = 5;
81
+ @memcpy(term.term_info.version[0..5], "1.0.0");
82
+ term.term_info.from_xtversion = false;
83
+
84
+ try testing.expectEqualStrings("vscode", term.getTerminalName());
85
+ try testing.expectEqualStrings("1.0.0", term.getTerminalVersion());
86
+ try testing.expect(!term.term_info.from_xtversion);
87
+
88
+ // Now process xtversion response - should override
89
+ const response = "\x1bP>|kitty(0.40.1)\x1b\\";
90
+ term.processCapabilityResponse(response);
91
+
92
+ try testing.expectEqualStrings("kitty", term.getTerminalName());
93
+ try testing.expectEqualStrings("0.40.1", term.getTerminalVersion());
94
+ try testing.expect(term.term_info.from_xtversion);
95
+ }
96
+
97
+ test "remote ignores env overrides but accepts capability responses" {
98
+ if (builtin.os.tag == .windows) return error.SkipZigTest;
99
+
100
+ var env = std.process.EnvMap.init(testing.allocator);
101
+ defer env.deinit();
102
+ try env.put("TMUX", "/tmp/tmux-1000/default,12345,0");
103
+ try env.put("TERM_PROGRAM", "iTerm.app");
104
+ try env.put("WT_SESSION", "test-session");
105
+
106
+ var term = Terminal.init(.{ .remote = true, .env_map = &env });
107
+
108
+ try testing.expect(!term.in_tmux);
109
+ try testing.expect(!term.caps.osc52);
110
+ try testing.expect(!term.caps.explicit_cursor_positioning);
111
+
112
+ term.processCapabilityResponse("\x1bP>|kitty(0.40.1)\x1b\\");
113
+ try testing.expect(term.caps.osc52);
114
+ }
115
+
116
+ test "setHostEnvVar applies env overrides in shared library mode" {
117
+ var term = Terminal.init(.{});
118
+ defer term.deinit();
119
+
120
+ try term.setHostEnvVar(testing.allocator, "TERM", "screen");
121
+ try testing.expect(term.skip_graphics_query);
122
+ try testing.expect(term.caps.unicode == .wcwidth);
123
+ try testing.expect(term.caps.explicit_cursor_positioning);
124
+
125
+ try term.setHostEnvVar(testing.allocator, "OPENTUI_FORCE_UNICODE", "1");
126
+ try testing.expect(term.caps.unicode == .unicode);
127
+
128
+ try term.setHostEnvVar(testing.allocator, "OPENTUI_GRAPHICS", "0");
129
+ try testing.expect(term.skip_graphics_query);
130
+ }
131
+
132
+ test "parseXtversion - terminal name only" {
133
+ var term = Terminal.init(.{});
134
+ const response = "\x1bP>|wezterm\x1b\\";
135
+ term.processCapabilityResponse(response);
136
+
137
+ try testing.expectEqualStrings("wezterm", term.getTerminalName());
138
+ try testing.expectEqualStrings("", term.getTerminalVersion());
139
+ try testing.expect(term.term_info.from_xtversion);
140
+ try testing.expect(term.caps.osc52);
141
+ }
142
+
143
+ test "parseXtversion - empty response" {
144
+ var term = Terminal.init(.{});
145
+
146
+ const initial_name_len = term.term_info.name_len;
147
+ const initial_version_len = term.term_info.version_len;
148
+
149
+ const response = "\x1bP>|\x1b\\";
150
+ term.processCapabilityResponse(response);
151
+
152
+ try testing.expectEqual(initial_name_len, term.term_info.name_len);
153
+ try testing.expectEqual(initial_version_len, term.term_info.version_len);
154
+ }
155
+
156
+ // Test buffer for capturing terminal output
157
+ const TestWriter = struct {
158
+ buffer: std.ArrayListUnmanaged(u8),
159
+ allocator: std.mem.Allocator,
160
+
161
+ pub fn init(allocator: std.mem.Allocator) TestWriter {
162
+ return .{ .buffer = .{}, .allocator = allocator };
163
+ }
164
+
165
+ pub fn deinit(self: *TestWriter) void {
166
+ self.buffer.deinit(self.allocator);
167
+ }
168
+
169
+ pub fn writeAll(self: *TestWriter, data: []const u8) !void {
170
+ try self.buffer.appendSlice(self.allocator, data);
171
+ }
172
+
173
+ pub fn print(self: *TestWriter, comptime fmt: []const u8, args: anytype) !void {
174
+ try self.buffer.writer(self.allocator).print(fmt, args);
175
+ }
176
+
177
+ pub fn getWritten(self: *TestWriter) []const u8 {
178
+ return self.buffer.items;
179
+ }
180
+
181
+ pub fn reset(self: *TestWriter) void {
182
+ self.buffer.clearRetainingCapacity();
183
+ }
184
+ };
185
+
186
+ test "queryTerminalSend - sends unwrapped queries when not in tmux" {
187
+ // Note: This test may fail if running inside tmux since checkEnvironmentOverrides
188
+ // reads TMUX/TERM env vars. We test the logic directly instead.
189
+ var term = Terminal.init(.{});
190
+
191
+ // Skip test if actually running in tmux
192
+ if (term.in_tmux) return error.SkipZigTest;
193
+
194
+ var writer = TestWriter.init(testing.allocator);
195
+ defer writer.deinit();
196
+
197
+ try term.queryTerminalSend(&writer);
198
+
199
+ const output = writer.getWritten();
200
+
201
+ // Should contain xtversion
202
+ try testing.expect(std.mem.indexOf(u8, output, "\x1b[>0q") != null);
203
+
204
+ // Should contain unwrapped DECRQM queries (single ESC)
205
+ try testing.expect(std.mem.indexOf(u8, output, "\x1b[?1016$p") != null);
206
+ try testing.expect(std.mem.indexOf(u8, output, "\x1b[?2027$p") != null);
207
+ try testing.expect(std.mem.indexOf(u8, output, "\x1b[?u") != null);
208
+
209
+ // Should NOT contain tmux DCS wrapper
210
+ try testing.expect(std.mem.indexOf(u8, output, "\x1bPtmux;") == null);
211
+
212
+ // Should mark capability queries as pending
213
+ try testing.expect(term.capability_queries_pending);
214
+ }
215
+
216
+ test "queryTerminalSend - sends DCS wrapped queries when in tmux" {
217
+ // Note: This test checks logic when in_tmux is true.
218
+ // We can't easily force in_tmux=true since checkEnvironmentOverrides resets it,
219
+ // so we test this via sendPendingQueries tests instead.
220
+ var term = Terminal.init(.{});
221
+
222
+ // Only run the DCS wrapping test if actually in tmux
223
+ if (!term.in_tmux) return error.SkipZigTest;
224
+
225
+ var writer = TestWriter.init(testing.allocator);
226
+ defer writer.deinit();
227
+
228
+ try term.queryTerminalSend(&writer);
229
+
230
+ const output = writer.getWritten();
231
+
232
+ // Should contain xtversion (unwrapped - used for detection)
233
+ try testing.expect(std.mem.indexOf(u8, output, "\x1b[>0q") != null);
234
+
235
+ // Should contain tmux DCS wrapper start and doubled ESC for queries
236
+ // wrapForTmux wraps all queries together with one DCS envelope
237
+ try testing.expect(std.mem.indexOf(u8, output, "\x1bPtmux;\x1b\x1b[?1016$p") != null);
238
+
239
+ // Should NOT mark capability queries as pending (already sent wrapped)
240
+ try testing.expect(!term.capability_queries_pending);
241
+ }
242
+
243
+ test "sendPendingQueries - sends wrapped queries after tmux detected via xtversion" {
244
+ var term = Terminal.init(.{});
245
+ term.in_tmux = false;
246
+ term.capability_queries_pending = true;
247
+ term.graphics_query_pending = true;
248
+
249
+ // Simulate tmux detected via xtversion
250
+ term.term_info.from_xtversion = true;
251
+ term.term_info.name_len = 4;
252
+ @memcpy(term.term_info.name[0..4], "tmux");
253
+
254
+ var writer = TestWriter.init(testing.allocator);
255
+ defer writer.deinit();
256
+
257
+ const did_send = try term.sendPendingQueries(&writer);
258
+
259
+ try testing.expect(did_send);
260
+
261
+ const output = writer.getWritten();
262
+
263
+ // Should send DCS wrapped capability queries (wrapForTmux wraps all queries together)
264
+ try testing.expect(std.mem.indexOf(u8, output, "\x1bPtmux;\x1b\x1b[?1016$p") != null);
265
+
266
+ // Should send DCS wrapped graphics query
267
+ try testing.expect(std.mem.indexOf(u8, output, "\x1bPtmux;\x1b\x1b_G") != null);
268
+
269
+ // Should clear pending flags
270
+ try testing.expect(!term.capability_queries_pending);
271
+ try testing.expect(!term.graphics_query_pending);
272
+ }
273
+
274
+ test "sendPendingQueries - sends unwrapped graphics query for non-tmux terminal" {
275
+ var term = Terminal.init(.{});
276
+ term.in_tmux = false;
277
+ term.capability_queries_pending = true;
278
+ term.graphics_query_pending = true;
279
+
280
+ // Simulate non-tmux terminal detected via xtversion
281
+ term.term_info.from_xtversion = true;
282
+ term.term_info.name_len = 5;
283
+ @memcpy(term.term_info.name[0..5], "kitty");
284
+
285
+ var writer = TestWriter.init(testing.allocator);
286
+ defer writer.deinit();
287
+
288
+ const did_send = try term.sendPendingQueries(&writer);
289
+
290
+ try testing.expect(did_send);
291
+
292
+ const output = writer.getWritten();
293
+
294
+ // Should NOT send DCS wrapped capability queries (not tmux)
295
+ try testing.expect(std.mem.indexOf(u8, output, "\x1bPtmux;") == null);
296
+
297
+ // Should send unwrapped graphics query
298
+ try testing.expect(std.mem.indexOf(u8, output, "\x1b_Gi=31337") != null);
299
+
300
+ // Should clear pending flags
301
+ try testing.expect(!term.capability_queries_pending);
302
+ try testing.expect(!term.graphics_query_pending);
303
+ }
304
+
305
+ test "sendPendingQueries - sends unwrapped graphics query even without xtversion response" {
306
+ // This covers terminals that support kitty graphics but don't respond to xtversion.
307
+ // The graphics query should still be sent (unwrapped) so we can detect graphics support.
308
+ var term = Terminal.init(.{});
309
+ term.in_tmux = false;
310
+ term.term_info.from_xtversion = false;
311
+ term.capability_queries_pending = true;
312
+ term.graphics_query_pending = true;
313
+
314
+ var writer = TestWriter.init(testing.allocator);
315
+ defer writer.deinit();
316
+
317
+ const did_send = try term.sendPendingQueries(&writer);
318
+
319
+ try testing.expect(did_send);
320
+
321
+ const output = writer.getWritten();
322
+
323
+ // Should send unwrapped graphics query (not tmux, so no DCS wrapper)
324
+ try testing.expect(std.mem.indexOf(u8, output, "\x1b_Gi=31337") != null);
325
+ try testing.expect(std.mem.indexOf(u8, output, "\x1bPtmux;") == null);
326
+
327
+ // Should clear graphics pending flag
328
+ try testing.expect(!term.graphics_query_pending);
329
+
330
+ // Capability queries should NOT be re-sent (no xtversion means we don't know if tmux,
331
+ // but they were already sent unwrapped in queryTerminalSend)
332
+ try testing.expect(!term.capability_queries_pending);
333
+ }
334
+
335
+ test "sendPendingQueries - skips graphics when skip_graphics_query is set" {
336
+ var term = Terminal.init(.{});
337
+ term.in_tmux = true;
338
+ term.skip_graphics_query = true;
339
+ term.graphics_query_pending = true;
340
+ term.capability_queries_pending = false;
341
+
342
+ var writer = TestWriter.init(testing.allocator);
343
+ defer writer.deinit();
344
+
345
+ const did_send = try term.sendPendingQueries(&writer);
346
+
347
+ try testing.expect(!did_send);
348
+
349
+ const output = writer.getWritten();
350
+ try testing.expect(std.mem.indexOf(u8, output, "Gi=31337") == null);
351
+ }
352
+
353
+ test "isXtversionTmux - detects tmux from xtversion" {
354
+ var term = Terminal.init(.{});
355
+
356
+ // Not from xtversion
357
+ term.term_info.from_xtversion = false;
358
+ term.term_info.name_len = 4;
359
+ @memcpy(term.term_info.name[0..4], "tmux");
360
+ try testing.expect(!term.isXtversionTmux());
361
+
362
+ // From xtversion but not tmux
363
+ term.term_info.from_xtversion = true;
364
+ term.term_info.name_len = 5;
365
+ @memcpy(term.term_info.name[0..5], "kitty");
366
+ try testing.expect(!term.isXtversionTmux());
367
+
368
+ // From xtversion and is tmux
369
+ term.term_info.name_len = 4;
370
+ @memcpy(term.term_info.name[0..4], "tmux");
371
+ try testing.expect(term.isXtversionTmux());
372
+ }
373
+
374
+ // ============================================================================
375
+ // GRAPHEME CURSOR POSITIONING CAPABILITY TESTS
376
+ // ============================================================================
377
+
378
+ test "processCapabilityResponse - tmux sets explicit_cursor_positioning" {
379
+ var term: Terminal = .{};
380
+
381
+ term.caps.explicit_cursor_positioning = false;
382
+ term.caps.unicode = .unicode;
383
+
384
+ const response = "\x1bP>|tmux 3.5a\x1b\\";
385
+ term.processCapabilityResponse(response);
386
+
387
+ try testing.expect(term.caps.explicit_cursor_positioning);
388
+ try testing.expectEqual(utf8.WidthMethod.wcwidth, term.caps.unicode);
389
+ }
390
+
391
+ test "processCapabilityResponse - alacritty sets explicit_cursor_positioning" {
392
+ var term: Terminal = .{};
393
+
394
+ term.caps.explicit_cursor_positioning = false;
395
+
396
+ const response = "\x1bP>|alacritty 0.13.0\x1b\\";
397
+ term.processCapabilityResponse(response);
398
+
399
+ try testing.expect(term.caps.explicit_cursor_positioning);
400
+ }
401
+
402
+ test "processCapabilityResponse - kitty does not set explicit_cursor_positioning" {
403
+ var term: Terminal = .{};
404
+
405
+ term.caps.explicit_cursor_positioning = false;
406
+
407
+ const response = "\x1bP>|kitty(0.40.1)\x1b\\";
408
+ term.processCapabilityResponse(response);
409
+
410
+ try testing.expect(!term.caps.explicit_cursor_positioning);
411
+ }
412
+
413
+ test "processCapabilityResponse - ghostty does not set explicit_cursor_positioning" {
414
+ var term: Terminal = .{};
415
+
416
+ term.caps.explicit_cursor_positioning = false;
417
+
418
+ const response = "\x1bP>|ghostty 1.1.3\x1b\\";
419
+ term.processCapabilityResponse(response);
420
+
421
+ try testing.expect(!term.caps.explicit_cursor_positioning);
422
+ }
423
+
424
+ // ============================================================================
425
+ // CLIPBOARD (OSC 52) TESTS
426
+ // ============================================================================
427
+
428
+ test "writeClipboard - generates basic OSC52 sequence" {
429
+ if (builtin.os.tag == .windows) return error.SkipZigTest;
430
+
431
+ var env = std.process.EnvMap.init(testing.allocator);
432
+ defer env.deinit();
433
+
434
+ var term = Terminal.init(.{ .env_map = &env });
435
+ term.caps.osc52 = true;
436
+
437
+ var writer = TestWriter.init(testing.allocator);
438
+ defer writer.deinit();
439
+
440
+ try term.writeClipboard(&writer, .clipboard, "aGVsbG8=");
441
+
442
+ const output = writer.getWritten();
443
+ // Should be: ESC]52;c;aGVsbG8=ESC\
444
+ try testing.expectEqualStrings("\x1b]52;c;aGVsbG8=\x1b\\", output);
445
+ }
446
+
447
+ test "writeClipboard - supports different targets" {
448
+ if (builtin.os.tag == .windows) return error.SkipZigTest;
449
+
450
+ var env = std.process.EnvMap.init(testing.allocator);
451
+ defer env.deinit();
452
+
453
+ var term = Terminal.init(.{ .env_map = &env });
454
+ term.caps.osc52 = true;
455
+
456
+ var writer = TestWriter.init(testing.allocator);
457
+ defer writer.deinit();
458
+
459
+ try term.writeClipboard(&writer, .primary, "test");
460
+ try testing.expect(std.mem.indexOf(u8, writer.getWritten(), "\x1b]52;p;") != null);
461
+
462
+ writer.reset();
463
+ try term.writeClipboard(&writer, .secondary, "test");
464
+ try testing.expect(std.mem.indexOf(u8, writer.getWritten(), "\x1b]52;s;") != null);
465
+
466
+ writer.reset();
467
+ try term.writeClipboard(&writer, .query, "test");
468
+ try testing.expect(std.mem.indexOf(u8, writer.getWritten(), "\x1b]52;q;") != null);
469
+ }
470
+
471
+ test "writeClipboard - returns error when OSC52 not supported" {
472
+ if (builtin.os.tag == .windows) return error.SkipZigTest;
473
+
474
+ var term = Terminal.init(.{});
475
+ term.caps.osc52 = false;
476
+
477
+ var writer = TestWriter.init(testing.allocator);
478
+ defer writer.deinit();
479
+
480
+ const result = term.writeClipboard(&writer, .clipboard, "test");
481
+ try testing.expectError(error.NotSupported, result);
482
+ }
483
+
484
+ test "writeClipboard - wraps in DCS passthrough for tmux" {
485
+ if (builtin.os.tag == .windows) return error.SkipZigTest;
486
+
487
+ var env = std.process.EnvMap.init(testing.allocator);
488
+ defer env.deinit();
489
+ try env.put("TMUX", "/tmp/tmux-1000/default,12345,0");
490
+
491
+ var term = Terminal.init(.{ .env_map = &env });
492
+ term.caps.osc52 = true;
493
+
494
+ var writer = TestWriter.init(testing.allocator);
495
+ defer writer.deinit();
496
+
497
+ try term.writeClipboard(&writer, .clipboard, "test");
498
+
499
+ const output = writer.getWritten();
500
+ // Should start with tmux DCS wrapper
501
+ try testing.expect(std.mem.startsWith(u8, output, "\x1bPtmux;"));
502
+ // Should end with DCS terminator
503
+ try testing.expect(std.mem.endsWith(u8, output, "\x1b\\"));
504
+ // Should have doubled ESC characters inside
505
+ try testing.expect(std.mem.indexOf(u8, output, "\x1b\x1b") != null);
506
+ }
507
+
508
+ test "writeClipboard - wraps in DCS passthrough for GNU Screen" {
509
+ if (builtin.os.tag == .windows) return error.SkipZigTest;
510
+
511
+ var env = std.process.EnvMap.init(testing.allocator);
512
+ defer env.deinit();
513
+ try env.put("STY", "12345.pts-0.hostname");
514
+
515
+ var term = Terminal.init(.{ .env_map = &env });
516
+ term.caps.osc52 = true;
517
+
518
+ var writer = TestWriter.init(testing.allocator);
519
+ defer writer.deinit();
520
+
521
+ try term.writeClipboard(&writer, .clipboard, "test");
522
+
523
+ const output = writer.getWritten();
524
+ // Should start with DCS (but not tmux prefix)
525
+ try testing.expect(std.mem.startsWith(u8, output, "\x1bP"));
526
+ try testing.expect(!std.mem.startsWith(u8, output, "\x1bPtmux;"));
527
+ // Should end with DCS terminator
528
+ try testing.expect(std.mem.endsWith(u8, output, "\x1b\\"));
529
+ // Should have doubled ESC characters
530
+ try testing.expect(std.mem.indexOf(u8, output, "\x1b\x1b") != null);
531
+ }
532
+
533
+ test "writeClipboard - handles tmux sessions" {
534
+ if (builtin.os.tag == .windows) return error.SkipZigTest;
535
+
536
+ var env = std.process.EnvMap.init(testing.allocator);
537
+ defer env.deinit();
538
+ try env.put("TMUX", "/tmp/tmux-1000/default,12345,0");
539
+
540
+ var term = Terminal.init(.{ .env_map = &env });
541
+ term.caps.osc52 = true;
542
+
543
+ var writer = TestWriter.init(testing.allocator);
544
+ defer writer.deinit();
545
+
546
+ try term.writeClipboard(&writer, .clipboard, "test");
547
+
548
+ const output = writer.getWritten();
549
+ // Should have tmux DCS wrapper
550
+ try testing.expect(std.mem.startsWith(u8, output, "\x1bPtmux;"));
551
+ // Should end with DCS terminator
552
+ try testing.expect(std.mem.endsWith(u8, output, "\x1b\\"));
553
+ // Should have doubled ESC characters
554
+ try testing.expect(std.mem.indexOf(u8, output, "\x1b\x1b") != null);
555
+ }
556
+
557
+ test "caps.osc52 - clipboard capability flag" {
558
+ var term = Terminal.init(.{});
559
+
560
+ term.caps.osc52 = false;
561
+ try testing.expect(!term.caps.osc52);
562
+
563
+ term.caps.osc52 = true;
564
+ try testing.expect(term.caps.osc52);
565
+ }
566
+
567
+ fn countSubstring(haystack: []const u8, needle: []const u8) usize {
568
+ var count: usize = 0;
569
+ var i: usize = 0;
570
+ while (i < haystack.len) {
571
+ if (std.mem.startsWith(u8, haystack[i..], needle)) {
572
+ count += 1;
573
+ i += needle.len;
574
+ } else {
575
+ i += 1;
576
+ }
577
+ }
578
+ return count;
579
+ }
580
+
581
+ test "queryTerminalSend - skips OSC 66 queries when OPENTUI_FORCE_EXPLICIT_WIDTH=false" {
582
+ if (builtin.os.tag == .windows) return error.SkipZigTest;
583
+
584
+ var env = std.process.EnvMap.init(testing.allocator);
585
+ defer env.deinit();
586
+ try env.put("OPENTUI_FORCE_EXPLICIT_WIDTH", "false");
587
+
588
+ var term = Terminal.init(.{ .env_map = &env });
589
+
590
+ var writer = TestWriter.init(testing.allocator);
591
+ defer writer.deinit();
592
+
593
+ try term.queryTerminalSend(&writer);
594
+
595
+ const output = writer.getWritten();
596
+
597
+ // Should not contain OSC 66 queries
598
+ try testing.expect(std.mem.indexOf(u8, output, "\x1b]66;") == null);
599
+
600
+ // Should still contain other queries
601
+ try testing.expect(std.mem.indexOf(u8, output, "\x1b[>0q") != null); // xtversion
602
+
603
+ // Verify the flag was set correctly
604
+ try testing.expect(term.skip_explicit_width_query);
605
+ try testing.expect(!term.caps.explicit_width);
606
+ }
607
+
608
+ test "queryTerminalSend - sends OSC 66 queries by default" {
609
+ if (builtin.os.tag == .windows) return error.SkipZigTest;
610
+
611
+ var env = std.process.EnvMap.init(testing.allocator);
612
+ defer env.deinit();
613
+
614
+ var term = Terminal.init(.{ .env_map = &env });
615
+
616
+ var writer = TestWriter.init(testing.allocator);
617
+ defer writer.deinit();
618
+
619
+ try term.queryTerminalSend(&writer);
620
+
621
+ const output = writer.getWritten();
622
+
623
+ // Should contain OSC 66 explicit width query
624
+ try testing.expect(std.mem.indexOf(u8, output, "\x1b]66;w=1; \x1b\\") != null);
625
+
626
+ // Should contain OSC 66 scaled text query
627
+ try testing.expect(std.mem.indexOf(u8, output, "\x1b]66;s=2; \x1b\\") != null);
628
+
629
+ // Verify the flag was not set
630
+ try testing.expect(!term.skip_explicit_width_query);
631
+ }
632
+
633
+ test "queryTerminalSend - sends OSC 66 queries when OPENTUI_FORCE_EXPLICIT_WIDTH=true" {
634
+ if (builtin.os.tag == .windows) return error.SkipZigTest;
635
+
636
+ var env = std.process.EnvMap.init(testing.allocator);
637
+ defer env.deinit();
638
+ try env.put("OPENTUI_FORCE_EXPLICIT_WIDTH", "true");
639
+
640
+ var term = Terminal.init(.{ .env_map = &env });
641
+
642
+ var writer = TestWriter.init(testing.allocator);
643
+ defer writer.deinit();
644
+
645
+ try term.queryTerminalSend(&writer);
646
+
647
+ const output = writer.getWritten();
648
+
649
+ // Should contain OSC 66 queries
650
+ try testing.expect(std.mem.indexOf(u8, output, "\x1b]66;w=1; \x1b\\") != null);
651
+ try testing.expect(std.mem.indexOf(u8, output, "\x1b]66;s=2; \x1b\\") != null);
652
+
653
+ // Verify the capability was forced on
654
+ try testing.expect(term.caps.explicit_width);
655
+ try testing.expect(!term.skip_explicit_width_query);
656
+ }
657
+
658
+ test "setMouseMode - enable without movement keeps click/drag only" {
659
+ var term = Terminal.init(.{});
660
+ var writer = TestWriter.init(testing.allocator);
661
+ defer writer.deinit();
662
+
663
+ try term.setMouseMode(&writer, true, false);
664
+
665
+ const output = writer.getWritten();
666
+ const idx_disable_any = std.mem.indexOf(u8, output, ansi.ANSI.disableAnyEventTracking).?;
667
+ const idx_enable_mouse = std.mem.indexOf(u8, output, ansi.ANSI.enableMouseTracking).?;
668
+ const idx_enable_button = std.mem.indexOf(u8, output, ansi.ANSI.enableButtonEventTracking).?;
669
+ const idx_enable_sgr = std.mem.indexOf(u8, output, ansi.ANSI.enableSGRMouseMode).?;
670
+ try testing.expect(std.mem.indexOf(u8, output, ansi.ANSI.enableAnyEventTracking) == null);
671
+ try testing.expect(idx_disable_any < idx_enable_mouse);
672
+ try testing.expect(idx_enable_mouse < idx_enable_button);
673
+ try testing.expect(idx_enable_button < idx_enable_sgr);
674
+
675
+ try testing.expect(term.state.mouse);
676
+ try testing.expect(!term.state.mouse_movement);
677
+ }
678
+
679
+ test "setMouseMode - enable with movement enables any-event tracking" {
680
+ var term = Terminal.init(.{});
681
+ var writer = TestWriter.init(testing.allocator);
682
+ defer writer.deinit();
683
+
684
+ try term.setMouseMode(&writer, true, true);
685
+
686
+ const output = writer.getWritten();
687
+ const idx_enable_mouse = std.mem.indexOf(u8, output, ansi.ANSI.enableMouseTracking).?;
688
+ const idx_enable_button = std.mem.indexOf(u8, output, ansi.ANSI.enableButtonEventTracking).?;
689
+ const idx_enable_any = std.mem.indexOf(u8, output, ansi.ANSI.enableAnyEventTracking).?;
690
+ const idx_enable_sgr = std.mem.indexOf(u8, output, ansi.ANSI.enableSGRMouseMode).?;
691
+ try testing.expect(idx_enable_mouse < idx_enable_button);
692
+ try testing.expect(idx_enable_button < idx_enable_any);
693
+ try testing.expect(idx_enable_any < idx_enable_sgr);
694
+ try testing.expect(std.mem.indexOf(u8, output, ansi.ANSI.disableAnyEventTracking) == null);
695
+
696
+ try testing.expect(term.state.mouse);
697
+ try testing.expect(term.state.mouse_movement);
698
+ }
699
+
700
+ test "restoreTerminalModes - respects mouse movement setting" {
701
+ var term = Terminal.init(.{});
702
+ term.state.mouse = true;
703
+ term.state.mouse_movement = false;
704
+
705
+ var writer = TestWriter.init(testing.allocator);
706
+ defer writer.deinit();
707
+
708
+ try term.restoreTerminalModes(&writer);
709
+
710
+ const output = writer.getWritten();
711
+ const idx_disable_any = std.mem.indexOf(u8, output, ansi.ANSI.disableAnyEventTracking).?;
712
+ const idx_enable_mouse = std.mem.indexOf(u8, output, ansi.ANSI.enableMouseTracking).?;
713
+ const idx_enable_button = std.mem.indexOf(u8, output, ansi.ANSI.enableButtonEventTracking).?;
714
+ const idx_enable_sgr = std.mem.indexOf(u8, output, ansi.ANSI.enableSGRMouseMode).?;
715
+ try testing.expect(idx_disable_any < idx_enable_mouse);
716
+ try testing.expect(idx_enable_mouse < idx_enable_button);
717
+ try testing.expect(idx_enable_button < idx_enable_sgr);
718
+ try testing.expect(std.mem.indexOf(u8, output, ansi.ANSI.enableAnyEventTracking) == null);
719
+ }