@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
@@ -0,0 +1,525 @@
1
+ #!/data/data/com.termux/files/usr/bin/bash
2
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
3
+ # XINCLI OpenTUI โ€” Native Termux Build Script
4
+ #
5
+ # RUN THIS ON YOUR ANDROID PHONE (in Termux).
6
+ # Builds libopentui.so natively โ€” no cross-compilation, no NDK.
7
+ #
8
+ # Prerequisites:
9
+ # pkg install nodejs git clang
10
+ # curl -L https://ziglang.org/download/0.15.2/zig-aarch64-linux-0.15.2.tar.xz | tar xJ
11
+ # export PATH="$HOME/zig-aarch64-linux-0.15.2:$PATH"
12
+ #
13
+ # Usage:
14
+ # git clone https://github.com/bd-loser/opentui.git
15
+ # cd opentui
16
+ # bash packages/core/scripts/vendor-deps.sh # one-time, needs network
17
+ # bash packages/core/scripts/build-native-termux.sh # builds offline after vendor
18
+ #
19
+ # Output: packages/core/prebuilt/aarch64-android/libopentui.so
20
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
21
+
22
+ set -e
23
+
24
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
25
+ REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
26
+
27
+ # โ”€โ”€ Verify Zig โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
28
+ if ! command -v zig >/dev/null 2>&1; then
29
+ echo "โŒ Zig not found in PATH."
30
+ echo " curl -L https://ziglang.org/download/0.15.2/zig-aarch64-linux-0.15.2.tar.xz | tar xJ"
31
+ echo " export PATH=\"\$HOME/zig-aarch64-linux-0.15.2:\$PATH\""
32
+ exit 1
33
+ fi
34
+ ZIG_VERSION=$(zig version 2>/dev/null || echo "unknown")
35
+ echo "โœ“ Zig $ZIG_VERSION detected"
36
+
37
+ # โ”€โ”€ Verify vendored deps exist โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
38
+ DEPS_DIR="$REPO_ROOT/.zig-deps"
39
+ if [ ! -d "$DEPS_DIR/yoga" ] || [ ! -d "$DEPS_DIR/uucode" ]; then
40
+ echo "๐Ÿ“ฆ Vendored deps not found. Running vendor-deps.sh first..."
41
+ bash "$SCRIPT_DIR/vendor-deps.sh"
42
+ fi
43
+
44
+ # โ”€โ”€ Populate Zig's dep cache from vendored deps โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
45
+ # Zig's build.zig.zon fetches yoga + uucode from GitHub at build time,
46
+ # which fails on flaky mobile DNS. We pre-fetch them (vendor-deps.sh)
47
+ # and symlink into Zig's global cache so `zig build` finds them locally
48
+ # without any network access.
49
+ ZIG_GLOBAL_CACHE="${XDG_CACHE_HOME:-$HOME/.cache}/zig"
50
+ mkdir -p "$ZIG_GLOBAL_CACHE"
51
+
52
+ # The cache key is the hash from build.zig.zon. We use a fixed name per
53
+ # dep โ€” Zig will look for <hash> as the cache key. If it's not there,
54
+ # Zig tries to fetch. We create the dirs with the expected hashes.
55
+ UUCODE_HASH="uucode-0.1.0-ZZjBPtA_TQCWp5PIKmfm5tu1WOkKWFmBGFEMxircPfkA"
56
+ YOGA_HASH="N-V-__8AAOYl0gAU76B1VRPFD9AWvy2VkOef2jN0B3sISTeO"
57
+
58
+ # Zig 0.15 cache layout: $XDG_CACHE_HOME/zig/p/<hash>/
59
+ mkdir -p "$ZIG_GLOBAL_CACHE/p"
60
+ if [ -d "$DEPS_DIR/uucode" ] && [ ! -d "$ZIG_GLOBAL_CACHE/p/$UUCODE_HASH" ]; then
61
+ cp -r "$DEPS_DIR/uucode" "$ZIG_GLOBAL_CACHE/p/$UUCODE_HASH" 2>/dev/null || true
62
+ echo "โœ“ Cached uucode in Zig global cache"
63
+ fi
64
+ if [ -d "$DEPS_DIR/yoga" ] && [ ! -d "$ZIG_GLOBAL_CACHE/p/$YOGA_HASH" ]; then
65
+ cp -r "$DEPS_DIR/yoga" "$ZIG_GLOBAL_CACHE/p/$YOGA_HASH" 2>/dev/null || true
66
+ echo "โœ“ Cached yoga in Zig global cache"
67
+ fi
68
+
69
+ # โ”€โ”€ Verify we're on Termux (for Bionic detection) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
70
+ PREFIX="${PREFIX:-/data/data/com.termux/files/usr}"
71
+ TERMUX_INCLUDE="$PREFIX/include"
72
+ TERMUX_LIB="$PREFIX/lib"
73
+
74
+ if [ ! -d "$TERMUX_INCLUDE" ]; then
75
+ echo "โš ๏ธ Termux include dir not found at $TERMUX_INCLUDE"
76
+ echo " This script is meant for Termux. Proceeding anyway..."
77
+ fi
78
+
79
+ # โ”€โ”€ Verify arch-specific asm headers exist โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
80
+ # opentui's audio.zig does @cImport of <signal.h> โ†’ <asm/sigcontext.h>.
81
+ # Termux's base linux-headers doesn't include arch-specific asm headers;
82
+ # they come from the `ndk-sysroot` package. Without it, the build fails
83
+ # with 'asm/sigcontext.h' file not found.
84
+ ASM_DIR="$TERMUX_INCLUDE/aarch64-linux-android/asm"
85
+ if [ ! -d "$ASM_DIR" ]; then
86
+ echo "๐Ÿ“ฆ Arch-specific asm headers missing. Installing ndk-sysroot..."
87
+ # ndk-sysroot provides aarch64-linux-android/asm/ + arch-specific headers
88
+ pkg install -y ndk-sysroot 2>&1 | tail -5 || {
89
+ echo "โš ๏ธ pkg install ndk-sysroot failed. Try manually:"
90
+ echo " pkg install ndk-sysroot"
91
+ echo " Then re-run this script."
92
+ }
93
+ fi
94
+
95
+ # Re-check after install attempt
96
+ if [ ! -d "$ASM_DIR" ]; then
97
+ echo "โŒ Arch-specific asm headers still missing at $ASM_DIR"
98
+ echo " Run: pkg install ndk-sysroot"
99
+ echo " Then re-run this script."
100
+ exit 1
101
+ fi
102
+ echo "โœ“ asm headers found at $ASM_DIR"
103
+
104
+ # โ”€โ”€ Find crt objects (crtbegin_so.o, crtend_so.o) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
105
+ # These are compile-time artifacts needed by ld.lld to produce a valid
106
+ # .so. On Termux they come from the ndk-sysroot or clang package. Without
107
+ # them, Zig falls back to glibc defaults and emits -lm -lc -ldl that fail.
108
+ CRT_DIR=""
109
+ for search_dir in \
110
+ "$PREFIX/lib" \
111
+ "$PREFIX/lib/aarch64-linux-android" \
112
+ "$PREFIX/lib64/clang"/*/lib/linux \
113
+ "$PREFIX/lib/clang"/*/lib/linux; do
114
+ if ls $search_dir/crtbegin_so.o >/dev/null 2>&1; then
115
+ CRT_DIR=$(dirname $(ls $search_dir/crtbegin_so.o 2>/dev/null | head -1))
116
+ break
117
+ fi
118
+ done
119
+
120
+ if [ -z "$CRT_DIR" ]; then
121
+ echo "๐Ÿ“ฆ crt objects not found โ€” installing ndk-sysroot + clang..."
122
+ pkg install -y ndk-sysroot clang 2>&1 | tail -5 || true
123
+ for search_dir in \
124
+ "$PREFIX/lib" \
125
+ "$PREFIX/lib/aarch64-linux-android" \
126
+ "$PREFIX/lib64/clang"/*/lib/linux \
127
+ "$PREFIX/lib/clang"/*/lib/linux; do
128
+ if ls $search_dir/crtbegin_so.o >/dev/null 2>&1; then
129
+ CRT_DIR=$(dirname $(ls $search_dir/crtbegin_so.o 2>/dev/null | head -1))
130
+ break
131
+ fi
132
+ done
133
+ fi
134
+
135
+ if [ -z "$CRT_DIR" ]; then
136
+ echo "โŒ Cannot find crtbegin_so.o anywhere on the system."
137
+ echo " Try: pkg install ndk-sysroot clang"
138
+ echo " Then re-run this script."
139
+ exit 1
140
+ fi
141
+ echo "โœ“ crt objects found at: $CRT_DIR"
142
+
143
+ # โ”€โ”€ Patch yoga source: replace std::isinf/isnan/abs with __builtin_* โ”€โ”€
144
+ # NUCLEAR OPTION: Bionic's math.h defines isinf/isnan as C macros that
145
+ # break ALL attempts to use std::isinf in C++. No compiler flag, wrapper
146
+ # header, or macro game can fix this because the preprocessor always wins.
147
+ #
148
+ # Fix: sed-patch yoga's source files to replace the problematic std::
149
+ # calls with __builtin_* compiler intrinsics. These are always available,
150
+ # never macros, and don't depend on any header.
151
+ #
152
+ # IMPORTANT: std::abs can be int or float. __builtin_abs is INT-ONLY.
153
+ # Use __builtin_fabs for abs โ€” it works for ALL numeric types (int,
154
+ # float, double) via implicit conversion, and returns double which
155
+ # compares correctly with < 0.0001.
156
+ #
157
+ # CRITICAL: Clear the Zig cache for yoga first, so we get FRESH source.
158
+ # Previous runs may have already patched std::abs โ†’ __builtin_abs (wrong),
159
+ # and the sed for std::abs won't match anymore. Clearing forces a re-fetch.
160
+ YOGA_DIR=$(find "$HOME/.cache/zig/p" -maxdepth 1 -name "N-V-*" -type d 2>/dev/null | head -1)
161
+ if [ -n "$YOGA_DIR" ] && [ -d "$YOGA_DIR/yoga" ]; then
162
+ # Check if already patched (has __builtin_abs from a previous run)
163
+ if grep -q "__builtin_abs(" "$YOGA_DIR/yoga/numeric/Comparison.h" 2>/dev/null; then
164
+ echo "โš ๏ธ Yoga source has stale patches from previous run โ€” re-fetching fresh copy"
165
+ rm -rf "$YOGA_DIR"
166
+ # Re-populate from vendored deps
167
+ ZIG_GLOBAL_CACHE="${XDG_CACHE_HOME:-$HOME/.cache}/zig"
168
+ YOGA_HASH="N-V-__8AAOYl0gAU76B1VRPFD9AWvy2VkOef2jN0B3sISTeO"
169
+ if [ -d "$REPO_ROOT/.zig-deps/yoga" ]; then
170
+ cp -r "$REPO_ROOT/.zig-deps/yoga" "$ZIG_GLOBAL_CACHE/p/$YOGA_HASH"
171
+ YOGA_DIR="$ZIG_GLOBAL_CACHE/p/$YOGA_HASH"
172
+ fi
173
+ fi
174
+ fi
175
+
176
+ if [ -n "$YOGA_DIR" ] && [ -d "$YOGA_DIR/yoga" ]; then
177
+ echo "๐Ÿ”ง Patching yoga source: std::isinf โ†’ __builtin_isinf etc."
178
+ find "$YOGA_DIR/yoga" -name "*.h" -o -name "*.cpp" | while read f; do
179
+ sed -i \
180
+ -e 's/std::isinf(/__builtin_isinf(/g' \
181
+ -e 's/std::isnan(/__builtin_isnan(/g' \
182
+ -e 's/std::isfinite(/__builtin_isfinite(/g' \
183
+ -e 's/std::signbit(/__builtin_signbit(/g' \
184
+ -e 's/std::abs(/__builtin_fabs(/g' \
185
+ -e 's/std::fabs(/__builtin_fabs(/g' \
186
+ -e 's/std::fpclassify(/__builtin_fpclassify(/g' \
187
+ "$f" 2>/dev/null || true
188
+ done
189
+ # Verify the patch took effect
190
+ if grep -q "__builtin_fabs(" "$YOGA_DIR/yoga/numeric/Comparison.h" 2>/dev/null; then
191
+ echo "โœ“ Yoga source patched (verified: __builtin_fabs in Comparison.h)"
192
+ else
193
+ echo "โš ๏ธ Patch may not have applied โ€” Comparison.h still doesn't have __builtin_fabs"
194
+ grep -n "abs\|isinf" "$YOGA_DIR/yoga/numeric/Comparison.h" 2>/dev/null | head -5
195
+ fi
196
+ else
197
+ echo "โš ๏ธ Yoga dir not found โ€” skipping patch"
198
+ fi
199
+
200
+ # โ”€โ”€ Generate a Zig libc file pointing at Termux's Bionic โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
201
+ # CRITICAL: Without this, Zig detects the host as 'aarch64-linux-musl'
202
+ # (wrong!) and produces a .so that won't load on Termux. The libc file
203
+ # explicitly tells Zig where Termux's Bionic headers + libs live.
204
+ #
205
+ # The libc file's include_dir is used by BOTH @cImport (C) AND the C++
206
+ # compiler. So we point it at Termux's REAL $PREFIX/include which has
207
+ # proper C/C++ header separation (math.h doesn't pollute C++ std::).
208
+ #
209
+ # For the arch-specific asm/ headers (asm/sigcontext.h, asm/types.h),
210
+ # we add them via XINCLI_ANDROID_ASM_INCLUDE env var which build.zig
211
+ # passes to @cImport only (not C++ compilation).
212
+ LIBC_FILE="$REPO_ROOT/packages/core/src/zig/libc-termux.txt"
213
+ cat > "$LIBC_FILE" << EOF
214
+ include_dir=$TERMUX_INCLUDE
215
+ sys_include_dir=$TERMUX_INCLUDE
216
+ crt_dir=$CRT_DIR
217
+ msvc_lib_dir=
218
+ kernel32_lib_dir=
219
+ gcc_dir=
220
+ EOF
221
+ echo "โœ“ Generated libc file: $LIBC_FILE"
222
+ echo " โ†’ include_dir=$TERMUX_INCLUDE (Termux real include โ€” proper C/C++ separation)"
223
+ echo " โ†’ crt_dir=$CRT_DIR"
224
+
225
+ # โ”€โ”€ Set up asm include path for @cImport โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
226
+ # The asm/ headers (asm/sigcontext.h, asm/types.h) live at
227
+ # $PREFIX/include/aarch64-linux-android/asm/. @cImport needs them but
228
+ # they're not in $PREFIX/include directly. We export the path so
229
+ # build.zig can add it via addSystemIncludePath for @cImport only.
230
+ ASM_INCLUDE="$TERMUX_INCLUDE/aarch64-linux-android"
231
+ if [ -d "$ASM_INCLUDE" ]; then
232
+ export XINCLI_ANDROID_ASM_INCLUDE="$ASM_INCLUDE"
233
+ echo "โœ“ asm include: $ASM_INCLUDE"
234
+ fi
235
+
236
+ # โ”€โ”€ Verify Bionic libs exist (DO NOT create stubs โ€” they break Termux) โ”€
237
+ # Zig's linkLibC() adds -lm -lc -ldl. On Termux/Bionic, libc.so IS the
238
+ # real Bionic โ€” but it's often a linker script (text file) that points
239
+ # at the real binary. We must NOT overwrite it.
240
+ #
241
+ # If libm.so or libdl.so are missing (some minimal Termux installs don't
242
+ # ship them as separate files โ€” Bionic folds them into libc.so), we
243
+ # create SEPARATE stub files in a temp dir (NOT $PREFIX/lib) and add
244
+ # that temp dir to the linker search path. This keeps Termux's real
245
+ # libs untouched.
246
+ LINKER_STUBS_DIR="$REPO_ROOT/.zig-linker-stubs"
247
+ mkdir -p "$LINKER_STUBS_DIR"
248
+
249
+ REAL_LIBC=""
250
+ for candidate in \
251
+ "$TERMUX_LIB/libc.so" \
252
+ "$TERMUX_LIB/libc-*.so" \
253
+ "$TERMUX_LIB/libandroid-support.so"; do
254
+ if ls $candidate >/dev/null 2>&1; then
255
+ REAL_LIBC=$(ls $candidate 2>/dev/null | head -1)
256
+ break
257
+ fi
258
+ done
259
+
260
+ if [ -z "$REAL_LIBC" ]; then
261
+ echo "โŒ No libc.so found in $TERMUX_LIB โ€” Termux install is broken."
262
+ echo " Fix: pkg reinstall libc"
263
+ exit 1
264
+ fi
265
+ echo "โœ“ Real libc found: $REAL_LIBC"
266
+
267
+ # Detect the system Bionic path (used for symlinks + direct linking).
268
+ SYSTEM_LIB_DIR="/system/lib64"
269
+ if [ ! -f "$SYSTEM_LIB_DIR/libc.so" ]; then
270
+ SYSTEM_LIB_DIR="/system/lib"
271
+ fi
272
+ if [ ! -f "$SYSTEM_LIB_DIR/libc.so" ]; then
273
+ echo "โŒ Cannot find libc.so in /system/lib64 or /system/lib"
274
+ echo " Android system is broken โ€” this should never happen."
275
+ exit 1
276
+ fi
277
+ SYSTEM_LIBC="$SYSTEM_LIB_DIR/libc.so"
278
+ # Resolve the symlink chain โ€” /system/lib64/libc.so โ†’ /apex/com.android.runtime/lib64/bionic/libc.so
279
+ # ld.lld sometimes can't follow the chain, so we resolve it ourselves.
280
+ SYSTEM_LIBC_REAL=$(readlink -f "$SYSTEM_LIBC" 2>/dev/null || echo "$SYSTEM_LIBC")
281
+ SYSTEM_LIBM_REAL=$(readlink -f "$SYSTEM_LIB_DIR/libm.so" 2>/dev/null || echo "$SYSTEM_LIBC_REAL")
282
+ SYSTEM_LIBDL_REAL=$(readlink -f "$SYSTEM_LIB_DIR/libdl.so" 2>/dev/null || echo "$SYSTEM_LIBC_REAL")
283
+ echo "โœ“ System Bionic (resolved):"
284
+ echo " libc: $SYSTEM_LIBC_REAL"
285
+ echo " libm: $SYSTEM_LIBM_REAL"
286
+ echo " libdl: $SYSTEM_LIBDL_REAL"
287
+
288
+ # Bionic on Termux: libm and libdl symbols are inside libc.so. Termux
289
+ # doesn't ship separate libm.so/libdl.so in $PREFIX/lib. We create
290
+ # LINKER SCRIPTS (not symlinks) in our temp stubs dir. The scripts use
291
+ # ABSOLUTE paths to the APEX .so files so ld.lld opens them directly
292
+ # via open() โ€” bypassing the stat() call that fails on /apex/ due to
293
+ # Android's restricted mount namespace.
294
+ #
295
+ # Format: INPUT ( /absolute/path/to/lib.so )
296
+ # ld.lld reads this as a linker script and opens the absolute path.
297
+ NEED_EXTRA_L_PATH=""
298
+ for libname in libc libm libdl; do
299
+ if [ ! -f "$TERMUX_LIB/${libname}.so" ] && [ ! -L "$TERMUX_LIB/${libname}.so" ]; then
300
+ # Pick the resolved real path for each lib
301
+ case "$libname" in
302
+ libc) TARGET_REAL="$SYSTEM_LIBC_REAL" ;;
303
+ libm) TARGET_REAL="$SYSTEM_LIBM_REAL" ;;
304
+ libdl) TARGET_REAL="$SYSTEM_LIBDL_REAL" ;;
305
+ esac
306
+ # rm -f first โ€” previous runs may have left a broken symlink
307
+ rm -f "$LINKER_STUBS_DIR/${libname}.so" 2>/dev/null || true
308
+ rm -f "$TERMUX_LIB/${libname}.so" 2>/dev/null || true
309
+ # Copy the real .so via dd (open/read/write โ€” bypasses stat())
310
+ echo "โ„น๏ธ Copying $TARGET_REAL โ†’ $TERMUX_LIB/${libname}.so (Termux lib dir)"
311
+ dd if="$TARGET_REAL" of="$TERMUX_LIB/${libname}.so" bs=1M 2>&1 | tail -2
312
+ # Also copy to stubs dir as backup
313
+ dd if="$TARGET_REAL" of="$LINKER_STUBS_DIR/${libname}.so" bs=1M 2>/dev/null || true
314
+ # Verify the copy is a real ELF (check file size > 1000 bytes)
315
+ FILE_SIZE=$(wc -c < "$TERMUX_LIB/${libname}.so" 2>/dev/null || echo "0")
316
+ echo " โ†’ $libname.so size: $FILE_SIZE bytes at $TERMUX_LIB/"
317
+ NEED_EXTRA_L_PATH=1
318
+ fi
319
+ done
320
+ if [ "$NEED_EXTRA_L_PATH" = "1" ]; then
321
+ echo "โœ“ Bionic linker scripts created in $LINKER_STUBS_DIR"
322
+ ls -la "$LINKER_STUBS_DIR"/ 2>&1
323
+ fi
324
+
325
+ # โ”€โ”€ Build โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
326
+ cd "$REPO_ROOT/packages/core/src/zig"
327
+
328
+ echo ""
329
+ echo "๐Ÿ”ง Building libopentui.so natively..."
330
+ echo " Target: aarch64-linux-android (explicit โ€” avoids musl misdetection)"
331
+ echo " Sysroot: $PREFIX (Termux's Bionic)"
332
+ echo " Lib search: $TERMUX_LIB + $LINKER_STUBS_DIR"
333
+ echo ""
334
+
335
+ # Explicit -Dtarget=aarch64-linux-android so Zig doesn't misdetect as musl.
336
+ # ZIG_LIBC env var makes Zig read our generated libc file (Bionic paths).
337
+ # XINCLI_ANDROID_LIB_SEARCH_PATHS is read by build.zig's addLibraryPath calls
338
+ # so ld.lld finds libc/libm/libdl in $PREFIX/lib + the linker-stubs dir.
339
+ #
340
+ # CRITICAL: Termux does NOT ship libc.so/libm.so/libdl.so in $PREFIX/lib/ โ€”
341
+ # they only exist at /system/lib64/. build.zig links them directly by
342
+ # absolute path via addObjectFile, reading the paths from these env vars.
343
+ export ZIG_LIBC="$LIBC_FILE"
344
+ export XINCLI_ANDROID_LIB_PATH="$TERMUX_LIB"
345
+ export XINCLI_ANDROID_LIB_SEARCH_PATHS="$TERMUX_LIB:$LINKER_STUBS_DIR"
346
+ # Include path for @cImport โ€” points at the merged-include dir that has
347
+ # both Termux's headers (pthread.h, math.h, signal.h) and arch-specific
348
+ # asm/ headers (asm/sigcontext.h, asm/types.h).
349
+ export XINCLI_ANDROID_INCLUDE_PATH="$MERGED_INCLUDE"
350
+ # Math.h wrapper dir โ€” placed FIRST in C++ include path to shadow
351
+ # Bionic's math.h and #undef the isinf/isnan/fabs/abs macros.
352
+ export XINCLI_ANDROID_MATH_WRAPPER="$WRAPPER_MATH"
353
+ # cmath wrapper dir โ€” shadows <cmath>, #undefs macros AFTER <cmath> runs
354
+ export XINCLI_ANDROID_CMATH_WRAPPER="$WRAPPER_INCLUDE"
355
+
356
+ # Export the system Bionic paths for build.zig's addObjectFile calls.
357
+ # Use the RESOLVED real paths so ld.lld doesn't have to follow symlinks.
358
+ export XINCLI_ANDROID_LIBC_PATH="$SYSTEM_LIBC_REAL"
359
+ export XINCLI_ANDROID_LIBM_PATH="$SYSTEM_LIBM_REAL"
360
+ export XINCLI_ANDROID_LIBDL_PATH="$SYSTEM_LIBDL_REAL"
361
+ # libc++_shared.so lives in Termux's $PREFIX/lib (from the libc++ package)
362
+ export XINCLI_ANDROID_LIBCXX_PATH="$TERMUX_LIB/libc++_shared.so"
363
+ echo "โœ“ Bionic libs (resolved): $SYSTEM_LIBC_REAL"
364
+ echo "โœ“ libc++: $XINCLI_ANDROID_LIBCXX_PATH"
365
+
366
+ # โ”€โ”€ Find libc++ headers for C++ compilation โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
367
+ # Yoga's C++ files need <type_traits>, <cstddef>, etc. from libc++.
368
+ # We skipped linkLibCpp() for android, so we must add the include path manually.
369
+ # Termux's libc++ package puts headers at $PREFIX/include/c++/v1/
370
+ LIBCXX_INCLUDE=""
371
+ for candidate in \
372
+ "$PREFIX/include/c++/v1" \
373
+ "$PREFIX/include/c++"/*/v1 \
374
+ "$PREFIX/include"/*/c++/v1; do
375
+ if [ -f "$candidate/type_traits" ] 2>/dev/null; then
376
+ LIBCXX_INCLUDE=$(echo $candidate | head -1)
377
+ break
378
+ fi
379
+ done
380
+
381
+ if [ -z "$LIBCXX_INCLUDE" ]; then
382
+ echo "๐Ÿ“ฆ libc++ headers not found โ€” installing libc++-dev..."
383
+ pkg install -y libc++-dev 2>&1 | tail -3 || true
384
+ for candidate in \
385
+ "$PREFIX/include/c++/v1" \
386
+ "$PREFIX/include/c++"/*/v1 \
387
+ "$PREFIX/include"/*/c++/v1; do
388
+ if [ -f "$candidate/type_traits" ] 2>/dev/null; then
389
+ LIBCXX_INCLUDE=$(echo $candidate | head -1)
390
+ break
391
+ fi
392
+ done
393
+ fi
394
+
395
+ if [ -z "$LIBCXX_INCLUDE" ]; then
396
+ echo "โŒ Cannot find libc++ headers (type_traits)."
397
+ echo " Try: pkg install libc++-dev"
398
+ exit 1
399
+ fi
400
+ export XINCLI_ANDROID_LIBCXX_INCLUDE="$LIBCXX_INCLUDE"
401
+ # Some libc++ setups have __config in a separate dir
402
+ LIBCXX_INCLUDE2=$(dirname "$LIBCXX_INCLUDE" 2>/dev/null)
403
+ if [ -d "$LIBCXX_INCLUDE2" ]; then
404
+ export XINCLI_ANDROID_LIBCXX_INCLUDE2="$LIBCXX_INCLUDE2"
405
+ fi
406
+ # Termux's real include dir โ€” used for C++ compilation (proper C/C++ separation).
407
+ # The merged-include dir is only for Zig @cImport (C-only) because its math.h
408
+ # macro 'isinf' breaks std::isinf in C++ context.
409
+ export XINCLI_ANDROID_TERMUX_INCLUDE="$TERMUX_INCLUDE"
410
+ echo "โœ“ libc++ headers: $LIBCXX_INCLUDE"
411
+ echo "โœ“ Termux include (C++): $TERMUX_INCLUDE"
412
+
413
+ # Run zig build with --summary all to see all steps + errors
414
+ # Force clean first to avoid cached results that don't output the .so
415
+ echo "Cleaning previous build cache..."
416
+ rm -rf "$REPO_ROOT/packages/core/src/zig/zig-out" "$REPO_ROOT/packages/core/src/zig/.zig-cache" 2>/dev/null || true
417
+
418
+ zig build \
419
+ -Dtarget=aarch64-linux-android \
420
+ -Doptimize=ReleaseFast \
421
+ --summary all
422
+ ZIG_EXIT=$?
423
+ echo "zig build exit code: $ZIG_EXIT"
424
+ if [ $ZIG_EXIT -ne 0 ]; then
425
+ echo "=== Build failed. Re-running with verbose to see the actual error ==="
426
+ zig build \
427
+ -Dtarget=aarch64-linux-android \
428
+ -Doptimize=ReleaseFast \
429
+ --summary all \
430
+ --verbose
431
+ fi
432
+
433
+ # โ”€โ”€ No symbol renaming needed โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
434
+ # Termux's libc++_shared.so ALSO uses __ndk1 namespace! The original
435
+ # __ndk1 symbols are correct โ€” they match Termux's libc++. The only
436
+ # problem was the TLS crash from NEEDED: libc.so, which is now fixed
437
+ # by RUNPATH: /system/lib64.
438
+ echo "โœ“ No symbol renaming needed (Termux libc++ uses __ndk1 too)"
439
+ # The install step uses dest_dir "../lib/{output_name}" which puts the .so
440
+ # at zig-out/lib/aarch64-android/libopentui.so (outside the default zig-out/)
441
+ # Search broadly: zig-out/, .zig-cache/, and parent directories
442
+ echo "Searching for libopentui.so..."
443
+ find "$REPO_ROOT/packages/core/src/zig" -name "libopentui*.so" -ls 2>/dev/null || echo " (find in src/zig returned nothing)"
444
+ # Also search the zig global cache
445
+ find "$HOME/.cache/zig" -name "libopentui*.so" -ls 2>/dev/null || true
446
+
447
+ SO_PATH=""
448
+ for candidate in \
449
+ "$REPO_ROOT/packages/core/src/zig/zig-out/lib/libopentui.so" \
450
+ "$REPO_ROOT/packages/core/src/zig/zig-out/libopentui.so" \
451
+ "$REPO_ROOT/packages/core/src/zig/zig-out/lib/aarch64-android/libopentui.so" \
452
+ "$REPO_ROOT/packages/core/src/zig/lib/aarch64-android/libopentui.so" \
453
+ "$REPO_ROOT/packages/core/lib/aarch64-android/libopentui.so" \
454
+ "$REPO_ROOT/lib/aarch64-android/libopentui.so" \
455
+ "$(find "$REPO_ROOT" -name 'libopentui*.so' -not -path '*/prebuilt/*' 2>/dev/null | head -1)"; do
456
+ if [ -n "$candidate" ] && [ -f "$candidate" ]; then
457
+ SO_PATH="$candidate"
458
+ break
459
+ fi
460
+ done
461
+
462
+ if [ -z "$SO_PATH" ]; then
463
+ echo ""
464
+ echo "โŒ libopentui.so not found after build."
465
+ echo " zig-out/ contents:"
466
+ find "$REPO_ROOT/packages/core/src/zig/zig-out" -type f 2>/dev/null | head -20
467
+ echo ""
468
+ echo " Common fixes:"
469
+ echo " - If yoga/uucode fetch failed: bash packages/core/scripts/vendor-deps.sh"
470
+ echo " - If DNS failed: try again on WiFi, or vendor deps on a laptop and push"
471
+ exit 1
472
+ fi
473
+
474
+ echo ""
475
+ echo "โœ“ Built: $SO_PATH"
476
+ echo " Size: $(du -h "$SO_PATH" | cut -f1)"
477
+
478
+ # โ”€โ”€ Verify it's ARM64 + links Bionic โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
479
+ echo ""
480
+ echo "๐Ÿ” Verifying .so..."
481
+ if command -v file >/dev/null 2>&1; then
482
+ file "$SO_PATH"
483
+ fi
484
+ if command -v readelf >/dev/null 2>&1; then
485
+ echo " ELF header:"
486
+ readelf -h "$SO_PATH" 2>/dev/null | grep -E "Machine|Class" || true
487
+ echo " Dynamic deps (should include libc.so):"
488
+ readelf -d "$SO_PATH" 2>/dev/null | grep NEEDED | head -10
489
+ fi
490
+
491
+ # โ”€โ”€ Remove Bionic .so copies from $PREFIX/lib after build โ”€โ”€โ”€โ”€โ”€โ”€
492
+ # These were needed for BUILD (linking) but must NOT be present at RUNTIME.
493
+ # At runtime, the linker searches RUNPATH ($PREFIX/lib first) and finds
494
+ # these copies (from /apex/) which cause TLS crash on dlopen because
495
+ # Bionic libc is already loaded in the process.
496
+ #
497
+ # At runtime, the linker should find libc.so at /system/lib64 (second in
498
+ # RUNPATH) โ€” which is the SAME libc already loaded, so no re-load = no crash.
499
+ #
500
+ # Only libc++_shared.so should remain in $PREFIX/lib (Termux's version).
501
+ echo "๐Ÿงน Removing Bionic .so copies from $PREFIX/lib (runtime TLS fix)..."
502
+ rm -f "$TERMUX_LIB/libc.so" 2>/dev/null && echo " โœ“ Removed libc.so" || true
503
+ rm -f "$TERMUX_LIB/libm.so" 2>/dev/null && echo " โœ“ Removed libm.so" || true
504
+ rm -f "$TERMUX_LIB/libdl.so" 2>/dev/null && echo " โœ“ Removed libdl.so" || true
505
+ echo " Remaining in $PREFIX/lib:"
506
+ ls -la "$TERMUX_LIB"/libc*.so "$TERMUX_LIB"/libm*.so "$TERMUX_LIB"/libdl*.so 2>/dev/null || echo " (none โ€” good!)"
507
+ OUT_DIR="$REPO_ROOT/packages/core/prebuilt/aarch64-android"
508
+ mkdir -p "$OUT_DIR"
509
+ cp "$SO_PATH" "$OUT_DIR/libopentui.so"
510
+
511
+ # No symbol renaming โ€” __ndk1 is correct (matches Termux's libc++)
512
+
513
+ echo ""
514
+ echo "โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—"
515
+ echo "โ•‘ โœ… NATIVE BUILD COMPLETE โ•‘"
516
+ echo "โ• โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ฃ"
517
+ echo "โ•‘ Output: packages/core/prebuilt/aarch64-android/libopentui.so โ•‘"
518
+ echo "โ•‘ โ•‘"
519
+ echo "โ•‘ Next: โ•‘"
520
+ echo "โ•‘ git add packages/core/prebuilt/ โ•‘"
521
+ echo "โ•‘ git commit -m 'build: native arm64 .so from Termux' โ•‘"
522
+ echo "โ•‘ git push origin main โ•‘"
523
+ echo "โ•‘ โ•‘"
524
+ echo "โ•‘ The package-prebuilt.yml workflow will publish to npm. โ•‘"
525
+ echo "โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•"