@xincli/opentui-core 0.4.6

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 (476) hide show
  1. package/README.md +63 -0
  2. package/dev/keypress-debug-renderer.ts +148 -0
  3. package/dev/keypress-debug.ts +43 -0
  4. package/dev/print-env-vars.ts +32 -0
  5. package/dev/test-tmux-graphics-334.sh +68 -0
  6. package/dev/test-tmux-theme-queries.sh +151 -0
  7. package/dev/thai-debug-test.ts +68 -0
  8. package/dev/theme-mode.ts +290 -0
  9. package/docs/development.md +144 -0
  10. package/package.json +102 -0
  11. package/prebuilt/aarch64-android/libopentui.so +0 -0
  12. package/scripts/build-android.ts +226 -0
  13. package/scripts/build-native-termux.sh +525 -0
  14. package/scripts/build.ts +530 -0
  15. package/scripts/dist-test.ts +312 -0
  16. package/scripts/package-prebuilt.ts +110 -0
  17. package/scripts/publish.ts +60 -0
  18. package/scripts/test-node-hook.mjs +16 -0
  19. package/scripts/test-node.ts +241 -0
  20. package/scripts/vendor-deps.sh +73 -0
  21. package/src/NativeSpanFeed.ts +375 -0
  22. package/src/Renderable.ts +1878 -0
  23. package/src/__snapshots__/buffer.test.ts.snap +28 -0
  24. package/src/animation/Timeline.test.ts +2709 -0
  25. package/src/animation/Timeline.ts +598 -0
  26. package/src/ansi.ts +22 -0
  27. package/src/audio.ts +479 -0
  28. package/src/benchmark/attenuation-benchmark.ts +81 -0
  29. package/src/benchmark/audio-playback-benchmark.ts +344 -0
  30. package/src/benchmark/box-draw-benchmark.ts +1042 -0
  31. package/src/benchmark/colormatrix-benchmark.ts +123 -0
  32. package/src/benchmark/gain-benchmark.ts +80 -0
  33. package/src/benchmark/latest-all-bench-run.json +707 -0
  34. package/src/benchmark/latest-async-bench-run.json +336 -0
  35. package/src/benchmark/latest-default-bench-run.json +657 -0
  36. package/src/benchmark/latest-large-bench-run.json +707 -0
  37. package/src/benchmark/latest-quick-bench-run.json +207 -0
  38. package/src/benchmark/layout-benchmark.ts +2547 -0
  39. package/src/benchmark/markdown-benchmark.ts +1796 -0
  40. package/src/benchmark/native-span-feed-async-benchmark.ts +355 -0
  41. package/src/benchmark/native-span-feed-benchmark.md +56 -0
  42. package/src/benchmark/native-span-feed-benchmark.ts +596 -0
  43. package/src/benchmark/native-span-feed-compare.ts +280 -0
  44. package/src/benchmark/render-traversal-benchmark.ts +928 -0
  45. package/src/benchmark/text-buffer-render-benchmark.ts +874 -0
  46. package/src/benchmark/text-table-benchmark.ts +948 -0
  47. package/src/buffer.test.ts +292 -0
  48. package/src/buffer.ts +564 -0
  49. package/src/console.test.ts +629 -0
  50. package/src/console.ts +1253 -0
  51. package/src/edit-buffer.test.ts +1852 -0
  52. package/src/edit-buffer.ts +417 -0
  53. package/src/editor-view.test.ts +1056 -0
  54. package/src/editor-view.ts +290 -0
  55. package/src/index.ts +25 -0
  56. package/src/lib/KeyHandler.integration.test.ts +292 -0
  57. package/src/lib/KeyHandler.stopPropagation.test.ts +289 -0
  58. package/src/lib/KeyHandler.test.ts +662 -0
  59. package/src/lib/KeyHandler.ts +222 -0
  60. package/src/lib/RGBA.test.ts +60 -0
  61. package/src/lib/RGBA.ts +343 -0
  62. package/src/lib/ascii.font.ts +330 -0
  63. package/src/lib/border.test.ts +83 -0
  64. package/src/lib/border.ts +170 -0
  65. package/src/lib/bunfs.test.ts +27 -0
  66. package/src/lib/bunfs.ts +18 -0
  67. package/src/lib/clipboard.test.ts +63 -0
  68. package/src/lib/clipboard.ts +41 -0
  69. package/src/lib/clock.ts +35 -0
  70. package/src/lib/data-paths.test.ts +133 -0
  71. package/src/lib/data-paths.ts +109 -0
  72. package/src/lib/debounce.ts +106 -0
  73. package/src/lib/detect-links.test.ts +98 -0
  74. package/src/lib/detect-links.ts +56 -0
  75. package/src/lib/env.test.ts +228 -0
  76. package/src/lib/env.ts +209 -0
  77. package/src/lib/extmarks-history.ts +51 -0
  78. package/src/lib/extmarks-multiwidth.test.ts +324 -0
  79. package/src/lib/extmarks.test.ts +3547 -0
  80. package/src/lib/extmarks.ts +861 -0
  81. package/src/lib/fonts/block.json +405 -0
  82. package/src/lib/fonts/grid.json +265 -0
  83. package/src/lib/fonts/huge.json +741 -0
  84. package/src/lib/fonts/pallet.json +314 -0
  85. package/src/lib/fonts/shade.json +591 -0
  86. package/src/lib/fonts/slick.json +321 -0
  87. package/src/lib/fonts/tiny.json +69 -0
  88. package/src/lib/hast-styled-text.ts +59 -0
  89. package/src/lib/index.ts +22 -0
  90. package/src/lib/keybinding.internal.test.ts +342 -0
  91. package/src/lib/keybinding.internal.ts +182 -0
  92. package/src/lib/objects-in-viewport.test.ts +789 -0
  93. package/src/lib/objects-in-viewport.ts +153 -0
  94. package/src/lib/output.capture.ts +58 -0
  95. package/src/lib/parse.keypress-kitty.protocol.test.ts +347 -0
  96. package/src/lib/parse.keypress-kitty.test.ts +712 -0
  97. package/src/lib/parse.keypress-kitty.ts +470 -0
  98. package/src/lib/parse.keypress.test.ts +2020 -0
  99. package/src/lib/parse.keypress.ts +480 -0
  100. package/src/lib/parse.mouse.test.ts +552 -0
  101. package/src/lib/parse.mouse.ts +232 -0
  102. package/src/lib/paste.ts +18 -0
  103. package/src/lib/queue.ts +65 -0
  104. package/src/lib/render-geometry.ts +36 -0
  105. package/src/lib/renderable.validations.test.ts +87 -0
  106. package/src/lib/renderable.validations.ts +83 -0
  107. package/src/lib/scroll-acceleration.ts +98 -0
  108. package/src/lib/selection.ts +261 -0
  109. package/src/lib/singleton.ts +34 -0
  110. package/src/lib/stdin-parser.test.ts +2439 -0
  111. package/src/lib/stdin-parser.ts +2007 -0
  112. package/src/lib/styled-text.ts +178 -0
  113. package/src/lib/terminal-capability-detection.test.ts +226 -0
  114. package/src/lib/terminal-capability-detection.ts +98 -0
  115. package/src/lib/terminal-palette.test.ts +954 -0
  116. package/src/lib/terminal-palette.ts +441 -0
  117. package/src/lib/tree-sitter/assets/README.md +119 -0
  118. package/src/lib/tree-sitter/assets/javascript/highlights.scm +205 -0
  119. package/src/lib/tree-sitter/assets/javascript/tree-sitter-javascript.wasm +0 -0
  120. package/src/lib/tree-sitter/assets/markdown/highlights.scm +150 -0
  121. package/src/lib/tree-sitter/assets/markdown/injections.scm +27 -0
  122. package/src/lib/tree-sitter/assets/markdown/tree-sitter-markdown.wasm +0 -0
  123. package/src/lib/tree-sitter/assets/markdown_inline/highlights.scm +115 -0
  124. package/src/lib/tree-sitter/assets/markdown_inline/tree-sitter-markdown_inline.wasm +0 -0
  125. package/src/lib/tree-sitter/assets/typescript/highlights.scm +604 -0
  126. package/src/lib/tree-sitter/assets/typescript/tree-sitter-typescript.wasm +0 -0
  127. package/src/lib/tree-sitter/assets/update.ts +360 -0
  128. package/src/lib/tree-sitter/assets/zig/highlights.scm +284 -0
  129. package/src/lib/tree-sitter/assets/zig/tree-sitter-zig.wasm +0 -0
  130. package/src/lib/tree-sitter/assets.d.ts +9 -0
  131. package/src/lib/tree-sitter/cache.test.ts +291 -0
  132. package/src/lib/tree-sitter/client.test.ts +1434 -0
  133. package/src/lib/tree-sitter/client.ts +847 -0
  134. package/src/lib/tree-sitter/default-parsers.ts +133 -0
  135. package/src/lib/tree-sitter/download-utils.ts +148 -0
  136. package/src/lib/tree-sitter/index.ts +75 -0
  137. package/src/lib/tree-sitter/parser.worker.ts +1098 -0
  138. package/src/lib/tree-sitter/parsers-config.ts +81 -0
  139. package/src/lib/tree-sitter/resolve-ft.test.ts +55 -0
  140. package/src/lib/tree-sitter/resolve-ft.ts +189 -0
  141. package/src/lib/tree-sitter/types.ts +132 -0
  142. package/src/lib/tree-sitter/update-assets.ts +10 -0
  143. package/src/lib/tree-sitter-styled-text.test.ts +1253 -0
  144. package/src/lib/tree-sitter-styled-text.ts +314 -0
  145. package/src/lib/validate-dir-name.ts +55 -0
  146. package/src/lib/yoga.options.test.ts +628 -0
  147. package/src/lib/yoga.options.ts +346 -0
  148. package/src/native-event-worker-repro.test.ts +48 -0
  149. package/src/native-event-worker-repro.worker.ts +9 -0
  150. package/src/native-handle.test.ts +221 -0
  151. package/src/platform/ffi.test.ts +516 -0
  152. package/src/platform/ffi.ts +653 -0
  153. package/src/platform/runtime.test.ts +52 -0
  154. package/src/platform/runtime.ts +121 -0
  155. package/src/platform/test.ts +45 -0
  156. package/src/platform/worker-handler-cleanup.fixture.ts +12 -0
  157. package/src/platform/worker-onmessage-startup.fixture.ts +10 -0
  158. package/src/platform/worker-startup.fixture.ts +9 -0
  159. package/src/platform/worker.node-test.ts +153 -0
  160. package/src/platform/worker.ts +425 -0
  161. package/src/plugins/core-slot.ts +579 -0
  162. package/src/plugins/registry.ts +402 -0
  163. package/src/plugins/types.ts +46 -0
  164. package/src/post/effects.ts +948 -0
  165. package/src/post/filters.ts +512 -0
  166. package/src/post/matrices.ts +288 -0
  167. package/src/renderables/ASCIIFont.ts +219 -0
  168. package/src/renderables/Box.test.ts +474 -0
  169. package/src/renderables/Box.ts +353 -0
  170. package/src/renderables/Code.test.ts +2388 -0
  171. package/src/renderables/Code.ts +555 -0
  172. package/src/renderables/Diff.regression.test.ts +381 -0
  173. package/src/renderables/Diff.test.ts +3212 -0
  174. package/src/renderables/Diff.ts +1278 -0
  175. package/src/renderables/EditBufferRenderable.test.ts +288 -0
  176. package/src/renderables/EditBufferRenderable.ts +1152 -0
  177. package/src/renderables/FrameBuffer.ts +47 -0
  178. package/src/renderables/Input.test.ts +1310 -0
  179. package/src/renderables/Input.ts +273 -0
  180. package/src/renderables/LineNumberRenderable.ts +725 -0
  181. package/src/renderables/Markdown.ts +2144 -0
  182. package/src/renderables/ScrollBar.ts +423 -0
  183. package/src/renderables/ScrollBox.ts +903 -0
  184. package/src/renderables/Select.test.ts +1134 -0
  185. package/src/renderables/Select.ts +535 -0
  186. package/src/renderables/Slider.test.ts +456 -0
  187. package/src/renderables/Slider.ts +342 -0
  188. package/src/renderables/TabSelect.test.ts +238 -0
  189. package/src/renderables/TabSelect.ts +447 -0
  190. package/src/renderables/Text.selection-buffer.test.ts +118 -0
  191. package/src/renderables/Text.test.ts +2662 -0
  192. package/src/renderables/Text.ts +147 -0
  193. package/src/renderables/TextBufferRenderable.ts +504 -0
  194. package/src/renderables/TextNode.test.ts +1137 -0
  195. package/src/renderables/TextNode.ts +379 -0
  196. package/src/renderables/TextTable.test.ts +1411 -0
  197. package/src/renderables/TextTable.ts +1434 -0
  198. package/src/renderables/Textarea.ts +425 -0
  199. package/src/renderables/TimeToFirstDraw.ts +89 -0
  200. package/src/renderables/__snapshots__/Code.test.ts.snap +13 -0
  201. package/src/renderables/__snapshots__/Diff.test.ts.snap +785 -0
  202. package/src/renderables/__snapshots__/Text.test.ts.snap +421 -0
  203. package/src/renderables/__snapshots__/TextTable.test.ts.snap +215 -0
  204. package/src/renderables/__tests__/Code.test.ts +55 -0
  205. package/src/renderables/__tests__/LineNumberRenderable.scrollbox-simple.test.ts +144 -0
  206. package/src/renderables/__tests__/LineNumberRenderable.scrollbox.test.ts +827 -0
  207. package/src/renderables/__tests__/LineNumberRenderable.test.ts +1906 -0
  208. package/src/renderables/__tests__/LineNumberRenderable.wrapping.test.ts +85 -0
  209. package/src/renderables/__tests__/Markdown.code-colors.test.ts +288 -0
  210. package/src/renderables/__tests__/Markdown.test.ts +4175 -0
  211. package/src/renderables/__tests__/MultiRenderable.selection.test.ts +87 -0
  212. package/src/renderables/__tests__/Textarea.buffer.test.ts +683 -0
  213. package/src/renderables/__tests__/Textarea.destroyed-events.test.ts +675 -0
  214. package/src/renderables/__tests__/Textarea.editing.test.ts +2120 -0
  215. package/src/renderables/__tests__/Textarea.error-handling.test.ts +35 -0
  216. package/src/renderables/__tests__/Textarea.events.test.ts +738 -0
  217. package/src/renderables/__tests__/Textarea.highlights.test.ts +590 -0
  218. package/src/renderables/__tests__/Textarea.keybinding.test.ts +3275 -0
  219. package/src/renderables/__tests__/Textarea.paste.test.ts +357 -0
  220. package/src/renderables/__tests__/Textarea.rendering.test.ts +1927 -0
  221. package/src/renderables/__tests__/Textarea.scroll.test.ts +733 -0
  222. package/src/renderables/__tests__/Textarea.selection.test.ts +1589 -0
  223. package/src/renderables/__tests__/Textarea.stress.test.ts +670 -0
  224. package/src/renderables/__tests__/Textarea.undo-redo.test.ts +383 -0
  225. package/src/renderables/__tests__/Textarea.visual-lines.test.ts +310 -0
  226. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.code.test.ts.snap +221 -0
  227. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox-simple.test.ts.snap +89 -0
  228. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox.test.ts.snap +457 -0
  229. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.test.ts.snap +158 -0
  230. package/src/renderables/__tests__/__snapshots__/Textarea.rendering.test.ts.snap +387 -0
  231. package/src/renderables/__tests__/markdown-parser.test.ts +241 -0
  232. package/src/renderables/__tests__/renderable-test-utils.ts +60 -0
  233. package/src/renderables/composition/README.md +8 -0
  234. package/src/renderables/composition/VRenderable.ts +32 -0
  235. package/src/renderables/composition/constructs.ts +127 -0
  236. package/src/renderables/composition/vnode.ts +277 -0
  237. package/src/renderables/index.ts +23 -0
  238. package/src/renderables/markdown-parser.ts +79 -0
  239. package/src/renderer-theme-mode.ts +199 -0
  240. package/src/renderer.ts +4975 -0
  241. package/src/runtime-plugin-support-configure.ts +63 -0
  242. package/src/runtime-plugin-support.ts +13 -0
  243. package/src/runtime-plugin.ts +626 -0
  244. package/src/specs/terminal-startup.md +64 -0
  245. package/src/syntax-style.test.ts +841 -0
  246. package/src/syntax-style.ts +274 -0
  247. package/src/testing/README.md +219 -0
  248. package/src/testing/bun-test-node.ts +880 -0
  249. package/src/testing/capture-spans.test.ts +216 -0
  250. package/src/testing/integration.test.ts +276 -0
  251. package/src/testing/manual-clock.ts +117 -0
  252. package/src/testing/mock-keys.test.ts +1378 -0
  253. package/src/testing/mock-keys.ts +457 -0
  254. package/src/testing/mock-mouse.test.ts +218 -0
  255. package/src/testing/mock-mouse.ts +247 -0
  256. package/src/testing/mock-tree-sitter-client.ts +81 -0
  257. package/src/testing/spy.ts +13 -0
  258. package/src/testing/terminal-capabilities.ts +47 -0
  259. package/src/testing/test-recorder.test.ts +410 -0
  260. package/src/testing/test-recorder.ts +133 -0
  261. package/src/testing/test-renderer.ts +375 -0
  262. package/src/testing/test-renderer.wait.test.ts +278 -0
  263. package/src/testing/test-streams.ts +31 -0
  264. package/src/testing.ts +9 -0
  265. package/src/tests/__snapshots__/absolute-positioning.snapshot.test.ts.snap +481 -0
  266. package/src/tests/__snapshots__/renderable.snapshot.test.ts.snap +19 -0
  267. package/src/tests/__snapshots__/scrollbox.test.ts.snap +29 -0
  268. package/src/tests/absolute-positioning.snapshot.test.ts +638 -0
  269. package/src/tests/allocator-stats.test.ts +53 -0
  270. package/src/tests/audio.test.ts +303 -0
  271. package/src/tests/destroy-during-render.test.ts +200 -0
  272. package/src/tests/destroy-on-exit.fixture.ts +36 -0
  273. package/src/tests/destroy-on-exit.test.ts +62 -0
  274. package/src/tests/ffi-borrowed-pointer-callsites.test.ts +153 -0
  275. package/src/tests/hover-cursor.test.ts +98 -0
  276. package/src/tests/native-backed-measurement-lifecycle.test.ts +133 -0
  277. package/src/tests/native-backed-measurement-parity.test.ts +322 -0
  278. package/src/tests/native-span-feed-async.test.ts +173 -0
  279. package/src/tests/native-span-feed-close.test.ts +120 -0
  280. package/src/tests/native-span-feed-coverage.test.ts +227 -0
  281. package/src/tests/native-span-feed-edge-cases.test.ts +384 -0
  282. package/src/tests/native-span-feed-use-after-free.test.ts +45 -0
  283. package/src/tests/opacity.test.ts +123 -0
  284. package/src/tests/renderable.snapshot.test.ts +524 -0
  285. package/src/tests/renderable.test.ts +1851 -0
  286. package/src/tests/renderer.clock.test.ts +270 -0
  287. package/src/tests/renderer.console-startup.test.ts +2151 -0
  288. package/src/tests/renderer.control.test.ts +458 -0
  289. package/src/tests/renderer.core-slot-binding.test.ts +962 -0
  290. package/src/tests/renderer.cursor.test.ts +26 -0
  291. package/src/tests/renderer.custom-stdout.test.ts +1112 -0
  292. package/src/tests/renderer.destroy-during-render.test.ts +147 -0
  293. package/src/tests/renderer.focus-restore.test.ts +257 -0
  294. package/src/tests/renderer.focus.test.ts +329 -0
  295. package/src/tests/renderer.idle.test.ts +219 -0
  296. package/src/tests/renderer.input.test.ts +2615 -0
  297. package/src/tests/renderer.kitty-flags.test.ts +195 -0
  298. package/src/tests/renderer.lifecycle.test.ts +34 -0
  299. package/src/tests/renderer.mouse.test.ts +1315 -0
  300. package/src/tests/renderer.notifications.test.ts +27 -0
  301. package/src/tests/renderer.palette.test.ts +1199 -0
  302. package/src/tests/renderer.remote.test.ts +247 -0
  303. package/src/tests/renderer.render-stats.test.ts +146 -0
  304. package/src/tests/renderer.scrollback-surface.test.ts +474 -0
  305. package/src/tests/renderer.selection.test.ts +138 -0
  306. package/src/tests/renderer.slot-registry.test.ts +684 -0
  307. package/src/tests/renderer.tracker.test.ts +202 -0
  308. package/src/tests/renderer.useMouse.test.ts +83 -0
  309. package/src/tests/runtime-plugin-node-modules-cycle.fixture.ts +76 -0
  310. package/src/tests/runtime-plugin-node-modules-import-like-string.fixture.ts +48 -0
  311. package/src/tests/runtime-plugin-node-modules-mjs.fixture.ts +43 -0
  312. package/src/tests/runtime-plugin-node-modules-no-bare-rewrite.fixture.ts +67 -0
  313. package/src/tests/runtime-plugin-node-modules-package-type-cache.fixture.ts +72 -0
  314. package/src/tests/runtime-plugin-node-modules-runtime-specifier.fixture.ts +44 -0
  315. package/src/tests/runtime-plugin-node-modules-scoped-package-bare-rewrite.fixture.ts +85 -0
  316. package/src/tests/runtime-plugin-path-alias.fixture.ts +43 -0
  317. package/src/tests/runtime-plugin-resolve-roots.fixture.ts +65 -0
  318. package/src/tests/runtime-plugin-support-configure.fixture.ts +31 -0
  319. package/src/tests/runtime-plugin-support-late-addition.fixture.ts +17 -0
  320. package/src/tests/runtime-plugin-support.fixture.ts +11 -0
  321. package/src/tests/runtime-plugin-support.test.ts +54 -0
  322. package/src/tests/runtime-plugin-windows-file-url.fixture.ts +30 -0
  323. package/src/tests/runtime-plugin.fixture.ts +40 -0
  324. package/src/tests/runtime-plugin.test.ts +369 -0
  325. package/src/tests/scrollbox-culling-bug.test.ts +114 -0
  326. package/src/tests/scrollbox-hitgrid-resize.test.ts +136 -0
  327. package/src/tests/scrollbox-hitgrid.test.ts +909 -0
  328. package/src/tests/scrollbox.test.ts +1895 -0
  329. package/src/tests/wrap-resize-perf.test.ts +276 -0
  330. package/src/tests/yoga-api-coverage.test.ts +409 -0
  331. package/src/tests/yoga-callback-stress.test.ts +122 -0
  332. package/src/tests/yoga-ffi.test.ts +117 -0
  333. package/src/tests/yoga-setters.test.ts +921 -0
  334. package/src/tests/yoga-upstream/YGAlignBaselineTest.test.ts +124 -0
  335. package/src/tests/yoga-upstream/YGComputedBorderTest.test.ts +27 -0
  336. package/src/tests/yoga-upstream/YGComputedMarginTest.test.ts +27 -0
  337. package/src/tests/yoga-upstream/YGComputedPaddingTest.test.ts +27 -0
  338. package/src/tests/yoga-upstream/YGDirtiedTest.test.ts +157 -0
  339. package/src/tests/yoga-upstream/YGErrataTest.test.ts +40 -0
  340. package/src/tests/yoga-upstream/YGFlexBasisAuto.test.ts +23 -0
  341. package/src/tests/yoga-upstream/YGHasNewLayout.test.ts +81 -0
  342. package/src/tests/yoga-upstream/YGMeasureCacheTest.test.ts +31 -0
  343. package/src/tests/yoga-upstream/YGMeasureTest.test.ts +70 -0
  344. package/src/tests/yoga-upstream/generated/YGAbsolutePositionTest.test.ts +1864 -0
  345. package/src/tests/yoga-upstream/generated/YGAlignContentTest.test.ts +5829 -0
  346. package/src/tests/yoga-upstream/generated/YGAlignItemsTest.test.ts +2444 -0
  347. package/src/tests/yoga-upstream/generated/YGAlignSelfTest.test.ts +293 -0
  348. package/src/tests/yoga-upstream/generated/YGAndroidNewsFeed.test.ts +315 -0
  349. package/src/tests/yoga-upstream/generated/YGAspectRatioTest.test.ts +231 -0
  350. package/src/tests/yoga-upstream/generated/YGAutoTest.test.ts +347 -0
  351. package/src/tests/yoga-upstream/generated/YGBorderTest.test.ts +256 -0
  352. package/src/tests/yoga-upstream/generated/YGBoxSizingTest.test.ts +2747 -0
  353. package/src/tests/yoga-upstream/generated/YGDimensionTest.test.ts +129 -0
  354. package/src/tests/yoga-upstream/generated/YGDisplayContentsTest.test.ts +109 -0
  355. package/src/tests/yoga-upstream/generated/YGDisplayTest.test.ts +1097 -0
  356. package/src/tests/yoga-upstream/generated/YGFlexDirectionTest.test.ts +4562 -0
  357. package/src/tests/yoga-upstream/generated/YGFlexTest.test.ts +677 -0
  358. package/src/tests/yoga-upstream/generated/YGFlexWrapTest.test.ts +2071 -0
  359. package/src/tests/yoga-upstream/generated/YGGapTest.test.ts +3303 -0
  360. package/src/tests/yoga-upstream/generated/YGIntrinsicSizeTest.test.ts +582 -0
  361. package/src/tests/yoga-upstream/generated/YGJustifyContentTest.test.ts +2150 -0
  362. package/src/tests/yoga-upstream/generated/YGMarginTest.test.ts +1963 -0
  363. package/src/tests/yoga-upstream/generated/YGMinMaxDimensionTest.test.ts +1446 -0
  364. package/src/tests/yoga-upstream/generated/YGPaddingTest.test.ts +354 -0
  365. package/src/tests/yoga-upstream/generated/YGPercentageTest.test.ts +1760 -0
  366. package/src/tests/yoga-upstream/generated/YGRoundingTest.test.ts +1161 -0
  367. package/src/tests/yoga-upstream/generated/YGSizeOverflowTest.test.ts +207 -0
  368. package/src/tests/yoga-upstream/generated/YGStaticPositionTest.test.ts +6338 -0
  369. package/src/tests/yoga-upstream/tools/MeasureCounter.ts +54 -0
  370. package/src/tests/yoga-upstream/tools/utils.ts +81 -0
  371. package/src/text-buffer-view.test.ts +722 -0
  372. package/src/text-buffer-view.ts +193 -0
  373. package/src/text-buffer.test.ts +512 -0
  374. package/src/text-buffer.ts +250 -0
  375. package/src/types.ts +199 -0
  376. package/src/utils.ts +88 -0
  377. package/src/yoga.ts +1146 -0
  378. package/src/zig/ansi.zig +502 -0
  379. package/src/zig/audio.zig +1206 -0
  380. package/src/zig/bench/README.md +50 -0
  381. package/src/zig/bench/buffer-color-blending_bench.zig +350 -0
  382. package/src/zig/bench/buffer-draw-box_bench.zig +786 -0
  383. package/src/zig/bench/buffer-draw-text-buffer_bench.zig +894 -0
  384. package/src/zig/bench/edit-buffer_bench.zig +476 -0
  385. package/src/zig/bench/editor-view_bench.zig +169 -0
  386. package/src/zig/bench/native-span-feed_bench.zig +107 -0
  387. package/src/zig/bench/rope-markers_bench.zig +713 -0
  388. package/src/zig/bench/rope_bench.zig +514 -0
  389. package/src/zig/bench/styled-text_bench.zig +476 -0
  390. package/src/zig/bench/text-buffer-coords_bench.zig +362 -0
  391. package/src/zig/bench/text-buffer-view_bench.zig +459 -0
  392. package/src/zig/bench/text-chunk-graphemes_bench.zig +272 -0
  393. package/src/zig/bench/utf8_bench.zig +799 -0
  394. package/src/zig/bench-utils.zig +431 -0
  395. package/src/zig/bench.zig +223 -0
  396. package/src/zig/buffer-methods.zig +215 -0
  397. package/src/zig/buffer.zig +2515 -0
  398. package/src/zig/build.zig +700 -0
  399. package/src/zig/build.zig.zon +19 -0
  400. package/src/zig/edit-buffer.zig +900 -0
  401. package/src/zig/editor-view.zig +812 -0
  402. package/src/zig/event-bus.zig +28 -0
  403. package/src/zig/event-emitter.zig +65 -0
  404. package/src/zig/file-logger.zig +92 -0
  405. package/src/zig/grapheme.zig +838 -0
  406. package/src/zig/handles.zig +267 -0
  407. package/src/zig/lib.zig +2813 -0
  408. package/src/zig/link.zig +349 -0
  409. package/src/zig/logger.zig +43 -0
  410. package/src/zig/mem-registry.zig +126 -0
  411. package/src/zig/miniaudio_shim.c +21 -0
  412. package/src/zig/native-renderable.zig +112 -0
  413. package/src/zig/native-span-feed-bench-lib.zig +7 -0
  414. package/src/zig/native-span-feed.zig +747 -0
  415. package/src/zig/renderer-output.zig +677 -0
  416. package/src/zig/renderer.zig +2106 -0
  417. package/src/zig/rope.zig +1220 -0
  418. package/src/zig/split-scrollback.zig +88 -0
  419. package/src/zig/syntax-style.zig +174 -0
  420. package/src/zig/terminal.zig +1652 -0
  421. package/src/zig/test.zig +82 -0
  422. package/src/zig/tests/README.md +18 -0
  423. package/src/zig/tests/ansi_test.zig +18 -0
  424. package/src/zig/tests/audio_test.zig +439 -0
  425. package/src/zig/tests/buffer-methods_test.zig +1111 -0
  426. package/src/zig/tests/buffer_test.zig +2926 -0
  427. package/src/zig/tests/edit-buffer-history_test.zig +299 -0
  428. package/src/zig/tests/edit-buffer_test.zig +1688 -0
  429. package/src/zig/tests/editor-view_test.zig +3454 -0
  430. package/src/zig/tests/event-emitter_test.zig +249 -0
  431. package/src/zig/tests/grapheme_test.zig +1329 -0
  432. package/src/zig/tests/handles_test.zig +123 -0
  433. package/src/zig/tests/link_test.zig +220 -0
  434. package/src/zig/tests/mem-registry_test.zig +473 -0
  435. package/src/zig/tests/memory_leak_regression_test.zig +234 -0
  436. package/src/zig/tests/native-renderable_test.zig +16 -0
  437. package/src/zig/tests/native-span-feed_test.zig +1266 -0
  438. package/src/zig/tests/renderer_test.zig +2604 -0
  439. package/src/zig/tests/rope-nested_test.zig +712 -0
  440. package/src/zig/tests/rope_fuzz_test.zig +238 -0
  441. package/src/zig/tests/rope_test.zig +2362 -0
  442. package/src/zig/tests/segment-merge.test.zig +148 -0
  443. package/src/zig/tests/split-scrollback_test.zig +70 -0
  444. package/src/zig/tests/syntax-style_test.zig +558 -0
  445. package/src/zig/tests/terminal_test.zig +1489 -0
  446. package/src/zig/tests/test-renderer.zig +126 -0
  447. package/src/zig/tests/text-buffer-drawing_test.zig +3291 -0
  448. package/src/zig/tests/text-buffer-highlights_test.zig +706 -0
  449. package/src/zig/tests/text-buffer-iterators_test.zig +776 -0
  450. package/src/zig/tests/text-buffer-segment_test.zig +320 -0
  451. package/src/zig/tests/text-buffer-selection_test.zig +1056 -0
  452. package/src/zig/tests/text-buffer-selection_viewport_test.zig +358 -0
  453. package/src/zig/tests/text-buffer-view_test.zig +3672 -0
  454. package/src/zig/tests/text-buffer_test.zig +2191 -0
  455. package/src/zig/tests/unicode-width-map.zon +3909 -0
  456. package/src/zig/tests/utf8_no_zwj_test.zig +260 -0
  457. package/src/zig/tests/utf8_test.zig +4060 -0
  458. package/src/zig/tests/utf8_wcwidth_cursor_test.zig +267 -0
  459. package/src/zig/tests/utf8_wcwidth_test.zig +357 -0
  460. package/src/zig/tests/word-wrap-editing_test.zig +498 -0
  461. package/src/zig/tests/wrap-cache-perf_test.zig +113 -0
  462. package/src/zig/tests/yoga_test.zig +65 -0
  463. package/src/zig/text-buffer-iterators.zig +496 -0
  464. package/src/zig/text-buffer-segment.zig +403 -0
  465. package/src/zig/text-buffer-view.zig +1428 -0
  466. package/src/zig/text-buffer.zig +1272 -0
  467. package/src/zig/utf8.zig +1954 -0
  468. package/src/zig/utils.zig +12 -0
  469. package/src/zig/uucode-stub.zig +76 -0
  470. package/src/zig/vendor/miniaudio/miniaudio.h +93468 -0
  471. package/src/zig/yoga.zig +658 -0
  472. package/src/zig-structs.ts +381 -0
  473. package/src/zig.ts +5260 -0
  474. package/tsconfig.build.json +17 -0
  475. package/tsconfig.json +27 -0
  476. package/tsconfig.node-test.json +138 -0
package/README.md ADDED
@@ -0,0 +1,63 @@
1
+ # OpenTUI Core
2
+
3
+ OpenTUI is a native terminal UI core written in Zig with TypeScript bindings. The native core exposes a C ABI and can be used from any language. OpenTUI powers OpenCode in production today and will also power terminal.shop. It is an extensible core with a focus on correctness, stability, and high performance. It provides a component-based architecture with flexible layout capabilities, allowing you to create complex terminal applications.
4
+
5
+ ## Documentation
6
+
7
+ - [Getting Started](docs/getting-started.md) - API and usage guide
8
+ - [Development Guide](docs/development.md) - Building, testing, and contributing
9
+ - [Tree-Sitter](docs/tree-sitter.md) - Syntax highlighting integration
10
+ - [Renderables vs Constructs](docs/renderables-vs-constructs.md) - Understanding the component model
11
+ - [Environment Variables](docs/env-vars.md) - Configuration options
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ bun install @opentui/core
17
+ ```
18
+
19
+ ## Build
20
+
21
+ ```bash
22
+ bun run build
23
+ ```
24
+
25
+ This creates platform-specific libraries that are automatically loaded by the TypeScript layer.
26
+
27
+ ## Examples
28
+
29
+ ```bash
30
+ bun install
31
+ cd ../examples
32
+ bun run dev
33
+ ```
34
+
35
+ ## Benchmarks
36
+
37
+ Run native performance benchmarks:
38
+
39
+ ```bash
40
+ bun run bench:native
41
+ ```
42
+
43
+ See [src/zig/bench.zig](src/zig/bench.zig) for available options like `--filter` and `--mem`.
44
+
45
+ NativeSpanFeed TypeScript benchmarks:
46
+
47
+ - [src/benchmark/native-span-feed-benchmark.md](src/benchmark/native-span-feed-benchmark.md)
48
+
49
+ ## CLI Renderer
50
+
51
+ ### Renderables
52
+
53
+ Renderables are hierarchical objects that can be positioned, nested, styled and rendered to the terminal:
54
+
55
+ ```typescript
56
+ import { createCliRenderer, TextRenderable } from "@opentui/core"
57
+
58
+ const renderer = await createCliRenderer()
59
+
60
+ const obj = new TextRenderable(renderer, { id: "my-obj", content: "Hello, world!" })
61
+
62
+ renderer.root.add(obj)
63
+ ```
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env bun
2
+ import { BoxRenderable, type CliRenderer, createCliRenderer, CodeRenderable, addDefaultParsers } from "../src/index.js"
3
+ import { ScrollBoxRenderable } from "../src/renderables/ScrollBox.js"
4
+ import { SyntaxStyle } from "../src/syntax-style.js"
5
+ import { parseColor } from "../src/lib/RGBA.js"
6
+
7
+ const parsers = [
8
+ {
9
+ filetype: "json",
10
+ wasm: "https://github.com/tree-sitter/tree-sitter-json/releases/download/v0.24.8/tree-sitter-json.wasm",
11
+ queries: {
12
+ highlights: [
13
+ "https://raw.githubusercontent.com/nvim-treesitter/nvim-treesitter/refs/heads/master/queries/json/highlights.scm",
14
+ ],
15
+ },
16
+ },
17
+ ]
18
+ addDefaultParsers(parsers)
19
+ let scrollBox: ScrollBoxRenderable | null = null
20
+ let renderer: CliRenderer | null = null
21
+ let syntaxStyle: SyntaxStyle | null = null
22
+ let eventCount = 0
23
+
24
+ function addEvent(eventType: string, event: object) {
25
+ if (!renderer || !scrollBox || !syntaxStyle) return
26
+
27
+ eventCount++
28
+
29
+ const eventData = {
30
+ type: eventType,
31
+ timestamp: new Date().toISOString(),
32
+ ...event,
33
+ }
34
+
35
+ const eventBox = new BoxRenderable(renderer, {
36
+ id: `event-${eventCount}`,
37
+ width: "auto",
38
+ marginBottom: 1,
39
+ padding: 1,
40
+ backgroundColor: "#1f2937",
41
+ })
42
+
43
+ const codeDisplay = new CodeRenderable(renderer, {
44
+ id: `event-code-${eventCount}`,
45
+ content: JSON.stringify(eventData, null, 2),
46
+ filetype: "json",
47
+ conceal: false,
48
+ syntaxStyle,
49
+ bg: "#1f2937",
50
+ })
51
+
52
+ eventBox.add(codeDisplay)
53
+ scrollBox.add(eventBox)
54
+
55
+ const children = scrollBox.getChildren()
56
+ if (children.length > 50) {
57
+ const oldest = children[0]
58
+ if (oldest) {
59
+ scrollBox.remove(oldest)
60
+ oldest.destroyRecursively()
61
+ }
62
+ }
63
+ }
64
+
65
+ async function main() {
66
+ const usePrepend = process.argv.includes("--prepend")
67
+ const prependInputHandlers = usePrepend
68
+ ? [
69
+ (sequence: string) => {
70
+ addEvent("raw-input-before", { sequence })
71
+ return false
72
+ },
73
+ ]
74
+ : []
75
+ renderer = await createCliRenderer({
76
+ exitOnCtrlC: true,
77
+ targetFps: 60,
78
+ useKittyKeyboard: { events: true },
79
+ prependInputHandlers,
80
+ })
81
+
82
+ renderer.setBackgroundColor("#0D1117")
83
+
84
+ const mainContainer = new BoxRenderable(renderer, {
85
+ id: "main-container",
86
+ flexGrow: 1,
87
+ flexDirection: "column",
88
+ })
89
+
90
+ renderer.root.add(mainContainer)
91
+
92
+ scrollBox = new ScrollBoxRenderable(renderer, {
93
+ id: "event-scroll-box",
94
+ stickyScroll: true,
95
+ stickyStart: "bottom",
96
+ border: true,
97
+ borderColor: "#6BCF7F",
98
+ title: `Keypress Debug${usePrepend ? " (prepend mode)" : ""} (Ctrl+C to exit)`,
99
+ titleAlignment: "center",
100
+ contentOptions: {
101
+ paddingLeft: 1,
102
+ paddingRight: 1,
103
+ paddingTop: 1,
104
+ },
105
+ })
106
+
107
+ mainContainer.add(scrollBox)
108
+
109
+ syntaxStyle = SyntaxStyle.fromStyles({
110
+ string: { fg: parseColor("#A5D6FF") },
111
+ number: { fg: parseColor("#79C0FF") },
112
+ boolean: { fg: parseColor("#79C0FF") },
113
+ keyword: { fg: parseColor("#FF7B72") },
114
+ default: { fg: parseColor("#E6EDF3") },
115
+ })
116
+
117
+ addEvent("capabilities", renderer.capabilities)
118
+
119
+ renderer.addInputHandler((sequence) => {
120
+ addEvent("raw-input-after", { sequence })
121
+ return true
122
+ })
123
+
124
+ renderer.keyInput.on("keypress", (event) => {
125
+ addEvent("keypress", event)
126
+
127
+ if (event.name === "c" && event.shift) {
128
+ if (renderer) {
129
+ addEvent("capabilities", renderer.capabilities)
130
+ }
131
+ }
132
+ })
133
+
134
+ renderer.keyInput.on("keyrelease", (event) => {
135
+ addEvent("keyrelease", event)
136
+ })
137
+
138
+ renderer.keyInput.on("paste", (event) => {
139
+ addEvent("paste", event)
140
+ })
141
+
142
+ renderer.requestRender()
143
+ }
144
+
145
+ main().catch((err) => {
146
+ console.error("Error:", err)
147
+ process.exit(1)
148
+ })
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env bun
2
+ import { parseKeypress } from "../src/lib/parse.keypress.ts"
3
+
4
+ console.log("Keypress Debug Tool")
5
+ console.log("Press keys to see their parsed output. Press Ctrl+C to exit.\n")
6
+
7
+ // Set stdin to raw mode to capture individual keypresses
8
+ process.stdin.setRawMode(true)
9
+ process.stdin.resume()
10
+
11
+ // Listen for keypress data
12
+ process.stdin.on("data", (data: Buffer) => {
13
+ // Check for Ctrl+C to exit
14
+ if (data.toString() === "\x03") {
15
+ console.log("\nExiting keypress debug tool...")
16
+ process.stdin.setRawMode(false)
17
+ process.exit(0)
18
+ }
19
+
20
+ const parsed = parseKeypress(data)
21
+
22
+ console.log("Input data:", JSON.stringify(data.toString()))
23
+ console.log("Raw:", JSON.stringify(parsed?.raw))
24
+ console.log("Parsed:", {
25
+ name: parsed?.name,
26
+ ctrl: parsed?.ctrl,
27
+ meta: parsed?.meta,
28
+ shift: parsed?.shift,
29
+ option: parsed?.option,
30
+ number: parsed?.number,
31
+ sequence: parsed?.sequence,
32
+ code: parsed?.code,
33
+ buffer: data,
34
+ })
35
+ console.log("---")
36
+ })
37
+
38
+ // Handle Ctrl+C gracefully
39
+ process.on("SIGINT", () => {
40
+ console.log("\nExiting keypress debug tool...")
41
+ process.stdin.setRawMode(false)
42
+ process.exit(0)
43
+ })
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env bun
2
+
3
+ /**
4
+ * Development script to print all registered environment variables
5
+ *
6
+ * Usage:
7
+ * bun dev/print-env-vars.ts # Colored output (default)
8
+ * bun dev/print-env-vars.ts --markdown # Markdown output
9
+ * bun dev/print-env-vars.ts --update # Update docs/env-vars.md
10
+ */
11
+
12
+ import { generateEnvColored, generateEnvMarkdown } from "../src/index.js"
13
+ import { join } from "path"
14
+
15
+ const args = process.argv.slice(2)
16
+ const useMarkdown = args.includes("--markdown")
17
+ const updateDocs = args.includes("--update")
18
+
19
+ const generateMarkdownContent = () => {
20
+ return `# Environment Variables\n\n${generateEnvMarkdown()}---\n\n_generated via packages/core/dev/print-env-vars.ts_\n`
21
+ }
22
+
23
+ if (updateDocs) {
24
+ const docsPath = join(import.meta.dir, "../docs/env-vars.md")
25
+ const content = generateMarkdownContent()
26
+ await Bun.write(docsPath, content)
27
+ console.log(`✓ Updated ${docsPath}`)
28
+ } else if (useMarkdown) {
29
+ console.log(`${generateEnvMarkdown()}\n---\n_generated via packages/core/dev/print-env-vars.ts_`)
30
+ } else {
31
+ console.log(generateEnvColored())
32
+ }
@@ -0,0 +1,68 @@
1
+ #!/bin/bash
2
+ # Test script for issue #334: Kitty Graphics Protocol query leaks into tmux pane title
3
+ #
4
+ # This script verifies that the kitty graphics query doesn't corrupt tmux pane titles.
5
+ # Run this inside tmux to test.
6
+ #
7
+ # Usage: ./test-tmux-graphics-334.sh
8
+ #
9
+ # Expected results:
10
+ # - Test 1 (Direct query): FAIL - demonstrates the bug
11
+ # - Test 2 (DCS passthrough): PASS - demonstrates the fix
12
+ # - Test 3 (No query): PASS - control test
13
+
14
+ set -e
15
+
16
+ SESSION_NAME="opentui-test-334-$$"
17
+ EXPECTED_TITLE="test-title"
18
+
19
+ cleanup() {
20
+ tmux kill-session -t "$SESSION_NAME" 2>/dev/null || true
21
+ }
22
+ trap cleanup EXIT
23
+
24
+ run_test() {
25
+ local test_name="$1"
26
+ local query_cmd="$2"
27
+
28
+ cleanup
29
+ tmux new-session -d -s "$SESSION_NAME" -x 80 -y 24
30
+ tmux select-pane -t "$SESSION_NAME" -T "$EXPECTED_TITLE"
31
+
32
+ if [ -n "$query_cmd" ]; then
33
+ tmux send-keys -t "$SESSION_NAME" "$query_cmd" Enter
34
+ sleep 0.5
35
+ fi
36
+
37
+ local after_title
38
+ after_title=$(tmux display-message -t "$SESSION_NAME" -p '#{pane_title}')
39
+
40
+ if [[ "$after_title" == *"Gi=31337"* ]] || [[ "$after_title" == *"i=31337"* ]]; then
41
+ echo "FAIL: $test_name - pane title corrupted: '$after_title'"
42
+ return 1
43
+ elif [[ "$after_title" != "$EXPECTED_TITLE" ]]; then
44
+ echo "WARN: $test_name - pane title changed: '$after_title'"
45
+ return 1
46
+ else
47
+ echo "PASS: $test_name"
48
+ return 0
49
+ fi
50
+ }
51
+
52
+ echo "=== Issue #334 Test: Kitty Graphics Query in tmux ==="
53
+ echo "tmux version: $(tmux -V)"
54
+ echo ""
55
+
56
+ echo "Test 1: Direct query (demonstrates bug)"
57
+ run_test "Direct kitty graphics query" \
58
+ "printf '\\x1b_Gi=31337,s=1,v=1,a=q,t=d,f=24;AAAA\\x1b\\\\\\x1b[c'" || true
59
+
60
+ echo "Test 2: DCS passthrough wrapped query (demonstrates fix)"
61
+ run_test "DCS passthrough wrapped" \
62
+ "printf '\\x1bPtmux;\\x1b\\x1b_Gi=31337,s=1,v=1,a=q,t=d,f=24;AAAA\\x1b\\x1b\\\\\\x1b\\x1b[c\\x1b\\\\'"
63
+
64
+ echo "Test 3: No query (control)"
65
+ run_test "No query" ""
66
+
67
+ echo ""
68
+ echo "If Test 1 fails and Test 2 passes, the fix is working correctly."
@@ -0,0 +1,151 @@
1
+ #!/bin/bash
2
+ # Probe theme-related terminal queries inside and outside tmux.
3
+ #
4
+ # Run this in the pane you want to test. It writes queries directly to /dev/tty,
5
+ # captures any replies, and prints both an escaped representation and raw hex.
6
+ #
7
+ # Usage:
8
+ # ./packages/core/dev/test-tmux-theme-queries.sh
9
+
10
+ set -u
11
+ set -o pipefail
12
+
13
+ LC_ALL=C
14
+
15
+ ESC=$'\033'
16
+ BEL=$'\a'
17
+ ST="${ESC}\\"
18
+ LOG_FILE="${LOG_FILE:-./_tmux_theme_query_$(date +%s).log}"
19
+
20
+ exec 3<> /dev/tty
21
+
22
+ ORIGINAL_STTY="$(stty -g <&3)"
23
+
24
+ cleanup() {
25
+ stty "$ORIGINAL_STTY" <&3 2>/dev/null || true
26
+ exec 3>&- 3<&-
27
+ }
28
+
29
+ interrupt() {
30
+ cleanup
31
+ exit 130
32
+ }
33
+
34
+ trap cleanup EXIT
35
+ trap interrupt INT TERM
36
+
37
+ READ_GAP_TENTHS="${READ_GAP_TENTHS:-4}"
38
+
39
+ stty -echo -icanon min 0 time "$READ_GAP_TENTHS" <&3
40
+
41
+ tmux_wrap() {
42
+ local payload="$1"
43
+ payload=${payload//$ESC/$ESC$ESC}
44
+ printf '%s' "${ESC}Ptmux;${payload}${ST}"
45
+ }
46
+
47
+ escape_for_display() {
48
+ local value="$1"
49
+ value=${value//$ESC/\\e}
50
+ value=${value//$BEL/\\a}
51
+ value=${value//$'\r'/\\r}
52
+ value=${value//$'\n'/\\n$'\n'}
53
+ value=${value//$'\t'/\\t}
54
+ printf '%s' "$value"
55
+ }
56
+
57
+ hex_dump() {
58
+ if [ -z "$1" ]; then
59
+ printf '(none)\n'
60
+ return
61
+ fi
62
+
63
+ printf '%s' "$1" | od -An -tx1 -v | tr -s ' ' | sed 's/^ //'
64
+ }
65
+
66
+ read_until_gap() {
67
+ local response=""
68
+ local chunk=""
69
+
70
+ while true; do
71
+ chunk="$(dd bs=1 count=1 2>/dev/null <&3)"
72
+ if [ -z "$chunk" ]; then
73
+ break
74
+ fi
75
+ response+="$chunk"
76
+ done
77
+
78
+ printf '%s' "$response"
79
+ }
80
+
81
+ drain_input() {
82
+ local drained=""
83
+ drained="$(read_until_gap)"
84
+ if [ -n "$drained" ]; then
85
+ printf 'Drained pending input before next test.\n' | tee -a "$LOG_FILE"
86
+ printf ' escaped: %s\n' "$(escape_for_display "$drained")" | tee -a "$LOG_FILE"
87
+ printf ' hex: %s\n' "$(hex_dump "$drained")" | tee -a "$LOG_FILE"
88
+ fi
89
+ }
90
+
91
+ run_case() {
92
+ local name="$1"
93
+ local payload="$2"
94
+ local response=""
95
+
96
+ drain_input
97
+
98
+ {
99
+ printf '\n=== %s ===\n' "$name"
100
+ printf 'query escaped: %s\n' "$(escape_for_display "$payload")"
101
+ printf 'query hex: %s\n' "$(hex_dump "$payload")"
102
+ } | tee -a "$LOG_FILE"
103
+
104
+ printf '%s' "$payload" >&3
105
+ response="$(read_until_gap)"
106
+
107
+ if [ -z "$response" ]; then
108
+ printf 'response: (none)\n' | tee -a "$LOG_FILE"
109
+ return
110
+ fi
111
+
112
+ {
113
+ printf 'response escaped: %s\n' "$(escape_for_display "$response")"
114
+ printf 'response hex: %s\n' "$(hex_dump "$response")"
115
+ } | tee -a "$LOG_FILE"
116
+ }
117
+
118
+ OSC10_BEL="${ESC}]10;?${BEL}"
119
+ OSC11_BEL="${ESC}]11;?${BEL}"
120
+ OSC10_ST="${ESC}]10;?${ST}"
121
+ OSC11_ST="${ESC}]11;?${ST}"
122
+ OSC10_11_BEL="${OSC10_BEL}${OSC11_BEL}"
123
+ OSC10_11_ST="${OSC10_ST}${OSC11_ST}"
124
+ CPR_QUERY="${ESC}[6n"
125
+ XTVERSION_QUERY="${ESC}[>0q"
126
+ COLOR_SCHEME_REQUEST="${ESC}[?996n"
127
+
128
+ {
129
+ printf 'tmux theme query probe\n'
130
+ printf 'log file: %s\n' "$LOG_FILE"
131
+ printf 'tmux env: %s\n' "${TMUX:-<not set>}"
132
+ printf 'TERM: %s\n' "${TERM:-<not set>}"
133
+ printf 'TERM_PROGRAM: %s\n' "${TERM_PROGRAM:-<not set>}"
134
+ printf 'read gap tenths: %s\n' "$READ_GAP_TENTHS"
135
+ printf '\n'
136
+ printf 'Recommended: run this inside tmux in the same pane where theme-mode.ts fails.\n'
137
+ } | tee "$LOG_FILE"
138
+
139
+ run_case 'Control: plain CPR (CSI 6n)' "$CPR_QUERY"
140
+ run_case 'Control: plain xtversion (CSI > 0q)' "$XTVERSION_QUERY"
141
+ run_case 'Plain OSC 10/11 combined with BEL terminators' "$OSC10_11_BEL"
142
+ run_case 'Plain OSC 10/11 combined with ST terminators' "$OSC10_11_ST"
143
+ run_case 'tmux wrapped OSC 10/11 combined in one DCS wrapper (BEL)' "$(tmux_wrap "$OSC10_11_BEL")"
144
+ run_case 'tmux wrapped OSC 10/11 combined in one DCS wrapper (ST)' "$(tmux_wrap "$OSC10_11_ST")"
145
+ run_case 'tmux wrapped OSC 10 only (BEL)' "$(tmux_wrap "$OSC10_BEL")"
146
+ run_case 'tmux wrapped OSC 11 only (BEL)' "$(tmux_wrap "$OSC11_BEL")"
147
+ run_case 'tmux wrapped OSC 10 then OSC 11 as separate DCS wrappers (BEL)' "$(tmux_wrap "$OSC10_BEL")$(tmux_wrap "$OSC11_BEL")"
148
+ run_case 'Plain color scheme request (CSI ?996n)' "$COLOR_SCHEME_REQUEST"
149
+ run_case 'tmux wrapped color scheme request (CSI ?996n)' "$(tmux_wrap "$COLOR_SCHEME_REQUEST")"
150
+
151
+ printf '\nDone. If you want, paste the generated log file and I will compare which query forms tmux answers.\n' | tee -a "$LOG_FILE"
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env bun
2
+ import { TextRenderable, createCliRenderer } from "../src/index.js"
3
+ import { ScrollBoxRenderable } from "../src/renderables/ScrollBox.js"
4
+ async function main() {
5
+ const renderer = await createCliRenderer({ exitOnCtrlC: true })
6
+ console.log("capabilities:", renderer.capabilities)
7
+ const scrollBox = new ScrollBoxRenderable(renderer, {
8
+ id: "scroll-box",
9
+ border: true,
10
+ height: 20,
11
+ title: "Thai Render Debug (Up/Down to scroll, Ctrl+C to exit)",
12
+ titleAlignment: "center",
13
+ })
14
+ const thaiLorem = `ภาษาไทยเป็นภาษาที่มีความสวยงามและซับซ้อนมาก มีพยัญชนะ 44 ตัว สระ 32 รูป และวรรณยุกต์ 4 รูป
15
+ มอญเป็นชนชาติที่มีอิทธิพลต่อภาษาไทยมาก คำว่า "มอ" เป็นพยัญชนะที่ใช้บ่อยในภาษาไทย
16
+ ตัวอย่างคำที่มี มอ: มา มี มือ มอง มัว มอบ มวย มอม มอด มอก
17
+ การเขียนภาษาไทยต้องใส่ใจเรื่องวรรณยุกต์ เช่น ม่า ม้า หม่า หม้า
18
+ สระลอยและสระเปลี่ยนรูปทำให้ภาษาไทยมีความพิเศษ เช่น เมือง แมว ไม้ ใหม่
19
+ คำผสมที่น่าสนใจ: มอมแมม มอดมอด มอมเมา มืดมอม มอมดำ
20
+ ภาษาไทยมีระบบการเขียนที่ไม่เว้นวรรคระหว่างคำ ทำให้การอ่านต้องอาศัยความเข้าใจ
21
+ ตัวอักษรไทยมีสามระดับ: บน กลาง ล่าง เช่น ก็ ปี่ ฎุ ฏู ญ ฐ ฑ
22
+ วรรณยุกต์ไทยมี 5 เสียง: สามัญ เอก โท ตรี จัตวา
23
+ ตัวอย่างเสียงวรรณยุกต์: มา ม่า ม้า หมา หม่า หม้า
24
+ การสะกดคำในภาษาไทยมีกฎเกณฑ์ที่ซับซ้อน มีทั้งตัวสะกดมาตราแม่ ก กา และตัวสะกดไม่ตรงมาตรา
25
+ คำยืมจากภาษาบาลีสันสกฤต: กรรม ธรรม สงฆ์ ศาสนา พระ มหา
26
+ คำยืมจากภาษาเขมร: ถนน เสวย ขนม ตำรวจ ทหาร
27
+ คำยืมจากภาษาจีน: ก๋วยเตี๋ยว เต้าหู้ บะหมี่ เกี๊ยว ซาลาเปา
28
+ ภาษาไทยถิ่นมีหลายภาษา: ภาษาเหนือ ภาษาอีสาน ภาษาใต้ ภาษากลาง
29
+ มอญกับไทยมีความสัมพันธ์ทางวัฒนธรรมมายาวนาน
30
+ ตัวเลขไทย: ๐ ๑ ๒ ๓ ๔ ๕ ๖ ๗ ๘ ๙
31
+ เครื่องหมายวรรคตอน: ฯ ๆ ฯลฯ « » ๏
32
+ อักษรไทยมีต้นกำเนิดจากอักษรเขมร ซึ่งมาจากอักษรปัลลวะของอินเดียใต้
33
+ พ่อขุนรามคำแหงมหาราชทรงประดิษฐ์อักษรไทยเมื่อ พ.ศ. 1826
34
+ ภาษาไทยเป็นภาษาที่มีวรรณยุกต์ การออกเสียงผิดวรรณยุกต์ทำให้ความหมายเปลี่ยน
35
+ ตัวอย่าง: ขาว (สีขาว) ข่าว (news) ข้าว (rice) เข้า (enter)
36
+ มอเตอร์ไซค์ มอนิเตอร์ มอลต์ มอร์ฟีน เป็นคำทับศัพท์ที่มี มอ
37
+ สำนวนไทยที่มี มอ: มอมเมา หมอมหมาม มืดมอม มอดไหม้
38
+ คำกริยาที่มี มอ: มอง มอบ มอม มอด มอก
39
+ คำนามที่มี มอ: มอญ มอด หมอ มอเตอร์
40
+ การผันวรรณยุกต์ของ มอ: มอ ม่อ ม้อ หมอ หม่อ หม้อ
41
+ ภาษาไทยมีคำควบกล้ำ: กร กล กว ขร ขล ขว คร คล คว
42
+ ตัวอย่างคำควบกล้ำ: กราบ กลาง กวาง ครู คลอง ความ
43
+ อักษรสูง กลาง ต่ำ มีผลต่อการผันวรรณยุกต์
44
+ อักษรสูง: ข ฃ ฉ ฐ ถ ผ ฝ ศ ษ ส ห
45
+ อักษรกลาง: ก จ ฎ ฏ ด ต บ ป อ
46
+ อักษรต่ำ: ค ฅ ฆ ง ช ซ ฌ ญ ฑ ฒ ณ ท ธ น พ ฟ ภ ม ย ร ล ว ฬ ฮ`
47
+ const text = new TextRenderable(renderer, {
48
+ id: "thai-text",
49
+ content: thaiLorem,
50
+ })
51
+ scrollBox.add(text)
52
+ renderer.root.add(scrollBox)
53
+ renderer.keyInput.on("keypress", (event) => {
54
+ if (event.name === "down") scrollBox.scrollDown()
55
+ if (event.name === "up") scrollBox.scrollUp()
56
+ })
57
+ renderer.requestRender()
58
+
59
+ renderer.keyInput.on("keypress", (event) => {
60
+ if (event.name === "`") {
61
+ renderer.console.toggle()
62
+ }
63
+ })
64
+ }
65
+ main().catch((err) => {
66
+ console.error("Error:", err)
67
+ process.exit(1)
68
+ })