@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,178 @@
1
+ import type { TextRenderable } from "../renderables/Text.js"
2
+ import type { TextBuffer, TextChunk } from "../text-buffer.js"
3
+ import { createTextAttributes } from "../utils.js"
4
+ import { parseColor, type ColorInput } from "./RGBA.js"
5
+
6
+ const BrandedStyledText: unique symbol = Symbol.for("@opentui/core/StyledText")
7
+
8
+ export type Color = ColorInput
9
+
10
+ export interface StyleAttrs {
11
+ fg?: Color
12
+ bg?: Color
13
+ bold?: boolean
14
+ italic?: boolean
15
+ underline?: boolean
16
+ strikethrough?: boolean
17
+ dim?: boolean
18
+ reverse?: boolean
19
+ blink?: boolean
20
+ }
21
+
22
+ export function isStyledText(obj: any): obj is StyledText {
23
+ return obj && obj[BrandedStyledText]
24
+ }
25
+
26
+ export class StyledText {
27
+ [BrandedStyledText] = true
28
+
29
+ public chunks: TextChunk[]
30
+
31
+ constructor(chunks: TextChunk[]) {
32
+ this.chunks = chunks
33
+ }
34
+ }
35
+
36
+ export function stringToStyledText(content: string): StyledText {
37
+ const chunk = {
38
+ __isChunk: true as const,
39
+ text: content,
40
+ }
41
+ return new StyledText([chunk])
42
+ }
43
+
44
+ export type StylableInput = string | number | boolean | TextChunk
45
+
46
+ function applyStyle(input: StylableInput, style: StyleAttrs): TextChunk {
47
+ if (typeof input === "object" && "__isChunk" in input) {
48
+ const existingChunk = input as TextChunk
49
+
50
+ const fg = style.fg ? parseColor(style.fg) : existingChunk.fg
51
+ const bg = style.bg ? parseColor(style.bg) : existingChunk.bg
52
+
53
+ const newAttrs = createTextAttributes(style)
54
+ const mergedAttrs = existingChunk.attributes ? existingChunk.attributes | newAttrs : newAttrs
55
+
56
+ return {
57
+ __isChunk: true,
58
+ text: existingChunk.text,
59
+ fg,
60
+ bg,
61
+ attributes: mergedAttrs,
62
+ link: existingChunk.link,
63
+ }
64
+ } else {
65
+ const plainTextStr = String(input)
66
+ const fg = style.fg ? parseColor(style.fg) : undefined
67
+ const bg = style.bg ? parseColor(style.bg) : undefined
68
+ const attributes = createTextAttributes(style)
69
+
70
+ return {
71
+ __isChunk: true,
72
+ text: plainTextStr,
73
+ fg,
74
+ bg,
75
+ attributes,
76
+ }
77
+ }
78
+ }
79
+
80
+ // Color functions
81
+ export const black = (input: StylableInput): TextChunk => applyStyle(input, { fg: "black" })
82
+ export const red = (input: StylableInput): TextChunk => applyStyle(input, { fg: "red" })
83
+ export const green = (input: StylableInput): TextChunk => applyStyle(input, { fg: "green" })
84
+ export const yellow = (input: StylableInput): TextChunk => applyStyle(input, { fg: "yellow" })
85
+ export const blue = (input: StylableInput): TextChunk => applyStyle(input, { fg: "blue" })
86
+ export const magenta = (input: StylableInput): TextChunk => applyStyle(input, { fg: "magenta" })
87
+ export const cyan = (input: StylableInput): TextChunk => applyStyle(input, { fg: "cyan" })
88
+ export const white = (input: StylableInput): TextChunk => applyStyle(input, { fg: "white" })
89
+
90
+ // Bright color functions
91
+ export const brightBlack = (input: StylableInput): TextChunk => applyStyle(input, { fg: "brightBlack" })
92
+ export const brightRed = (input: StylableInput): TextChunk => applyStyle(input, { fg: "brightRed" })
93
+ export const brightGreen = (input: StylableInput): TextChunk => applyStyle(input, { fg: "brightGreen" })
94
+ export const brightYellow = (input: StylableInput): TextChunk => applyStyle(input, { fg: "brightYellow" })
95
+ export const brightBlue = (input: StylableInput): TextChunk => applyStyle(input, { fg: "brightBlue" })
96
+ export const brightMagenta = (input: StylableInput): TextChunk => applyStyle(input, { fg: "brightMagenta" })
97
+ export const brightCyan = (input: StylableInput): TextChunk => applyStyle(input, { fg: "brightCyan" })
98
+ export const brightWhite = (input: StylableInput): TextChunk => applyStyle(input, { fg: "brightWhite" })
99
+
100
+ // Background color functions
101
+ export const bgBlack = (input: StylableInput): TextChunk => applyStyle(input, { bg: "black" })
102
+ export const bgRed = (input: StylableInput): TextChunk => applyStyle(input, { bg: "red" })
103
+ export const bgGreen = (input: StylableInput): TextChunk => applyStyle(input, { bg: "green" })
104
+ export const bgYellow = (input: StylableInput): TextChunk => applyStyle(input, { bg: "yellow" })
105
+ export const bgBlue = (input: StylableInput): TextChunk => applyStyle(input, { bg: "blue" })
106
+ export const bgMagenta = (input: StylableInput): TextChunk => applyStyle(input, { bg: "magenta" })
107
+ export const bgCyan = (input: StylableInput): TextChunk => applyStyle(input, { bg: "cyan" })
108
+ export const bgWhite = (input: StylableInput): TextChunk => applyStyle(input, { bg: "white" })
109
+
110
+ // Style functions
111
+ export const bold = (input: StylableInput): TextChunk => applyStyle(input, { bold: true })
112
+ export const italic = (input: StylableInput): TextChunk => applyStyle(input, { italic: true })
113
+ export const underline = (input: StylableInput): TextChunk => applyStyle(input, { underline: true })
114
+ export const strikethrough = (input: StylableInput): TextChunk => applyStyle(input, { strikethrough: true })
115
+ export const dim = (input: StylableInput): TextChunk => applyStyle(input, { dim: true })
116
+ export const reverse = (input: StylableInput): TextChunk => applyStyle(input, { reverse: true })
117
+ export const blink = (input: StylableInput): TextChunk => applyStyle(input, { blink: true })
118
+
119
+ // Custom color functions
120
+ export const fg =
121
+ (color: Color) =>
122
+ (input: StylableInput): TextChunk =>
123
+ applyStyle(input, { fg: color })
124
+ export const bg =
125
+ (color: Color) =>
126
+ (input: StylableInput): TextChunk =>
127
+ applyStyle(input, { bg: color })
128
+
129
+ export const link =
130
+ (url: string) =>
131
+ (input: StylableInput): TextChunk => {
132
+ const chunk =
133
+ typeof input === "object" && "__isChunk" in input
134
+ ? (input as TextChunk)
135
+ : {
136
+ __isChunk: true as const,
137
+ text: String(input),
138
+ }
139
+
140
+ return {
141
+ ...chunk,
142
+ link: { url },
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Template literal handler for styled text (non-cached version).
148
+ * Returns a StyledText object containing chunks of text with optional styles.
149
+ */
150
+ export function t(strings: TemplateStringsArray, ...values: StylableInput[]): StyledText {
151
+ const chunks: TextChunk[] = []
152
+
153
+ for (let i = 0; i < strings.length; i++) {
154
+ const raw = strings[i]
155
+
156
+ if (raw) {
157
+ chunks.push({
158
+ __isChunk: true,
159
+ text: raw,
160
+ attributes: 0,
161
+ })
162
+ }
163
+
164
+ const val = values[i]
165
+ if (typeof val === "object" && "__isChunk" in val) {
166
+ chunks.push(val as TextChunk)
167
+ } else if (val !== undefined) {
168
+ const plainTextStr = String(val)
169
+ chunks.push({
170
+ __isChunk: true,
171
+ text: plainTextStr,
172
+ attributes: 0,
173
+ })
174
+ }
175
+ }
176
+
177
+ return new StyledText(chunks)
178
+ }
@@ -0,0 +1,202 @@
1
+ import { test, expect, describe } from "bun:test"
2
+ import {
3
+ isCapabilityResponse,
4
+ isPixelResolutionResponse,
5
+ parsePixelResolution,
6
+ } from "./terminal-capability-detection.js"
7
+
8
+ describe("isCapabilityResponse", () => {
9
+ test("detects DECRPM responses", () => {
10
+ expect(isCapabilityResponse("\x1b[?1016;2$y")).toBe(true)
11
+ expect(isCapabilityResponse("\x1b[?2027;0$y")).toBe(true)
12
+ expect(isCapabilityResponse("\x1b[?2031;2$y")).toBe(true)
13
+ expect(isCapabilityResponse("\x1b[?1004;1$y")).toBe(true)
14
+ expect(isCapabilityResponse("\x1b[?2026;2$y")).toBe(true)
15
+ expect(isCapabilityResponse("\x1b[?2004;2$y")).toBe(true)
16
+ })
17
+
18
+ test("detects CPR responses for width detection", () => {
19
+ expect(isCapabilityResponse("\x1b[1;2R")).toBe(true) // explicit width
20
+ expect(isCapabilityResponse("\x1b[1;3R")).toBe(true) // scaled text
21
+ })
22
+
23
+ test("does not detect regular CPR responses as capabilities", () => {
24
+ // Regular cursor position reports are NOT capabilities
25
+ expect(isCapabilityResponse("\x1b[10;5R")).toBe(false)
26
+ expect(isCapabilityResponse("\x1b[20;30R")).toBe(false)
27
+ })
28
+
29
+ test("detects XTVersion responses", () => {
30
+ expect(isCapabilityResponse("\x1bP>|kitty(0.40.1)\x1b\\")).toBe(true)
31
+ expect(isCapabilityResponse("\x1bP>|ghostty 1.1.3\x1b\\")).toBe(true)
32
+ expect(isCapabilityResponse("\x1bP>|tmux 3.5a\x1b\\")).toBe(true)
33
+ })
34
+
35
+ test("detects Kitty graphics responses", () => {
36
+ expect(isCapabilityResponse("\x1b_Gi=1;OK\x1b\\")).toBe(true)
37
+ expect(isCapabilityResponse("\x1b_Gi=1;EINVAL:Zero width/height not allowed\x1b\\")).toBe(true)
38
+ })
39
+
40
+ test("detects DA1 (Device Attributes) responses", () => {
41
+ expect(isCapabilityResponse("\x1b[?62;c")).toBe(true)
42
+ expect(isCapabilityResponse("\x1b[?62;22c")).toBe(true)
43
+ expect(isCapabilityResponse("\x1b[?1;2;4c")).toBe(true)
44
+ expect(isCapabilityResponse("\x1b[?6c")).toBe(true)
45
+ })
46
+
47
+ test("detects Kitty keyboard query responses", () => {
48
+ expect(isCapabilityResponse("\x1b[?0u")).toBe(true)
49
+ expect(isCapabilityResponse("\x1b[?1u")).toBe(true)
50
+ expect(isCapabilityResponse("\x1b[?31u")).toBe(true)
51
+ })
52
+
53
+ test("does not detect regular keypresses", () => {
54
+ expect(isCapabilityResponse("a")).toBe(false)
55
+ expect(isCapabilityResponse("A")).toBe(false)
56
+ expect(isCapabilityResponse("\x1b")).toBe(false)
57
+ expect(isCapabilityResponse("\x1ba")).toBe(false)
58
+ })
59
+
60
+ test("does not detect arrow keys", () => {
61
+ expect(isCapabilityResponse("\x1b[A")).toBe(false)
62
+ expect(isCapabilityResponse("\x1b[B")).toBe(false)
63
+ expect(isCapabilityResponse("\x1b[C")).toBe(false)
64
+ expect(isCapabilityResponse("\x1b[D")).toBe(false)
65
+ })
66
+
67
+ test("does not detect function keys", () => {
68
+ expect(isCapabilityResponse("\x1bOP")).toBe(false)
69
+ expect(isCapabilityResponse("\x1b[11~")).toBe(false)
70
+ expect(isCapabilityResponse("\x1b[24~")).toBe(false)
71
+ })
72
+
73
+ test("does not detect modified arrow keys", () => {
74
+ expect(isCapabilityResponse("\x1b[1;2A")).toBe(false)
75
+ expect(isCapabilityResponse("\x1b[1;5C")).toBe(false)
76
+ })
77
+
78
+ test("does not detect mouse sequences", () => {
79
+ expect(isCapabilityResponse("\x1b[<35;20;5m")).toBe(false)
80
+ expect(isCapabilityResponse("\x1b[<0;10;10M")).toBe(false)
81
+ })
82
+ })
83
+
84
+ describe("isPixelResolutionResponse", () => {
85
+ test("detects pixel resolution responses", () => {
86
+ expect(isPixelResolutionResponse("\x1b[4;720;1280t")).toBe(true)
87
+ expect(isPixelResolutionResponse("\x1b[4;1080;1920t")).toBe(true)
88
+ expect(isPixelResolutionResponse("\x1b[4;0;0t")).toBe(true)
89
+ })
90
+
91
+ test("does not detect other sequences", () => {
92
+ expect(isPixelResolutionResponse("a")).toBe(false)
93
+ expect(isPixelResolutionResponse("\x1b[A")).toBe(false)
94
+ expect(isPixelResolutionResponse("\x1b[?1016;2$y")).toBe(false)
95
+ })
96
+ })
97
+
98
+ describe("parsePixelResolution", () => {
99
+ test("parses valid pixel resolution responses", () => {
100
+ expect(parsePixelResolution("\x1b[4;720;1280t")).toEqual({ width: 1280, height: 720 })
101
+ expect(parsePixelResolution("\x1b[4;1080;1920t")).toEqual({ width: 1920, height: 1080 })
102
+ expect(parsePixelResolution("\x1b[4;0;0t")).toEqual({ width: 0, height: 0 })
103
+ })
104
+
105
+ test("returns null for invalid sequences", () => {
106
+ expect(parsePixelResolution("a")).toBeNull()
107
+ expect(parsePixelResolution("\x1b[A")).toBeNull()
108
+ expect(parsePixelResolution("\x1b[?1016;2$y")).toBeNull()
109
+ })
110
+ })
111
+
112
+ describe("real-world terminal capability sequences", () => {
113
+ test("kitty terminal full response - individual sequences", () => {
114
+ // Should detect multiple capability sequences
115
+ expect(isCapabilityResponse("\x1b[?1016;2$y")).toBe(true)
116
+ expect(isCapabilityResponse("\x1b[?2027;0$y")).toBe(true)
117
+ expect(isCapabilityResponse("\x1b[1;2R")).toBe(true)
118
+ expect(isCapabilityResponse("\x1b[1;3R")).toBe(true)
119
+ expect(isCapabilityResponse("\x1bP>|kitty(0.40.1)\x1b\\")).toBe(true)
120
+ expect(isCapabilityResponse("\x1b_Gi=1;EINVAL:Zero width/height not allowed\x1b\\")).toBe(true)
121
+ expect(isCapabilityResponse("\x1b[?62;c")).toBe(true)
122
+ })
123
+
124
+ test("ghostty terminal response - individual sequences", () => {
125
+ expect(isCapabilityResponse("\x1bP>|ghostty 1.1.3\x1b\\")).toBe(true)
126
+ expect(isCapabilityResponse("\x1b_Gi=1;OK\x1b\\")).toBe(true)
127
+ expect(isCapabilityResponse("\x1b[?62;22c")).toBe(true)
128
+ })
129
+
130
+ test("alacritty terminal response - individual sequences", () => {
131
+ expect(isCapabilityResponse("\x1b[?1016;0$y")).toBe(true)
132
+ expect(isCapabilityResponse("\x1b[?6c")).toBe(true)
133
+ })
134
+
135
+ test("vscode terminal minimal response", () => {
136
+ expect(isCapabilityResponse("\x1b[?1016;2$y")).toBe(true)
137
+ })
138
+ })
139
+
140
+ describe("renderer capabilities event", () => {
141
+ /**
142
+ * The renderer emits "capabilities" event each time a capability response is processed.
143
+ * This happens multiple times at startup because the terminal responds to multiple queries:
144
+ * - DECRPM queries (sgr_pixels, unicode, color_scheme, focus, bracketed_paste, sync)
145
+ * - CPR queries for width detection (explicit_width, scaled_text)
146
+ * - XTVersion (terminal name/version, kitty detection)
147
+ * - Kitty keyboard query response
148
+ *
149
+ * Each response arrives async and triggers the event, so consumers should expect
150
+ * multiple emissions and handle them reactively.
151
+ */
152
+ test("kitty terminal emits capabilities event for each response", async () => {
153
+ const { createTestRenderer } = await import("../testing/test-renderer.js")
154
+ const { renderer } = await createTestRenderer({})
155
+
156
+ const events: any[] = []
157
+ renderer.on("capabilities", (caps) => events.push({ ...caps }))
158
+
159
+ // Simulate all 10 Kitty capability responses (as they arrive separately)
160
+ const kittyResponses = [
161
+ "\x1b[?1016;2$y", // 1. sgr_pixels
162
+ "\x1b[?2027;0$y", // 2. unicode query
163
+ "\x1b[?2031;2$y", // 3. color_scheme_updates
164
+ "\x1b[?1004;2$y", // 4. focus_tracking
165
+ "\x1b[?2004;2$y", // 5. bracketed_paste
166
+ "\x1b[?2026;2$y", // 6. sync
167
+ "\x1b[1;2R", // 7. explicit_width (CPR)
168
+ "\x1b[1;3R", // 8. scaled_text (CPR)
169
+ "\x1bP>|kitty(0.42.2)\x1b\\", // 9. xtversion (triggers kitty detection)
170
+ "\x1b[?0u", // 10. kitty keyboard query
171
+ ]
172
+
173
+ for (const response of kittyResponses) {
174
+ renderer.stdin.emit("data", Buffer.from(response))
175
+ await new Promise((resolve) => setTimeout(resolve, 10))
176
+ }
177
+
178
+ // Should have received 10 capability events
179
+ expect(events.length).toBe(10)
180
+
181
+ // First event: sgr_pixels detected
182
+ expect(events[0].sgr_pixels).toBe(true)
183
+
184
+ // After xtversion (event 9): kitty_keyboard should be true
185
+ expect(events[8].kitty_keyboard).toBe(true)
186
+ expect(events[8].kitty_graphics).toBe(true)
187
+ expect(events[8].terminal.name).toBe("kitty")
188
+ expect(events[8].terminal.version).toBe("0.42.2")
189
+
190
+ // Final state should have all kitty capabilities
191
+ const finalCaps = events[9]
192
+ expect(finalCaps.kitty_keyboard).toBe(true)
193
+ expect(finalCaps.sgr_pixels).toBe(true)
194
+ expect(finalCaps.color_scheme_updates).toBe(true)
195
+ expect(finalCaps.focus_tracking).toBe(true)
196
+ expect(finalCaps.sync).toBe(true)
197
+ expect(finalCaps.explicit_width).toBe(true)
198
+ expect(finalCaps.scaled_text).toBe(true)
199
+
200
+ renderer.destroy()
201
+ })
202
+ })
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Terminal capability response detection utilities.
3
+ *
4
+ * Detects various terminal capability response sequences:
5
+ * - DECRPM (DEC Request Mode): ESC[?...;N$y where N is 0,1,2,3,4
6
+ * - CPR (Cursor Position Report): ESC[row;colR (used for width detection)
7
+ * - XTVersion: ESC P >| ... ESC \
8
+ * - Kitty Graphics: ESC _ G ... ESC \
9
+ * - Kitty Keyboard Query: ESC[?Nu where N is 0,1,2,etc
10
+ * - DA1 (Device Attributes): ESC[?...c
11
+ * - Pixel Resolution: ESC[4;height;widtht
12
+ */
13
+
14
+ /**
15
+ * Check if a sequence is a terminal capability response.
16
+ * Returns true if the sequence matches any known capability response pattern.
17
+ */
18
+ export function isCapabilityResponse(sequence: string): boolean {
19
+ // DECRPM: ESC[?digits;digits$y
20
+ if (/\x1b\[\?\d+(?:;\d+)*\$y/.test(sequence)) {
21
+ return true
22
+ }
23
+
24
+ // CPR for explicit width/scaled text detection: ESC[1;NR where N >= 2
25
+ // The column number tells us how many characters were rendered with width annotations
26
+ // ESC[1;1R means no width support (cursor didn't move)
27
+ // ESC[1;2R or higher means width support (cursor moved after rendering)
28
+ // We accept any column >= 2 to handle cases where cursor wasn't at exact home position
29
+ if (/\x1b\[1;(?!1R)\d+R/.test(sequence)) {
30
+ return true
31
+ }
32
+
33
+ // XTVersion: ESC P >| ... ESC \
34
+ if (/\x1bP>\|[\s\S]*?\x1b\\/.test(sequence)) {
35
+ return true
36
+ }
37
+
38
+ // Kitty graphics response: ESC _ G ... ESC \
39
+ // Matches any graphics response including OK, errors, etc.
40
+ // This is for filtering capability responses from user input
41
+ if (/\x1b_G[\s\S]*?\x1b\\/.test(sequence)) {
42
+ return true
43
+ }
44
+
45
+ // Kitty keyboard query response: ESC[?Nu or ESC[?N;Mu (progressive enhancement)
46
+ if (/\x1b\[\?\d+(?:;\d+)?u/.test(sequence)) {
47
+ return true
48
+ }
49
+
50
+ // DA1 (Device Attributes): ESC[?...c
51
+ if (/\x1b\[\?[0-9;]*c/.test(sequence)) {
52
+ return true
53
+ }
54
+
55
+ return false
56
+ }
57
+
58
+ /**
59
+ * Check if a sequence is a pixel resolution response.
60
+ * Format: ESC[4;height;widtht
61
+ */
62
+ export function isPixelResolutionResponse(sequence: string): boolean {
63
+ return /\x1b\[4;\d+;\d+t/.test(sequence)
64
+ }
65
+
66
+ /**
67
+ * Parse pixel resolution from response sequence.
68
+ * Returns { width, height } or null if not a valid resolution response.
69
+ */
70
+ export function parsePixelResolution(sequence: string): { width: number; height: number } | null {
71
+ const match = sequence.match(/\x1b\[4;(\d+);(\d+)t/)
72
+ if (match) {
73
+ return {
74
+ width: parseInt(match[2]),
75
+ height: parseInt(match[1]),
76
+ }
77
+ }
78
+ return null
79
+ }