@fairyhunter13/opentui-core 0.1.113 → 0.1.114

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (591) hide show
  1. package/dev/keypress-debug-renderer.ts +148 -0
  2. package/dev/keypress-debug.ts +43 -0
  3. package/dev/print-env-vars.ts +32 -0
  4. package/dev/test-tmux-graphics-334.sh +68 -0
  5. package/dev/thai-debug-test.ts +68 -0
  6. package/docs/development.md +144 -0
  7. package/package.json +62 -53
  8. package/scripts/build.ts +400 -0
  9. package/scripts/publish.ts +60 -0
  10. package/src/3d/SpriteResourceManager.ts +286 -0
  11. package/src/3d/SpriteUtils.ts +70 -0
  12. package/src/3d/TextureUtils.ts +196 -0
  13. package/src/3d/ThreeRenderable.ts +197 -0
  14. package/src/3d/WGPURenderer.ts +294 -0
  15. package/src/3d/animation/ExplodingSpriteEffect.ts +513 -0
  16. package/src/3d/animation/PhysicsExplodingSpriteEffect.ts +429 -0
  17. package/src/3d/animation/SpriteAnimator.ts +633 -0
  18. package/src/3d/animation/SpriteParticleGenerator.ts +435 -0
  19. package/src/3d/canvas.ts +464 -0
  20. package/src/3d/index.ts +12 -0
  21. package/src/3d/physics/PlanckPhysicsAdapter.ts +72 -0
  22. package/src/3d/physics/RapierPhysicsAdapter.ts +66 -0
  23. package/src/3d/physics/physics-interface.ts +31 -0
  24. package/src/3d/shaders/supersampling.wgsl +201 -0
  25. package/src/3d.ts +3 -0
  26. package/src/NativeSpanFeed.ts +300 -0
  27. package/src/Renderable.ts +1704 -0
  28. package/src/__snapshots__/buffer.test.ts.snap +28 -0
  29. package/src/animation/Timeline.test.ts +2709 -0
  30. package/src/animation/Timeline.ts +598 -0
  31. package/src/ansi.ts +18 -0
  32. package/src/benchmark/attenuation-benchmark.ts +81 -0
  33. package/src/benchmark/colormatrix-benchmark.ts +128 -0
  34. package/src/benchmark/gain-benchmark.ts +80 -0
  35. package/src/benchmark/latest-all-bench-run.json +707 -0
  36. package/src/benchmark/latest-async-bench-run.json +336 -0
  37. package/src/benchmark/latest-default-bench-run.json +657 -0
  38. package/src/benchmark/latest-large-bench-run.json +707 -0
  39. package/src/benchmark/latest-quick-bench-run.json +207 -0
  40. package/src/benchmark/markdown-benchmark.ts +1796 -0
  41. package/src/benchmark/native-span-feed-async-benchmark.ts +355 -0
  42. package/src/benchmark/native-span-feed-benchmark.md +56 -0
  43. package/src/benchmark/native-span-feed-benchmark.ts +596 -0
  44. package/src/benchmark/native-span-feed-compare.ts +280 -0
  45. package/src/benchmark/renderer-benchmark.ts +754 -0
  46. package/src/benchmark/text-table-benchmark.ts +948 -0
  47. package/src/buffer.test.ts +291 -0
  48. package/src/buffer.ts +554 -0
  49. package/src/console.test.ts +612 -0
  50. package/src/console.ts +1254 -0
  51. package/src/edit-buffer.test.ts +1769 -0
  52. package/src/edit-buffer.ts +411 -0
  53. package/src/editor-view.test.ts +1032 -0
  54. package/src/editor-view.ts +284 -0
  55. package/src/examples/ascii-font-selection-demo.ts +245 -0
  56. package/src/examples/assets/Water_2_M_Normal.jpg +0 -0
  57. package/src/examples/assets/concrete.png +0 -0
  58. package/src/examples/assets/crate.png +0 -0
  59. package/src/examples/assets/crate_emissive.png +0 -0
  60. package/src/examples/assets/forrest_background.png +0 -0
  61. package/src/examples/assets/hast-example.json +1018 -0
  62. package/src/examples/assets/heart.png +0 -0
  63. package/src/examples/assets/main_char_heavy_attack.png +0 -0
  64. package/src/examples/assets/main_char_idle.png +0 -0
  65. package/src/examples/assets/main_char_jump_end.png +0 -0
  66. package/src/examples/assets/main_char_jump_landing.png +0 -0
  67. package/src/examples/assets/main_char_jump_start.png +0 -0
  68. package/src/examples/assets/main_char_run_loop.png +0 -0
  69. package/src/examples/assets/roughness_map.jpg +0 -0
  70. package/src/examples/build.ts +115 -0
  71. package/src/examples/code-demo.ts +924 -0
  72. package/src/examples/console-demo.ts +358 -0
  73. package/src/examples/core-plugin-slots-demo.ts +759 -0
  74. package/src/examples/diff-demo.ts +701 -0
  75. package/src/examples/draggable-three-demo.ts +259 -0
  76. package/src/examples/editor-demo.ts +322 -0
  77. package/src/examples/extmarks-demo.ts +196 -0
  78. package/src/examples/focus-restore-demo.ts +310 -0
  79. package/src/examples/fonts.ts +245 -0
  80. package/src/examples/fractal-shader-demo.ts +268 -0
  81. package/src/examples/framebuffer-demo.ts +674 -0
  82. package/src/examples/full-unicode-demo.ts +241 -0
  83. package/src/examples/golden-star-demo.ts +933 -0
  84. package/src/examples/grayscale-buffer-demo.ts +249 -0
  85. package/src/examples/hast-syntax-highlighting-demo.ts +129 -0
  86. package/src/examples/index.ts +926 -0
  87. package/src/examples/input-demo.ts +377 -0
  88. package/src/examples/input-select-layout-demo.ts +425 -0
  89. package/src/examples/install.sh +143 -0
  90. package/src/examples/keypress-debug-demo.ts +452 -0
  91. package/src/examples/lib/HexList.ts +122 -0
  92. package/src/examples/lib/PaletteGrid.ts +125 -0
  93. package/src/examples/lib/standalone-keys.ts +25 -0
  94. package/src/examples/lib/tab-controller.ts +243 -0
  95. package/src/examples/lights-phong-demo.ts +290 -0
  96. package/src/examples/link-demo.ts +220 -0
  97. package/src/examples/live-state-demo.ts +480 -0
  98. package/src/examples/markdown-demo.ts +725 -0
  99. package/src/examples/mouse-interaction-demo.ts +428 -0
  100. package/src/examples/nested-zindex-demo.ts +357 -0
  101. package/src/examples/opacity-example.ts +235 -0
  102. package/src/examples/opentui-demo.ts +1057 -0
  103. package/src/examples/physx-planck-2d-demo.ts +623 -0
  104. package/src/examples/physx-rapier-2d-demo.ts +655 -0
  105. package/src/examples/relative-positioning-demo.ts +323 -0
  106. package/src/examples/scroll-example.ts +214 -0
  107. package/src/examples/scrollbox-mouse-test.ts +112 -0
  108. package/src/examples/scrollbox-overlay-hit-test.ts +206 -0
  109. package/src/examples/select-demo.ts +237 -0
  110. package/src/examples/shader-cube-demo.ts +1015 -0
  111. package/src/examples/simple-layout-example.ts +591 -0
  112. package/src/examples/slider-demo.ts +617 -0
  113. package/src/examples/split-mode-demo.ts +453 -0
  114. package/src/examples/sprite-animation-demo.ts +443 -0
  115. package/src/examples/sprite-particle-generator-demo.ts +486 -0
  116. package/src/examples/static-sprite-demo.ts +193 -0
  117. package/src/examples/sticky-scroll-example.ts +308 -0
  118. package/src/examples/styled-text-demo.ts +282 -0
  119. package/src/examples/tab-select-demo.ts +219 -0
  120. package/src/examples/terminal-title.ts +29 -0
  121. package/src/examples/terminal.ts +305 -0
  122. package/src/examples/text-node-demo.ts +416 -0
  123. package/src/examples/text-selection-demo.ts +377 -0
  124. package/src/examples/text-table-demo.ts +503 -0
  125. package/src/examples/text-truncation-demo.ts +481 -0
  126. package/src/examples/text-wrap.ts +757 -0
  127. package/src/examples/texture-loading-demo.ts +259 -0
  128. package/src/examples/timeline-example.ts +670 -0
  129. package/src/examples/transparency-demo.ts +400 -0
  130. package/src/examples/vnode-composition-demo.ts +404 -0
  131. package/src/examples/wide-grapheme-overlay-demo.ts +280 -0
  132. package/src/index.ts +24 -0
  133. package/src/lib/KeyHandler.integration.test.ts +292 -0
  134. package/src/lib/KeyHandler.stopPropagation.test.ts +289 -0
  135. package/src/lib/KeyHandler.test.ts +662 -0
  136. package/src/lib/KeyHandler.ts +222 -0
  137. package/src/lib/RGBA.test.ts +984 -0
  138. package/src/lib/RGBA.ts +204 -0
  139. package/src/lib/ascii.font.ts +330 -0
  140. package/src/lib/border.test.ts +83 -0
  141. package/src/lib/border.ts +170 -0
  142. package/src/lib/bunfs.test.ts +27 -0
  143. package/src/lib/bunfs.ts +18 -0
  144. package/src/lib/clipboard.test.ts +41 -0
  145. package/src/lib/clipboard.ts +47 -0
  146. package/src/lib/clock.ts +35 -0
  147. package/src/lib/data-paths.test.ts +133 -0
  148. package/src/lib/data-paths.ts +109 -0
  149. package/src/lib/debounce.ts +106 -0
  150. package/src/lib/detect-links.test.ts +98 -0
  151. package/src/lib/detect-links.ts +56 -0
  152. package/src/lib/env.test.ts +228 -0
  153. package/src/lib/env.ts +209 -0
  154. package/src/lib/extmarks-history.ts +51 -0
  155. package/src/lib/extmarks-multiwidth.test.ts +322 -0
  156. package/src/lib/extmarks.test.ts +3457 -0
  157. package/src/lib/extmarks.ts +843 -0
  158. package/src/lib/fonts/block.json +405 -0
  159. package/src/lib/fonts/grid.json +265 -0
  160. package/src/lib/fonts/huge.json +741 -0
  161. package/src/lib/fonts/pallet.json +314 -0
  162. package/src/lib/fonts/shade.json +591 -0
  163. package/src/lib/fonts/slick.json +321 -0
  164. package/src/lib/fonts/tiny.json +69 -0
  165. package/src/lib/hast-styled-text.ts +59 -0
  166. package/src/lib/index.ts +21 -0
  167. package/src/lib/keymapping.test.ts +317 -0
  168. package/src/lib/keymapping.ts +115 -0
  169. package/src/lib/objects-in-viewport.test.ts +787 -0
  170. package/src/lib/objects-in-viewport.ts +153 -0
  171. package/src/lib/output.capture.ts +58 -0
  172. package/src/lib/parse.keypress-kitty.protocol.test.ts +340 -0
  173. package/src/lib/parse.keypress-kitty.test.ts +663 -0
  174. package/src/lib/parse.keypress-kitty.ts +439 -0
  175. package/src/lib/parse.keypress.test.ts +1849 -0
  176. package/src/lib/parse.keypress.ts +397 -0
  177. package/src/lib/parse.mouse.test.ts +552 -0
  178. package/src/lib/parse.mouse.ts +232 -0
  179. package/src/lib/paste.ts +16 -0
  180. package/src/lib/queue.ts +65 -0
  181. package/src/lib/renderable.validations.test.ts +87 -0
  182. package/src/lib/renderable.validations.ts +83 -0
  183. package/src/lib/scroll-acceleration.ts +98 -0
  184. package/src/lib/selection.ts +240 -0
  185. package/src/lib/singleton.ts +28 -0
  186. package/src/lib/stdin-parser.test.ts +2290 -0
  187. package/src/lib/stdin-parser.ts +1810 -0
  188. package/src/lib/styled-text.ts +178 -0
  189. package/src/lib/terminal-capability-detection.test.ts +202 -0
  190. package/src/lib/terminal-capability-detection.ts +79 -0
  191. package/src/lib/terminal-palette.test.ts +878 -0
  192. package/src/lib/terminal-palette.ts +383 -0
  193. package/src/lib/tree-sitter/assets/README.md +118 -0
  194. package/src/lib/tree-sitter/assets/update.ts +334 -0
  195. package/src/lib/tree-sitter/assets.d.ts +9 -0
  196. package/src/lib/tree-sitter/cache.test.ts +273 -0
  197. package/src/lib/tree-sitter/client.test.ts +1165 -0
  198. package/src/lib/tree-sitter/client.ts +607 -0
  199. package/src/lib/tree-sitter/default-parsers.ts +86 -0
  200. package/src/lib/tree-sitter/download-utils.ts +148 -0
  201. package/src/lib/tree-sitter/index.ts +28 -0
  202. package/src/lib/tree-sitter/parser.worker.ts +1042 -0
  203. package/src/lib/tree-sitter/parsers-config.ts +81 -0
  204. package/src/lib/tree-sitter/resolve-ft.test.ts +55 -0
  205. package/src/lib/tree-sitter/resolve-ft.ts +189 -0
  206. package/src/lib/tree-sitter/types.ts +82 -0
  207. package/src/lib/tree-sitter-styled-text.test.ts +1253 -0
  208. package/src/lib/tree-sitter-styled-text.ts +306 -0
  209. package/src/lib/validate-dir-name.ts +55 -0
  210. package/src/lib/yoga.options.test.ts +628 -0
  211. package/src/lib/yoga.options.ts +346 -0
  212. package/src/plugins/core-slot.ts +579 -0
  213. package/src/plugins/registry.ts +402 -0
  214. package/src/plugins/types.ts +46 -0
  215. package/src/post/effects.ts +930 -0
  216. package/src/post/filters.ts +489 -0
  217. package/src/post/matrices.ts +288 -0
  218. package/src/renderables/ASCIIFont.ts +219 -0
  219. package/src/renderables/Box.test.ts +205 -0
  220. package/src/renderables/Box.ts +326 -0
  221. package/src/renderables/Code.test.ts +2062 -0
  222. package/src/renderables/Code.ts +357 -0
  223. package/src/renderables/Diff.regression.test.ts +226 -0
  224. package/src/renderables/Diff.test.ts +3101 -0
  225. package/src/renderables/Diff.ts +1211 -0
  226. package/src/renderables/EditBufferRenderable.test.ts +288 -0
  227. package/src/renderables/EditBufferRenderable.ts +1166 -0
  228. package/src/renderables/FrameBuffer.ts +47 -0
  229. package/src/renderables/Input.test.ts +1228 -0
  230. package/src/renderables/Input.ts +247 -0
  231. package/src/renderables/LineNumberRenderable.ts +724 -0
  232. package/src/renderables/Markdown.ts +1393 -0
  233. package/src/renderables/ScrollBar.ts +422 -0
  234. package/src/renderables/ScrollBox.ts +883 -0
  235. package/src/renderables/Select.test.ts +1033 -0
  236. package/src/renderables/Select.ts +524 -0
  237. package/src/renderables/Slider.test.ts +456 -0
  238. package/src/renderables/Slider.ts +342 -0
  239. package/src/renderables/TabSelect.test.ts +197 -0
  240. package/src/renderables/TabSelect.ts +455 -0
  241. package/src/renderables/Text.selection-buffer.test.ts +123 -0
  242. package/src/renderables/Text.test.ts +2660 -0
  243. package/src/renderables/Text.ts +147 -0
  244. package/src/renderables/TextBufferRenderable.ts +518 -0
  245. package/src/renderables/TextNode.test.ts +1058 -0
  246. package/src/renderables/TextNode.ts +325 -0
  247. package/src/renderables/TextTable.test.ts +1421 -0
  248. package/src/renderables/TextTable.ts +1344 -0
  249. package/src/renderables/Textarea.ts +430 -0
  250. package/src/renderables/TimeToFirstDraw.ts +89 -0
  251. package/src/renderables/__snapshots__/Code.test.ts.snap +13 -0
  252. package/src/renderables/__snapshots__/Diff.test.ts.snap +785 -0
  253. package/src/renderables/__snapshots__/Text.test.ts.snap +421 -0
  254. package/src/renderables/__snapshots__/TextTable.test.ts.snap +215 -0
  255. package/src/renderables/__tests__/LineNumberRenderable.scrollbox-simple.test.ts +144 -0
  256. package/src/renderables/__tests__/LineNumberRenderable.scrollbox.test.ts +816 -0
  257. package/src/renderables/__tests__/LineNumberRenderable.test.ts +1865 -0
  258. package/src/renderables/__tests__/LineNumberRenderable.wrapping.test.ts +85 -0
  259. package/src/renderables/__tests__/Markdown.code-colors.test.ts +242 -0
  260. package/src/renderables/__tests__/Markdown.test.ts +2518 -0
  261. package/src/renderables/__tests__/MultiRenderable.selection.test.ts +87 -0
  262. package/src/renderables/__tests__/Textarea.buffer.test.ts +682 -0
  263. package/src/renderables/__tests__/Textarea.destroyed-events.test.ts +675 -0
  264. package/src/renderables/__tests__/Textarea.editing.test.ts +2041 -0
  265. package/src/renderables/__tests__/Textarea.error-handling.test.ts +35 -0
  266. package/src/renderables/__tests__/Textarea.events.test.ts +738 -0
  267. package/src/renderables/__tests__/Textarea.highlights.test.ts +590 -0
  268. package/src/renderables/__tests__/Textarea.keybinding.test.ts +3149 -0
  269. package/src/renderables/__tests__/Textarea.paste.test.ts +357 -0
  270. package/src/renderables/__tests__/Textarea.rendering.test.ts +1866 -0
  271. package/src/renderables/__tests__/Textarea.scroll.test.ts +733 -0
  272. package/src/renderables/__tests__/Textarea.selection.test.ts +1590 -0
  273. package/src/renderables/__tests__/Textarea.stress.test.ts +670 -0
  274. package/src/renderables/__tests__/Textarea.undo-redo.test.ts +383 -0
  275. package/src/renderables/__tests__/Textarea.visual-lines.test.ts +310 -0
  276. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.code.test.ts.snap +221 -0
  277. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox-simple.test.ts.snap +89 -0
  278. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox.test.ts.snap +457 -0
  279. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.test.ts.snap +158 -0
  280. package/src/renderables/__tests__/__snapshots__/Textarea.rendering.test.ts.snap +387 -0
  281. package/src/renderables/__tests__/markdown-parser.test.ts +217 -0
  282. package/src/renderables/__tests__/renderable-test-utils.ts +60 -0
  283. package/src/renderables/composition/README.md +8 -0
  284. package/src/renderables/composition/VRenderable.ts +32 -0
  285. package/src/renderables/composition/constructs.ts +127 -0
  286. package/src/renderables/composition/vnode.ts +289 -0
  287. package/src/renderables/index.ts +23 -0
  288. package/src/renderables/markdown-parser.ts +66 -0
  289. package/src/renderer.ts +2681 -0
  290. package/src/runtime-plugin-support.ts +39 -0
  291. package/src/runtime-plugin.ts +615 -0
  292. package/src/syntax-style.test.ts +841 -0
  293. package/src/syntax-style.ts +257 -0
  294. package/src/testing/README.md +210 -0
  295. package/src/testing/capture-spans.test.ts +194 -0
  296. package/src/testing/integration.test.ts +276 -0
  297. package/src/testing/manual-clock.ts +117 -0
  298. package/src/testing/mock-keys.test.ts +1378 -0
  299. package/src/testing/mock-keys.ts +457 -0
  300. package/src/testing/mock-mouse.test.ts +218 -0
  301. package/src/testing/mock-mouse.ts +247 -0
  302. package/src/testing/mock-tree-sitter-client.ts +73 -0
  303. package/src/testing/spy.ts +13 -0
  304. package/src/testing/test-recorder.test.ts +415 -0
  305. package/src/testing/test-recorder.ts +145 -0
  306. package/src/testing/test-renderer.ts +132 -0
  307. package/src/testing.ts +7 -0
  308. package/src/tests/__snapshots__/absolute-positioning.snapshot.test.ts.snap +481 -0
  309. package/src/tests/__snapshots__/renderable.snapshot.test.ts.snap +19 -0
  310. package/src/tests/__snapshots__/scrollbox.test.ts.snap +29 -0
  311. package/src/tests/absolute-positioning.snapshot.test.ts +638 -0
  312. package/src/tests/allocator-stats.test.ts +38 -0
  313. package/src/tests/destroy-during-render.test.ts +200 -0
  314. package/src/tests/destroy-on-exit.fixture.ts +36 -0
  315. package/src/tests/destroy-on-exit.test.ts +41 -0
  316. package/src/tests/hover-cursor.test.ts +98 -0
  317. package/src/tests/native-span-feed-async.test.ts +173 -0
  318. package/src/tests/native-span-feed-close.test.ts +120 -0
  319. package/src/tests/native-span-feed-coverage.test.ts +227 -0
  320. package/src/tests/native-span-feed-edge-cases.test.ts +352 -0
  321. package/src/tests/native-span-feed-use-after-free.test.ts +45 -0
  322. package/src/tests/opacity.test.ts +123 -0
  323. package/src/tests/renderable.snapshot.test.ts +524 -0
  324. package/src/tests/renderable.test.ts +1281 -0
  325. package/src/tests/renderer.clock.test.ts +158 -0
  326. package/src/tests/renderer.console-startup.test.ts +185 -0
  327. package/src/tests/renderer.control.test.ts +425 -0
  328. package/src/tests/renderer.core-slot-binding.test.ts +952 -0
  329. package/src/tests/renderer.cursor.test.ts +26 -0
  330. package/src/tests/renderer.destroy-during-render.test.ts +147 -0
  331. package/src/tests/renderer.focus-restore.test.ts +257 -0
  332. package/src/tests/renderer.focus.test.ts +294 -0
  333. package/src/tests/renderer.idle.test.ts +219 -0
  334. package/src/tests/renderer.input.test.ts +2237 -0
  335. package/src/tests/renderer.kitty-flags.test.ts +195 -0
  336. package/src/tests/renderer.mouse.test.ts +1274 -0
  337. package/src/tests/renderer.palette.test.ts +629 -0
  338. package/src/tests/renderer.selection.test.ts +49 -0
  339. package/src/tests/renderer.slot-registry.test.ts +684 -0
  340. package/src/tests/renderer.useMouse.test.ts +47 -0
  341. package/src/tests/runtime-plugin-node-modules-cycle.fixture.ts +76 -0
  342. package/src/tests/runtime-plugin-node-modules-mjs.fixture.ts +43 -0
  343. package/src/tests/runtime-plugin-node-modules-no-bare-rewrite.fixture.ts +67 -0
  344. package/src/tests/runtime-plugin-node-modules-package-type-cache.fixture.ts +72 -0
  345. package/src/tests/runtime-plugin-node-modules-runtime-specifier.fixture.ts +44 -0
  346. package/src/tests/runtime-plugin-node-modules-scoped-package-bare-rewrite.fixture.ts +85 -0
  347. package/src/tests/runtime-plugin-path-alias.fixture.ts +43 -0
  348. package/src/tests/runtime-plugin-resolve-roots.fixture.ts +65 -0
  349. package/src/tests/runtime-plugin-support.fixture.ts +11 -0
  350. package/src/tests/runtime-plugin-support.test.ts +19 -0
  351. package/src/tests/runtime-plugin-windows-file-url.fixture.ts +30 -0
  352. package/src/tests/runtime-plugin.fixture.ts +40 -0
  353. package/src/tests/runtime-plugin.test.ts +354 -0
  354. package/src/tests/scrollbox-culling-bug.test.ts +114 -0
  355. package/src/tests/scrollbox-hitgrid-resize.test.ts +136 -0
  356. package/src/tests/scrollbox-hitgrid.test.ts +909 -0
  357. package/src/tests/scrollbox.test.ts +1530 -0
  358. package/src/tests/wrap-resize-perf.test.ts +276 -0
  359. package/src/tests/yoga-setters.test.ts +921 -0
  360. package/src/text-buffer-view.test.ts +705 -0
  361. package/src/text-buffer-view.ts +189 -0
  362. package/src/text-buffer.test.ts +347 -0
  363. package/src/text-buffer.ts +250 -0
  364. package/src/types.ts +161 -0
  365. package/src/utils.ts +88 -0
  366. package/src/zig/ansi.zig +268 -0
  367. package/src/zig/bench/README.md +50 -0
  368. package/src/zig/bench/buffer-draw-text-buffer_bench.zig +887 -0
  369. package/src/zig/bench/edit-buffer_bench.zig +476 -0
  370. package/src/zig/bench/native-span-feed_bench.zig +100 -0
  371. package/src/zig/bench/rope-markers_bench.zig +713 -0
  372. package/src/zig/bench/rope_bench.zig +514 -0
  373. package/src/zig/bench/styled-text_bench.zig +470 -0
  374. package/src/zig/bench/text-buffer-coords_bench.zig +362 -0
  375. package/src/zig/bench/text-buffer-view_bench.zig +459 -0
  376. package/src/zig/bench/text-chunk-graphemes_bench.zig +273 -0
  377. package/src/zig/bench/utf8_bench.zig +799 -0
  378. package/src/zig/bench-utils.zig +431 -0
  379. package/src/zig/bench.zig +217 -0
  380. package/src/zig/buffer-methods.zig +211 -0
  381. package/src/zig/buffer.zig +2281 -0
  382. package/src/zig/build.zig +289 -0
  383. package/src/zig/build.zig.zon +16 -0
  384. package/src/zig/edit-buffer.zig +825 -0
  385. package/src/zig/editor-view.zig +802 -0
  386. package/src/zig/event-bus.zig +13 -0
  387. package/src/zig/event-emitter.zig +65 -0
  388. package/src/zig/file-logger.zig +92 -0
  389. package/src/zig/grapheme.zig +599 -0
  390. package/src/zig/lib.zig +1854 -0
  391. package/src/zig/link.zig +333 -0
  392. package/src/zig/logger.zig +43 -0
  393. package/src/zig/mem-registry.zig +125 -0
  394. package/src/zig/native-span-feed-bench-lib.zig +7 -0
  395. package/src/zig/native-span-feed.zig +708 -0
  396. package/src/zig/renderer.zig +1393 -0
  397. package/src/zig/rope.zig +1220 -0
  398. package/src/zig/syntax-style.zig +161 -0
  399. package/src/zig/terminal.zig +987 -0
  400. package/src/zig/test.zig +72 -0
  401. package/src/zig/tests/README.md +18 -0
  402. package/src/zig/tests/buffer-methods_test.zig +1109 -0
  403. package/src/zig/tests/buffer_test.zig +2557 -0
  404. package/src/zig/tests/edit-buffer-history_test.zig +271 -0
  405. package/src/zig/tests/edit-buffer_test.zig +1689 -0
  406. package/src/zig/tests/editor-view_test.zig +3299 -0
  407. package/src/zig/tests/event-emitter_test.zig +249 -0
  408. package/src/zig/tests/grapheme_test.zig +1304 -0
  409. package/src/zig/tests/link_test.zig +190 -0
  410. package/src/zig/tests/mem-registry_test.zig +473 -0
  411. package/src/zig/tests/memory_leak_regression_test.zig +159 -0
  412. package/src/zig/tests/native-span-feed_test.zig +1264 -0
  413. package/src/zig/tests/renderer_test.zig +1017 -0
  414. package/src/zig/tests/rope-nested_test.zig +712 -0
  415. package/src/zig/tests/rope_fuzz_test.zig +238 -0
  416. package/src/zig/tests/rope_test.zig +2362 -0
  417. package/src/zig/tests/segment-merge.test.zig +148 -0
  418. package/src/zig/tests/syntax-style_test.zig +557 -0
  419. package/src/zig/tests/terminal_test.zig +754 -0
  420. package/src/zig/tests/text-buffer-drawing_test.zig +3237 -0
  421. package/src/zig/tests/text-buffer-highlights_test.zig +666 -0
  422. package/src/zig/tests/text-buffer-iterators_test.zig +776 -0
  423. package/src/zig/tests/text-buffer-segment_test.zig +320 -0
  424. package/src/zig/tests/text-buffer-selection_test.zig +1035 -0
  425. package/src/zig/tests/text-buffer-selection_viewport_test.zig +358 -0
  426. package/src/zig/tests/text-buffer-view_test.zig +3649 -0
  427. package/src/zig/tests/text-buffer_test.zig +2191 -0
  428. package/src/zig/tests/unicode-width-map.zon +3909 -0
  429. package/src/zig/tests/utf8_no_zwj_test.zig +260 -0
  430. package/src/zig/tests/utf8_test.zig +4057 -0
  431. package/src/zig/tests/utf8_wcwidth_cursor_test.zig +267 -0
  432. package/src/zig/tests/utf8_wcwidth_test.zig +357 -0
  433. package/src/zig/tests/word-wrap-editing_test.zig +498 -0
  434. package/src/zig/tests/wrap-cache-perf_test.zig +113 -0
  435. package/src/zig/text-buffer-iterators.zig +499 -0
  436. package/src/zig/text-buffer-segment.zig +404 -0
  437. package/src/zig/text-buffer-view.zig +1371 -0
  438. package/src/zig/text-buffer.zig +1180 -0
  439. package/src/zig/utf8.zig +1948 -0
  440. package/src/zig/utils.zig +9 -0
  441. package/src/zig-structs.ts +261 -0
  442. package/src/zig.ts +3884 -0
  443. package/tsconfig.build.json +24 -0
  444. package/tsconfig.json +27 -0
  445. package/3d/SpriteResourceManager.d.ts +0 -74
  446. package/3d/SpriteUtils.d.ts +0 -13
  447. package/3d/TextureUtils.d.ts +0 -24
  448. package/3d/ThreeRenderable.d.ts +0 -40
  449. package/3d/WGPURenderer.d.ts +0 -61
  450. package/3d/animation/ExplodingSpriteEffect.d.ts +0 -71
  451. package/3d/animation/PhysicsExplodingSpriteEffect.d.ts +0 -76
  452. package/3d/animation/SpriteAnimator.d.ts +0 -124
  453. package/3d/animation/SpriteParticleGenerator.d.ts +0 -62
  454. package/3d/canvas.d.ts +0 -44
  455. package/3d/index.d.ts +0 -12
  456. package/3d/physics/PlanckPhysicsAdapter.d.ts +0 -19
  457. package/3d/physics/RapierPhysicsAdapter.d.ts +0 -19
  458. package/3d/physics/physics-interface.d.ts +0 -27
  459. package/3d.d.ts +0 -2
  460. package/3d.js +0 -34041
  461. package/3d.js.map +0 -155
  462. package/LICENSE +0 -21
  463. package/NativeSpanFeed.d.ts +0 -41
  464. package/Renderable.d.ts +0 -334
  465. package/animation/Timeline.d.ts +0 -126
  466. package/ansi.d.ts +0 -13
  467. package/buffer.d.ts +0 -111
  468. package/console.d.ts +0 -144
  469. package/edit-buffer.d.ts +0 -98
  470. package/editor-view.d.ts +0 -73
  471. package/index-9vwc3fg6.js +0 -12260
  472. package/index-9vwc3fg6.js.map +0 -42
  473. package/index-dcj62y8t.js +0 -20614
  474. package/index-dcj62y8t.js.map +0 -67
  475. package/index-f7n39gpy.js +0 -411
  476. package/index-f7n39gpy.js.map +0 -10
  477. package/index.d.ts +0 -23
  478. package/index.js +0 -478
  479. package/index.js.map +0 -9
  480. package/lib/KeyHandler.d.ts +0 -61
  481. package/lib/RGBA.d.ts +0 -25
  482. package/lib/ascii.font.d.ts +0 -508
  483. package/lib/border.d.ts +0 -51
  484. package/lib/bunfs.d.ts +0 -7
  485. package/lib/clipboard.d.ts +0 -17
  486. package/lib/clock.d.ts +0 -15
  487. package/lib/data-paths.d.ts +0 -26
  488. package/lib/debounce.d.ts +0 -42
  489. package/lib/detect-links.d.ts +0 -6
  490. package/lib/env.d.ts +0 -42
  491. package/lib/extmarks-history.d.ts +0 -17
  492. package/lib/extmarks.d.ts +0 -89
  493. package/lib/hast-styled-text.d.ts +0 -17
  494. package/lib/index.d.ts +0 -21
  495. package/lib/keymapping.d.ts +0 -25
  496. package/lib/objects-in-viewport.d.ts +0 -24
  497. package/lib/output.capture.d.ts +0 -24
  498. package/lib/parse.keypress-kitty.d.ts +0 -2
  499. package/lib/parse.keypress.d.ts +0 -26
  500. package/lib/parse.mouse.d.ts +0 -30
  501. package/lib/paste.d.ts +0 -7
  502. package/lib/queue.d.ts +0 -15
  503. package/lib/renderable.validations.d.ts +0 -12
  504. package/lib/scroll-acceleration.d.ts +0 -43
  505. package/lib/selection.d.ts +0 -63
  506. package/lib/singleton.d.ts +0 -7
  507. package/lib/stdin-parser.d.ts +0 -87
  508. package/lib/styled-text.d.ts +0 -63
  509. package/lib/terminal-capability-detection.d.ts +0 -30
  510. package/lib/terminal-palette.d.ts +0 -50
  511. package/lib/tree-sitter/assets/update.d.ts +0 -11
  512. package/lib/tree-sitter/client.d.ts +0 -47
  513. package/lib/tree-sitter/default-parsers.d.ts +0 -2
  514. package/lib/tree-sitter/download-utils.d.ts +0 -21
  515. package/lib/tree-sitter/index.d.ts +0 -8
  516. package/lib/tree-sitter/parser.worker.d.ts +0 -1
  517. package/lib/tree-sitter/parsers-config.d.ts +0 -53
  518. package/lib/tree-sitter/resolve-ft.d.ts +0 -5
  519. package/lib/tree-sitter/types.d.ts +0 -82
  520. package/lib/tree-sitter-styled-text.d.ts +0 -14
  521. package/lib/validate-dir-name.d.ts +0 -1
  522. package/lib/yoga.options.d.ts +0 -32
  523. package/parser.worker.js +0 -899
  524. package/parser.worker.js.map +0 -12
  525. package/plugins/core-slot.d.ts +0 -72
  526. package/plugins/registry.d.ts +0 -42
  527. package/plugins/types.d.ts +0 -34
  528. package/post/effects.d.ts +0 -147
  529. package/post/filters.d.ts +0 -65
  530. package/post/matrices.d.ts +0 -20
  531. package/renderables/ASCIIFont.d.ts +0 -52
  532. package/renderables/Box.d.ts +0 -81
  533. package/renderables/Code.d.ts +0 -78
  534. package/renderables/Diff.d.ts +0 -142
  535. package/renderables/EditBufferRenderable.d.ts +0 -237
  536. package/renderables/FrameBuffer.d.ts +0 -16
  537. package/renderables/Input.d.ts +0 -67
  538. package/renderables/LineNumberRenderable.d.ts +0 -78
  539. package/renderables/Markdown.d.ts +0 -185
  540. package/renderables/ScrollBar.d.ts +0 -77
  541. package/renderables/ScrollBox.d.ts +0 -124
  542. package/renderables/Select.d.ts +0 -115
  543. package/renderables/Slider.d.ts +0 -47
  544. package/renderables/TabSelect.d.ts +0 -96
  545. package/renderables/Text.d.ts +0 -36
  546. package/renderables/TextBufferRenderable.d.ts +0 -105
  547. package/renderables/TextNode.d.ts +0 -91
  548. package/renderables/TextTable.d.ts +0 -140
  549. package/renderables/Textarea.d.ts +0 -63
  550. package/renderables/TimeToFirstDraw.d.ts +0 -24
  551. package/renderables/__tests__/renderable-test-utils.d.ts +0 -12
  552. package/renderables/composition/VRenderable.d.ts +0 -16
  553. package/renderables/composition/constructs.d.ts +0 -35
  554. package/renderables/composition/vnode.d.ts +0 -46
  555. package/renderables/index.d.ts +0 -23
  556. package/renderables/markdown-parser.d.ts +0 -10
  557. package/renderer.d.ts +0 -419
  558. package/runtime-plugin-support.d.ts +0 -3
  559. package/runtime-plugin-support.js +0 -29
  560. package/runtime-plugin-support.js.map +0 -10
  561. package/runtime-plugin.d.ts +0 -16
  562. package/runtime-plugin.js +0 -16
  563. package/runtime-plugin.js.map +0 -9
  564. package/syntax-style.d.ts +0 -54
  565. package/testing/manual-clock.d.ts +0 -17
  566. package/testing/mock-keys.d.ts +0 -81
  567. package/testing/mock-mouse.d.ts +0 -38
  568. package/testing/mock-tree-sitter-client.d.ts +0 -23
  569. package/testing/spy.d.ts +0 -7
  570. package/testing/test-recorder.d.ts +0 -61
  571. package/testing/test-renderer.d.ts +0 -23
  572. package/testing.d.ts +0 -6
  573. package/testing.js +0 -697
  574. package/testing.js.map +0 -15
  575. package/text-buffer-view.d.ts +0 -42
  576. package/text-buffer.d.ts +0 -67
  577. package/types.d.ts +0 -139
  578. package/utils.d.ts +0 -14
  579. package/zig-structs.d.ts +0 -155
  580. package/zig.d.ts +0 -353
  581. /package/{assets → src/lib/tree-sitter/assets}/javascript/highlights.scm +0 -0
  582. /package/{assets → src/lib/tree-sitter/assets}/javascript/tree-sitter-javascript.wasm +0 -0
  583. /package/{assets → src/lib/tree-sitter/assets}/markdown/highlights.scm +0 -0
  584. /package/{assets → src/lib/tree-sitter/assets}/markdown/injections.scm +0 -0
  585. /package/{assets → src/lib/tree-sitter/assets}/markdown/tree-sitter-markdown.wasm +0 -0
  586. /package/{assets → src/lib/tree-sitter/assets}/markdown_inline/highlights.scm +0 -0
  587. /package/{assets → src/lib/tree-sitter/assets}/markdown_inline/tree-sitter-markdown_inline.wasm +0 -0
  588. /package/{assets → src/lib/tree-sitter/assets}/typescript/highlights.scm +0 -0
  589. /package/{assets → src/lib/tree-sitter/assets}/typescript/tree-sitter-typescript.wasm +0 -0
  590. /package/{assets → src/lib/tree-sitter/assets}/zig/highlights.scm +0 -0
  591. /package/{assets → src/lib/tree-sitter/assets}/zig/tree-sitter-zig.wasm +0 -0
@@ -0,0 +1,724 @@
1
+ import { Renderable, type RenderableOptions } from "../Renderable.js"
2
+ import { OptimizedBuffer } from "../buffer.js"
3
+ import type { RenderContext, LineInfoProvider } from "../types.js"
4
+ import { RGBA, parseColor } from "../lib/RGBA.js"
5
+ import { MeasureMode } from "yoga-layout"
6
+
7
+ export interface LineSign {
8
+ before?: string
9
+ beforeColor?: string | RGBA
10
+ after?: string
11
+ afterColor?: string | RGBA
12
+ }
13
+
14
+ export interface LineColorConfig {
15
+ gutter?: string | RGBA
16
+ content?: string | RGBA
17
+ }
18
+
19
+ export interface LineNumberOptions extends RenderableOptions<LineNumberRenderable> {
20
+ target?: Renderable & LineInfoProvider
21
+ fg?: string | RGBA
22
+ bg?: string | RGBA
23
+ minWidth?: number
24
+ paddingRight?: number
25
+ lineColors?: Map<number, string | RGBA | LineColorConfig>
26
+ lineSigns?: Map<number, LineSign>
27
+ lineNumberOffset?: number
28
+ hideLineNumbers?: Set<number>
29
+ lineNumbers?: Map<number, number>
30
+ showLineNumbers?: boolean
31
+ }
32
+
33
+ const DEFAULT_GUTTER_FG = "#888888"
34
+ const DEFAULT_GUTTER_BG = "transparent"
35
+
36
+ class GutterRenderable extends Renderable {
37
+ private target: Renderable & LineInfoProvider
38
+ private _fg: RGBA
39
+ private _bg: RGBA
40
+ private _minWidth: number
41
+ private _paddingRight: number
42
+ private _lineColorsGutter: Map<number, RGBA>
43
+ private _lineColorsContent: Map<number, RGBA>
44
+ private _lineSigns: Map<number, LineSign>
45
+ private _lineNumberOffset: number
46
+ private _hideLineNumbers: Set<number>
47
+ private _lineNumbers: Map<number, number>
48
+ private _maxBeforeWidth: number = 0
49
+ private _maxAfterWidth: number = 0
50
+ private _lastKnownLineCount: number = 0
51
+ private _lastKnownScrollY: number = 0
52
+
53
+ constructor(
54
+ ctx: RenderContext,
55
+ target: Renderable & LineInfoProvider,
56
+ options: {
57
+ fg: RGBA
58
+ bg: RGBA
59
+ minWidth: number
60
+ paddingRight: number
61
+ lineColorsGutter: Map<number, RGBA>
62
+ lineColorsContent: Map<number, RGBA>
63
+ lineSigns: Map<number, LineSign>
64
+ lineNumberOffset: number
65
+ hideLineNumbers: Set<number>
66
+ lineNumbers?: Map<number, number>
67
+ id?: string
68
+ buffered?: boolean
69
+ },
70
+ ) {
71
+ super(ctx, {
72
+ id: options.id,
73
+ width: "auto",
74
+ height: "auto",
75
+ flexGrow: 0,
76
+ flexShrink: 0,
77
+ buffered: options.buffered,
78
+ })
79
+ this.target = target
80
+ this._fg = options.fg
81
+ this._bg = options.bg
82
+ this._minWidth = options.minWidth
83
+ this._paddingRight = options.paddingRight
84
+ this._lineColorsGutter = options.lineColorsGutter
85
+ this._lineColorsContent = options.lineColorsContent
86
+ this._lineSigns = options.lineSigns
87
+ this._lineNumberOffset = options.lineNumberOffset
88
+ this._hideLineNumbers = options.hideLineNumbers
89
+ this._lineNumbers = options.lineNumbers ?? new Map()
90
+ this._lastKnownLineCount = this.target.virtualLineCount
91
+ this._lastKnownScrollY = this.target.scrollY
92
+ this.calculateSignWidths()
93
+ this.setupMeasureFunc()
94
+
95
+ // Use lifecycle pass to detect line count changes BEFORE layout
96
+ this.onLifecyclePass = () => {
97
+ const currentLineCount = this.target.virtualLineCount
98
+ if (currentLineCount !== this._lastKnownLineCount) {
99
+ this._lastKnownLineCount = currentLineCount
100
+ this.yogaNode.markDirty()
101
+ this.requestRender()
102
+ }
103
+ }
104
+ }
105
+
106
+ private setupMeasureFunc(): void {
107
+ const measureFunc = (
108
+ width: number,
109
+ widthMode: MeasureMode,
110
+ height: number,
111
+ heightMode: MeasureMode,
112
+ ): { width: number; height: number } => {
113
+ // Calculate the gutter width based on the target's line count
114
+ const gutterWidth = this.calculateWidth()
115
+
116
+ // Calculate gutter height based on target's actual virtual line count
117
+ // The gutter should match the height of the content it's numbering
118
+ const gutterHeight = this.target.virtualLineCount
119
+
120
+ // Return calculated dimensions based on content, not parent constraints
121
+ return {
122
+ width: gutterWidth,
123
+ height: gutterHeight,
124
+ }
125
+ }
126
+
127
+ this.yogaNode.setMeasureFunc(measureFunc)
128
+ }
129
+
130
+ public remeasure(): void {
131
+ // Mark the yoga node as dirty to trigger re-measurement
132
+ this.yogaNode.markDirty()
133
+ }
134
+
135
+ public setLineNumberOffset(offset: number): void {
136
+ if (this._lineNumberOffset !== offset) {
137
+ this._lineNumberOffset = offset
138
+ this.yogaNode.markDirty()
139
+ this.requestRender()
140
+ }
141
+ }
142
+
143
+ public setHideLineNumbers(hideLineNumbers: Set<number>): void {
144
+ this._hideLineNumbers = hideLineNumbers
145
+ this.yogaNode.markDirty()
146
+ this.requestRender()
147
+ }
148
+
149
+ public setLineNumbers(lineNumbers: Map<number, number>): void {
150
+ this._lineNumbers = lineNumbers
151
+ this.yogaNode.markDirty()
152
+ this.requestRender()
153
+ }
154
+
155
+ private calculateSignWidths(): void {
156
+ this._maxBeforeWidth = 0
157
+ this._maxAfterWidth = 0
158
+
159
+ for (const sign of this._lineSigns.values()) {
160
+ if (sign.before) {
161
+ const width = Bun.stringWidth(sign.before)
162
+ this._maxBeforeWidth = Math.max(this._maxBeforeWidth, width)
163
+ }
164
+ if (sign.after) {
165
+ const width = Bun.stringWidth(sign.after)
166
+ this._maxAfterWidth = Math.max(this._maxAfterWidth, width)
167
+ }
168
+ }
169
+ }
170
+
171
+ private calculateWidth(): number {
172
+ const totalLines = this.target.virtualLineCount
173
+
174
+ // Find max line number, considering both calculated and custom line numbers
175
+ let maxLineNumber = totalLines + this._lineNumberOffset
176
+ if (this._lineNumbers.size > 0) {
177
+ for (const customLineNum of this._lineNumbers.values()) {
178
+ maxLineNumber = Math.max(maxLineNumber, customLineNum)
179
+ }
180
+ }
181
+
182
+ const digits = maxLineNumber > 0 ? Math.floor(Math.log10(maxLineNumber)) + 1 : 1
183
+ const baseWidth = Math.max(this._minWidth, digits + this._paddingRight + 1) // +1 for left padding
184
+ return baseWidth + this._maxBeforeWidth + this._maxAfterWidth
185
+ }
186
+
187
+ public setLineColors(lineColorsGutter: Map<number, RGBA>, lineColorsContent: Map<number, RGBA>): void {
188
+ this._lineColorsGutter = lineColorsGutter
189
+ this._lineColorsContent = lineColorsContent
190
+ this.requestRender()
191
+ }
192
+
193
+ public get fg(): RGBA {
194
+ return this._fg
195
+ }
196
+
197
+ public setFg(fg: RGBA): void {
198
+ if (this._fg !== fg) {
199
+ this._fg = fg
200
+ this.requestRender()
201
+ }
202
+ }
203
+
204
+ public get bg(): RGBA {
205
+ return this._bg
206
+ }
207
+
208
+ public setBg(bg: RGBA): void {
209
+ if (this._bg !== bg) {
210
+ this._bg = bg
211
+ this.requestRender()
212
+ }
213
+ }
214
+
215
+ public getLineColors(): { gutter: Map<number, RGBA>; content: Map<number, RGBA> } {
216
+ return {
217
+ gutter: this._lineColorsGutter,
218
+ content: this._lineColorsContent,
219
+ }
220
+ }
221
+
222
+ public setLineSigns(lineSigns: Map<number, LineSign>): void {
223
+ const oldMaxBefore = this._maxBeforeWidth
224
+ const oldMaxAfter = this._maxAfterWidth
225
+
226
+ this._lineSigns = lineSigns
227
+ this.calculateSignWidths()
228
+
229
+ // Mark dirty if sign widths changed - this will trigger remeasure
230
+ if (this._maxBeforeWidth !== oldMaxBefore || this._maxAfterWidth !== oldMaxAfter) {
231
+ this.yogaNode.markDirty()
232
+ }
233
+
234
+ // Always request render since signs themselves may have changed
235
+ this.requestRender()
236
+ }
237
+
238
+ public getLineSigns(): Map<number, LineSign> {
239
+ return this._lineSigns
240
+ }
241
+
242
+ protected override renderSelf(buffer: OptimizedBuffer): void {
243
+ // For buffered rendering, only re-render when dirty OR when scroll position changed
244
+ const currentScrollY = this.target.scrollY
245
+ const scrollChanged = currentScrollY !== this._lastKnownScrollY
246
+
247
+ if (this.buffered && !this.isDirty && !scrollChanged) {
248
+ return
249
+ }
250
+
251
+ this._lastKnownScrollY = currentScrollY
252
+ this.refreshFrameBuffer(buffer)
253
+ }
254
+
255
+ private refreshFrameBuffer(buffer: OptimizedBuffer): void {
256
+ const startX = this.buffered ? 0 : this.x
257
+ const startY = this.buffered ? 0 : this.y
258
+
259
+ if (this.buffered) {
260
+ buffer.clear(this._bg)
261
+ } else if (this._bg.a > 0) {
262
+ // Fill background if not buffered and opaque (if buffered, clear handles it)
263
+ // Note: this.height might be determined by parent (flex stretch)
264
+ buffer.fillRect(startX, startY, this.width, this.height, this._bg)
265
+ }
266
+
267
+ const lineInfo = this.target.lineInfo
268
+ if (!lineInfo || !lineInfo.lineSources) return
269
+
270
+ const sources = lineInfo.lineSources
271
+ let lastSource = -1
272
+
273
+ // lineSources contains the logical line index for each visual line
274
+ // We start iterating from the scroll offset (first visible line)
275
+ const startLine = this.target.scrollY
276
+
277
+ // If scrolled past content (shouldn't happen normally but good to be safe)
278
+ if (startLine >= sources.length) return
279
+
280
+ // Get the logical line index of the line *before* the first visible line
281
+ // This helps determine if the first visible line is a wrapped continuation
282
+ lastSource = startLine > 0 ? sources[startLine - 1] : -1
283
+
284
+ for (let i = 0; i < this.height; i++) {
285
+ const visualLineIndex = startLine + i
286
+ if (visualLineIndex >= sources.length) break
287
+
288
+ const logicalLine = sources[visualLineIndex]
289
+ const lineBg = this._lineColorsGutter.get(logicalLine) ?? this._bg
290
+
291
+ // Fill background for this line if it has a custom color
292
+ if (lineBg !== this._bg) {
293
+ buffer.fillRect(startX, startY + i, this.width, 1, lineBg)
294
+ }
295
+
296
+ // Draw line number only for the first visual line of a logical line (wrapping)
297
+ if (logicalLine === lastSource) {
298
+ // Continuation line, maybe draw a dot or nothing
299
+ } else {
300
+ let currentX = startX
301
+
302
+ // Draw 'before' sign if present
303
+ const sign = this._lineSigns.get(logicalLine)
304
+ if (sign?.before) {
305
+ const beforeWidth = Bun.stringWidth(sign.before)
306
+ // Pad to max before width for alignment
307
+ const padding = this._maxBeforeWidth - beforeWidth
308
+ currentX += padding
309
+ const beforeColor = sign.beforeColor ? parseColor(sign.beforeColor) : this._fg
310
+ buffer.drawText(sign.before, currentX, startY + i, beforeColor, lineBg)
311
+ currentX += beforeWidth
312
+ } else if (this._maxBeforeWidth > 0) {
313
+ currentX += this._maxBeforeWidth
314
+ }
315
+
316
+ // Draw line number (right-aligned in its space with left padding of 1)
317
+ if (!this._hideLineNumbers.has(logicalLine)) {
318
+ // Use custom line number if provided, otherwise use calculated line number
319
+ const customLineNum = this._lineNumbers.get(logicalLine)
320
+ const lineNum = customLineNum !== undefined ? customLineNum : logicalLine + 1 + this._lineNumberOffset
321
+ const lineNumStr = lineNum.toString()
322
+ const lineNumWidth = lineNumStr.length
323
+ const availableSpace = this.width - this._maxBeforeWidth - this._maxAfterWidth - this._paddingRight
324
+ const lineNumX = startX + this._maxBeforeWidth + 1 + availableSpace - lineNumWidth - 1
325
+
326
+ if (lineNumX >= startX + this._maxBeforeWidth + 1) {
327
+ buffer.drawText(lineNumStr, lineNumX, startY + i, this._fg, lineBg)
328
+ }
329
+ }
330
+
331
+ // Draw 'after' sign if present
332
+ if (sign?.after) {
333
+ const afterX = startX + this.width - this._paddingRight - this._maxAfterWidth
334
+ const afterColor = sign.afterColor ? parseColor(sign.afterColor) : this._fg
335
+ buffer.drawText(sign.after, afterX, startY + i, afterColor, lineBg)
336
+ }
337
+ }
338
+
339
+ lastSource = logicalLine
340
+ }
341
+ }
342
+ }
343
+
344
+ // Helper function to darken an RGBA color by 20%
345
+ function darkenColor(color: RGBA): RGBA {
346
+ return RGBA.fromValues(color.r * 0.8, color.g * 0.8, color.b * 0.8, color.a)
347
+ }
348
+
349
+ export class LineNumberRenderable extends Renderable {
350
+ private gutter: GutterRenderable | null = null
351
+ private target: (Renderable & LineInfoProvider) | null = null
352
+ private _lineColorsGutter: Map<number, RGBA>
353
+ private _lineColorsContent: Map<number, RGBA>
354
+ private _lineSigns: Map<number, LineSign>
355
+ private _fg: RGBA
356
+ private _bg: RGBA
357
+ private _minWidth: number
358
+ private _paddingRight: number
359
+ private _lineNumberOffset: number
360
+ private _hideLineNumbers: Set<number>
361
+ private _lineNumbers: Map<number, number>
362
+ private _isDestroying: boolean = false
363
+ private handleLineInfoChange = (): void => {
364
+ // When line info changes in the target, remeasure the gutter
365
+ this.gutter?.remeasure()
366
+ this.requestRender()
367
+ }
368
+
369
+ private parseLineColor(line: number, color: string | RGBA | LineColorConfig): void {
370
+ if (typeof color === "object" && "gutter" in color) {
371
+ // LineColorConfig format
372
+ const config = color as LineColorConfig
373
+ if (config.gutter) {
374
+ this._lineColorsGutter.set(line, parseColor(config.gutter))
375
+ }
376
+ if (config.content) {
377
+ this._lineColorsContent.set(line, parseColor(config.content))
378
+ } else if (config.gutter) {
379
+ // If only gutter is specified, use a darker version for content
380
+ this._lineColorsContent.set(line, darkenColor(parseColor(config.gutter)))
381
+ }
382
+ } else {
383
+ // Simple format - same color for both, but content is darker
384
+ const parsedColor = parseColor(color as string | RGBA)
385
+ this._lineColorsGutter.set(line, parsedColor)
386
+ this._lineColorsContent.set(line, darkenColor(parsedColor))
387
+ }
388
+ }
389
+
390
+ constructor(ctx: RenderContext, options: LineNumberOptions) {
391
+ super(ctx, {
392
+ ...options,
393
+ flexDirection: "row",
394
+ // CRITICAL:
395
+ // By forcing height=auto, we ensure the parent box properly accounts for our full height.
396
+ height: "auto",
397
+ })
398
+
399
+ this._fg = parseColor(options.fg ?? DEFAULT_GUTTER_FG)
400
+ this._bg = parseColor(options.bg ?? DEFAULT_GUTTER_BG)
401
+ this._minWidth = options.minWidth ?? 3
402
+ this._paddingRight = options.paddingRight ?? 1
403
+ this._lineNumberOffset = options.lineNumberOffset ?? 0
404
+ this._hideLineNumbers = options.hideLineNumbers ?? new Set()
405
+ this._lineNumbers = options.lineNumbers ?? new Map()
406
+
407
+ this._lineColorsGutter = new Map<number, RGBA>()
408
+ this._lineColorsContent = new Map<number, RGBA>()
409
+ if (options.lineColors) {
410
+ for (const [line, color] of options.lineColors) {
411
+ this.parseLineColor(line, color)
412
+ }
413
+ }
414
+
415
+ this._lineSigns = new Map<number, LineSign>()
416
+ if (options.lineSigns) {
417
+ for (const [line, sign] of options.lineSigns) {
418
+ this._lineSigns.set(line, sign)
419
+ }
420
+ }
421
+
422
+ // If target is provided in constructor, set it up immediately
423
+ if (options.target) {
424
+ this.setTarget(options.target)
425
+ }
426
+ }
427
+
428
+ private setTarget(target: Renderable & LineInfoProvider): void {
429
+ if (this.target === target) return
430
+
431
+ if (this.target) {
432
+ // Remove event listener from old target
433
+ this.target.off("line-info-change", this.handleLineInfoChange)
434
+ super.remove(this.target.id)
435
+ }
436
+
437
+ if (this.gutter) {
438
+ super.remove(this.gutter.id)
439
+ this.gutter = null
440
+ }
441
+
442
+ this.target = target
443
+
444
+ // Listen for line info changes from target
445
+ this.target.on("line-info-change", this.handleLineInfoChange)
446
+
447
+ this.gutter = new GutterRenderable(this.ctx, this.target, {
448
+ fg: this._fg,
449
+ bg: this._bg,
450
+ minWidth: this._minWidth,
451
+ paddingRight: this._paddingRight,
452
+ lineColorsGutter: this._lineColorsGutter,
453
+ lineColorsContent: this._lineColorsContent,
454
+ lineSigns: this._lineSigns,
455
+ lineNumberOffset: this._lineNumberOffset,
456
+ hideLineNumbers: this._hideLineNumbers,
457
+ lineNumbers: this._lineNumbers,
458
+ id: this.id ? `${this.id}-gutter` : undefined,
459
+ buffered: true,
460
+ })
461
+
462
+ super.add(this.gutter)
463
+ super.add(this.target)
464
+ }
465
+
466
+ // Override add to intercept and set as target if it's a LineInfoProvider
467
+ public override add(child: Renderable): number {
468
+ // If this is a LineInfoProvider and we don't have a target yet, set it
469
+ if (
470
+ !this.target &&
471
+ "lineInfo" in child &&
472
+ "lineCount" in child &&
473
+ "virtualLineCount" in child &&
474
+ "scrollY" in child
475
+ ) {
476
+ this.setTarget(child as Renderable & LineInfoProvider)
477
+ return this.getChildrenCount() - 1
478
+ }
479
+ // Otherwise ignore - SolidJS may try to add layout slots or other helpers
480
+ return -1
481
+ }
482
+
483
+ // Override remove to prevent removing gutter/target directly
484
+ public override remove(id: string): void {
485
+ if (this._isDestroying) {
486
+ super.remove(id)
487
+ return
488
+ }
489
+
490
+ if (this.gutter && id === this.gutter.id) {
491
+ throw new Error("LineNumberRenderable: Cannot remove gutter directly.")
492
+ }
493
+ if (this.target && id === this.target.id) {
494
+ throw new Error("LineNumberRenderable: Cannot remove target directly. Use clearTarget() instead.")
495
+ }
496
+ super.remove(id)
497
+ }
498
+
499
+ // Override destroyRecursively to properly clean up internal components
500
+ public override destroyRecursively(): void {
501
+ this._isDestroying = true
502
+
503
+ if (this.target) {
504
+ this.target.off("line-info-change", this.handleLineInfoChange)
505
+ }
506
+
507
+ super.destroyRecursively()
508
+
509
+ this.gutter = null
510
+ this.target = null
511
+ }
512
+
513
+ public clearTarget(): void {
514
+ if (this.target) {
515
+ this.target.off("line-info-change", this.handleLineInfoChange)
516
+ super.remove(this.target.id)
517
+ this.target = null
518
+ }
519
+ if (this.gutter) {
520
+ super.remove(this.gutter.id)
521
+ this.gutter = null
522
+ }
523
+ }
524
+
525
+ protected override renderSelf(buffer: OptimizedBuffer): void {
526
+ // Draw full-width line backgrounds before children render
527
+ if (!this.target || !this.gutter) return
528
+
529
+ const lineInfo = this.target.lineInfo
530
+ if (!lineInfo || !lineInfo.lineSources) return
531
+
532
+ const sources = lineInfo.lineSources
533
+ const startLine = this.target.scrollY
534
+
535
+ if (startLine >= sources.length) return
536
+
537
+ // Calculate the area to fill: from after the gutter (if visible) to the end of our width
538
+ const gutterWidth = this.gutter.visible ? this.gutter.width : 0
539
+ const contentWidth = this.width - gutterWidth
540
+
541
+ // Draw full-width background colors for lines with custom colors
542
+ for (let i = 0; i < this.height; i++) {
543
+ const visualLineIndex = startLine + i
544
+ if (visualLineIndex >= sources.length) break
545
+
546
+ const logicalLine = sources[visualLineIndex]
547
+ const lineBg = this._lineColorsContent.get(logicalLine)
548
+
549
+ if (lineBg) {
550
+ // Fill from after gutter to the end of the LineNumberRenderable
551
+ buffer.fillRect(this.x + gutterWidth, this.y + i, contentWidth, 1, lineBg)
552
+ }
553
+ }
554
+ }
555
+
556
+ public set showLineNumbers(value: boolean) {
557
+ if (this.gutter) {
558
+ this.gutter.visible = value
559
+ }
560
+ }
561
+
562
+ public get showLineNumbers(): boolean {
563
+ return this.gutter?.visible ?? false
564
+ }
565
+
566
+ public get fg(): RGBA {
567
+ return this._fg
568
+ }
569
+
570
+ public set fg(value: string | RGBA | undefined) {
571
+ const parsed = parseColor(value ?? DEFAULT_GUTTER_FG)
572
+ if (this._fg !== parsed) {
573
+ this._fg = parsed
574
+ this.gutter?.setFg(parsed)
575
+ }
576
+ }
577
+
578
+ public get bg(): RGBA {
579
+ return this._bg
580
+ }
581
+
582
+ public set bg(value: string | RGBA | undefined) {
583
+ const parsed = parseColor(value ?? DEFAULT_GUTTER_BG)
584
+ if (this._bg !== parsed) {
585
+ this._bg = parsed
586
+ this.gutter?.setBg(parsed)
587
+ }
588
+ }
589
+
590
+ public setLineColor(line: number, color: string | RGBA | LineColorConfig): void {
591
+ this.parseLineColor(line, color)
592
+ // Update gutter if it exists
593
+ if (this.gutter) {
594
+ this.gutter.setLineColors(this._lineColorsGutter, this._lineColorsContent)
595
+ }
596
+ }
597
+
598
+ public clearLineColor(line: number): void {
599
+ this._lineColorsGutter.delete(line)
600
+ this._lineColorsContent.delete(line)
601
+ if (this.gutter) {
602
+ this.gutter.setLineColors(this._lineColorsGutter, this._lineColorsContent)
603
+ }
604
+ }
605
+
606
+ public clearAllLineColors(): void {
607
+ this._lineColorsGutter.clear()
608
+ this._lineColorsContent.clear()
609
+ if (this.gutter) {
610
+ this.gutter.setLineColors(this._lineColorsGutter, this._lineColorsContent)
611
+ }
612
+ }
613
+
614
+ public setLineColors(lineColors: Map<number, string | RGBA | LineColorConfig>): void {
615
+ this._lineColorsGutter.clear()
616
+ this._lineColorsContent.clear()
617
+ for (const [line, color] of lineColors) {
618
+ this.parseLineColor(line, color)
619
+ }
620
+ // Update gutter once after all colors are set
621
+ if (this.gutter) {
622
+ this.gutter.setLineColors(this._lineColorsGutter, this._lineColorsContent)
623
+ }
624
+ }
625
+
626
+ public getLineColors(): { gutter: Map<number, RGBA>; content: Map<number, RGBA> } {
627
+ return {
628
+ gutter: this._lineColorsGutter,
629
+ content: this._lineColorsContent,
630
+ }
631
+ }
632
+
633
+ public setLineSign(line: number, sign: LineSign): void {
634
+ this._lineSigns.set(line, sign)
635
+ if (this.gutter) {
636
+ this.gutter.setLineSigns(this._lineSigns)
637
+ }
638
+ }
639
+
640
+ public clearLineSign(line: number): void {
641
+ this._lineSigns.delete(line)
642
+ if (this.gutter) {
643
+ this.gutter.setLineSigns(this._lineSigns)
644
+ }
645
+ }
646
+
647
+ public clearAllLineSigns(): void {
648
+ this._lineSigns.clear()
649
+ if (this.gutter) {
650
+ this.gutter.setLineSigns(this._lineSigns)
651
+ }
652
+ }
653
+
654
+ public setLineSigns(lineSigns: Map<number, LineSign>): void {
655
+ this._lineSigns.clear()
656
+ for (const [line, sign] of lineSigns) {
657
+ this._lineSigns.set(line, sign)
658
+ }
659
+ if (this.gutter) {
660
+ this.gutter.setLineSigns(this._lineSigns)
661
+ }
662
+ }
663
+
664
+ public getLineSigns(): Map<number, LineSign> {
665
+ return this._lineSigns
666
+ }
667
+
668
+ public set lineNumberOffset(value: number) {
669
+ if (this._lineNumberOffset !== value) {
670
+ this._lineNumberOffset = value
671
+ if (this.gutter) {
672
+ // Update the gutter's offset using its setter
673
+ this.gutter.setLineNumberOffset(value)
674
+ }
675
+ }
676
+ }
677
+
678
+ public get lineNumberOffset(): number {
679
+ return this._lineNumberOffset
680
+ }
681
+
682
+ public setHideLineNumbers(hideLineNumbers: Set<number>): void {
683
+ this._hideLineNumbers = hideLineNumbers
684
+ if (this.gutter) {
685
+ // Update the gutter's hideLineNumbers using its setter
686
+ this.gutter.setHideLineNumbers(hideLineNumbers)
687
+ }
688
+ }
689
+
690
+ public getHideLineNumbers(): Set<number> {
691
+ return this._hideLineNumbers
692
+ }
693
+
694
+ public setLineNumbers(lineNumbers: Map<number, number>): void {
695
+ this._lineNumbers = lineNumbers
696
+ if (this.gutter) {
697
+ // Update the gutter's lineNumbers using its setter
698
+ this.gutter.setLineNumbers(lineNumbers)
699
+ }
700
+ }
701
+
702
+ public getLineNumbers(): Map<number, number> {
703
+ return this._lineNumbers
704
+ }
705
+
706
+ public highlightLines(startLine: number, endLine: number, color: string | RGBA | LineColorConfig): void {
707
+ for (let i = startLine; i <= endLine; i++) {
708
+ this.parseLineColor(i, color)
709
+ }
710
+ if (this.gutter) {
711
+ this.gutter.setLineColors(this._lineColorsGutter, this._lineColorsContent)
712
+ }
713
+ }
714
+
715
+ public clearHighlightLines(startLine: number, endLine: number): void {
716
+ for (let i = startLine; i <= endLine; i++) {
717
+ this._lineColorsGutter.delete(i)
718
+ this._lineColorsContent.delete(i)
719
+ }
720
+ if (this.gutter) {
721
+ this.gutter.setLineColors(this._lineColorsGutter, this._lineColorsContent)
722
+ }
723
+ }
724
+ }