@fairyhunter13/opentui-core 0.1.90 → 0.1.92

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 (571) hide show
  1. package/3d/SpriteResourceManager.d.ts +74 -0
  2. package/3d/SpriteUtils.d.ts +13 -0
  3. package/3d/TextureUtils.d.ts +24 -0
  4. package/3d/ThreeRenderable.d.ts +40 -0
  5. package/3d/WGPURenderer.d.ts +61 -0
  6. package/3d/animation/ExplodingSpriteEffect.d.ts +71 -0
  7. package/3d/animation/PhysicsExplodingSpriteEffect.d.ts +76 -0
  8. package/3d/animation/SpriteAnimator.d.ts +124 -0
  9. package/3d/animation/SpriteParticleGenerator.d.ts +62 -0
  10. package/3d/canvas.d.ts +44 -0
  11. package/3d/index.d.ts +12 -0
  12. package/3d/physics/PlanckPhysicsAdapter.d.ts +19 -0
  13. package/3d/physics/RapierPhysicsAdapter.d.ts +19 -0
  14. package/3d/physics/physics-interface.d.ts +27 -0
  15. package/3d.d.ts +2 -0
  16. package/3d.js +34042 -0
  17. package/3d.js.map +155 -0
  18. package/LICENSE +21 -0
  19. package/NativeSpanFeed.d.ts +41 -0
  20. package/README.md +2 -2
  21. package/Renderable.d.ts +334 -0
  22. package/animation/Timeline.d.ts +126 -0
  23. package/ansi.d.ts +13 -0
  24. package/buffer.d.ts +107 -0
  25. package/console.d.ts +143 -0
  26. package/edit-buffer.d.ts +98 -0
  27. package/editor-view.d.ts +73 -0
  28. package/index-e6ec7apq.js +18415 -0
  29. package/index-e6ec7apq.js.map +64 -0
  30. package/index-h066zmrb.js +12619 -0
  31. package/index-h066zmrb.js.map +43 -0
  32. package/index-ynzawt3n.js +113 -0
  33. package/index-ynzawt3n.js.map +10 -0
  34. package/index.d.ts +21 -0
  35. package/index.js +430 -0
  36. package/index.js.map +9 -0
  37. package/lib/KeyHandler.d.ts +61 -0
  38. package/lib/RGBA.d.ts +25 -0
  39. package/lib/ascii.font.d.ts +508 -0
  40. package/lib/border.d.ts +49 -0
  41. package/lib/bunfs.d.ts +7 -0
  42. package/lib/clipboard.d.ts +17 -0
  43. package/lib/clock.d.ts +15 -0
  44. package/lib/data-paths.d.ts +26 -0
  45. package/lib/debounce.d.ts +42 -0
  46. package/lib/detect-links.d.ts +6 -0
  47. package/lib/env.d.ts +42 -0
  48. package/lib/extmarks-history.d.ts +17 -0
  49. package/lib/extmarks.d.ts +89 -0
  50. package/lib/hast-styled-text.d.ts +17 -0
  51. package/lib/index.d.ts +21 -0
  52. package/lib/keymapping.d.ts +25 -0
  53. package/lib/objects-in-viewport.d.ts +24 -0
  54. package/lib/output.capture.d.ts +24 -0
  55. package/lib/parse.keypress-kitty.d.ts +2 -0
  56. package/lib/parse.keypress.d.ts +26 -0
  57. package/lib/parse.mouse.d.ts +30 -0
  58. package/lib/paste.d.ts +7 -0
  59. package/lib/queue.d.ts +15 -0
  60. package/lib/renderable.validations.d.ts +12 -0
  61. package/lib/scroll-acceleration.d.ts +43 -0
  62. package/lib/selection.d.ts +63 -0
  63. package/lib/singleton.d.ts +7 -0
  64. package/lib/stdin-parser.d.ts +76 -0
  65. package/lib/styled-text.d.ts +63 -0
  66. package/lib/terminal-capability-detection.d.ts +30 -0
  67. package/lib/terminal-palette.d.ts +50 -0
  68. package/lib/tree-sitter/assets/update.d.ts +11 -0
  69. package/lib/tree-sitter/client.d.ts +47 -0
  70. package/lib/tree-sitter/default-parsers.d.ts +2 -0
  71. package/lib/tree-sitter/download-utils.d.ts +21 -0
  72. package/lib/tree-sitter/index.d.ts +8 -0
  73. package/lib/tree-sitter/parser.worker.d.ts +1 -0
  74. package/lib/tree-sitter/parsers-config.d.ts +38 -0
  75. package/lib/tree-sitter/resolve-ft.d.ts +2 -0
  76. package/lib/tree-sitter/types.d.ts +81 -0
  77. package/lib/tree-sitter-styled-text.d.ts +14 -0
  78. package/lib/validate-dir-name.d.ts +1 -0
  79. package/lib/yoga.options.d.ts +32 -0
  80. package/package.json +51 -63
  81. package/parser.worker.js +869 -0
  82. package/parser.worker.js.map +12 -0
  83. package/plugins/core-slot.d.ts +72 -0
  84. package/plugins/registry.d.ts +38 -0
  85. package/plugins/types.d.ts +34 -0
  86. package/post/filters.d.ts +105 -0
  87. package/renderables/ASCIIFont.d.ts +52 -0
  88. package/renderables/Box.d.ts +72 -0
  89. package/renderables/Code.d.ts +78 -0
  90. package/renderables/Diff.d.ts +142 -0
  91. package/renderables/EditBufferRenderable.d.ts +162 -0
  92. package/renderables/FrameBuffer.d.ts +16 -0
  93. package/renderables/Input.d.ts +67 -0
  94. package/renderables/LineNumberRenderable.d.ts +74 -0
  95. package/renderables/Markdown.d.ts +173 -0
  96. package/renderables/ScrollBar.d.ts +77 -0
  97. package/renderables/ScrollBox.d.ts +124 -0
  98. package/renderables/Select.d.ts +115 -0
  99. package/renderables/Slider.d.ts +44 -0
  100. package/renderables/TabSelect.d.ts +96 -0
  101. package/renderables/Text.d.ts +36 -0
  102. package/renderables/TextBufferRenderable.d.ts +105 -0
  103. package/renderables/TextNode.d.ts +91 -0
  104. package/renderables/TextTable.d.ts +140 -0
  105. package/renderables/Textarea.d.ts +114 -0
  106. package/renderables/TimeToFirstDraw.d.ts +24 -0
  107. package/renderables/__tests__/renderable-test-utils.d.ts +12 -0
  108. package/renderables/composition/VRenderable.d.ts +16 -0
  109. package/renderables/composition/constructs.d.ts +35 -0
  110. package/renderables/composition/vnode.d.ts +46 -0
  111. package/renderables/index.d.ts +22 -0
  112. package/renderables/markdown-parser.d.ts +10 -0
  113. package/renderer.d.ts +388 -0
  114. package/runtime-plugin-support.d.ts +3 -0
  115. package/runtime-plugin-support.js +29 -0
  116. package/runtime-plugin-support.js.map +10 -0
  117. package/runtime-plugin.d.ts +11 -0
  118. package/runtime-plugin.js +16 -0
  119. package/runtime-plugin.js.map +9 -0
  120. package/syntax-style.d.ts +54 -0
  121. package/testing/manual-clock.d.ts +16 -0
  122. package/testing/mock-keys.d.ts +81 -0
  123. package/testing/mock-mouse.d.ts +38 -0
  124. package/testing/mock-tree-sitter-client.d.ts +23 -0
  125. package/testing/spy.d.ts +7 -0
  126. package/testing/test-recorder.d.ts +61 -0
  127. package/testing/test-renderer.d.ts +23 -0
  128. package/testing.d.ts +6 -0
  129. package/testing.js +675 -0
  130. package/testing.js.map +15 -0
  131. package/text-buffer-view.d.ts +42 -0
  132. package/text-buffer.d.ts +67 -0
  133. package/types.d.ts +131 -0
  134. package/utils.d.ts +14 -0
  135. package/zig-structs.d.ts +155 -0
  136. package/zig.d.ts +351 -0
  137. package/dev/keypress-debug-renderer.ts +0 -148
  138. package/dev/keypress-debug.ts +0 -43
  139. package/dev/print-env-vars.ts +0 -32
  140. package/dev/test-tmux-graphics-334.sh +0 -68
  141. package/dev/thai-debug-test.ts +0 -68
  142. package/docs/development.md +0 -141
  143. package/docs/env-vars.md +0 -140
  144. package/docs/getting-started.md +0 -353
  145. package/docs/renderables-vs-constructs.md +0 -159
  146. package/docs/tree-sitter.md +0 -311
  147. package/scripts/build.ts +0 -400
  148. package/scripts/publish.ts +0 -60
  149. package/src/3d/SpriteResourceManager.ts +0 -286
  150. package/src/3d/SpriteUtils.ts +0 -71
  151. package/src/3d/TextureUtils.ts +0 -196
  152. package/src/3d/ThreeRenderable.ts +0 -197
  153. package/src/3d/WGPURenderer.ts +0 -294
  154. package/src/3d/animation/ExplodingSpriteEffect.ts +0 -513
  155. package/src/3d/animation/PhysicsExplodingSpriteEffect.ts +0 -429
  156. package/src/3d/animation/SpriteAnimator.ts +0 -633
  157. package/src/3d/animation/SpriteParticleGenerator.ts +0 -435
  158. package/src/3d/canvas.ts +0 -464
  159. package/src/3d/index.ts +0 -12
  160. package/src/3d/physics/PlanckPhysicsAdapter.ts +0 -72
  161. package/src/3d/physics/RapierPhysicsAdapter.ts +0 -66
  162. package/src/3d/physics/physics-interface.ts +0 -31
  163. package/src/3d/shaders/supersampling.wgsl +0 -201
  164. package/src/3d.ts +0 -3
  165. package/src/NativeSpanFeed.ts +0 -300
  166. package/src/Renderable.ts +0 -1698
  167. package/src/__snapshots__/buffer.test.ts.snap +0 -28
  168. package/src/animation/Timeline.test.ts +0 -2709
  169. package/src/animation/Timeline.ts +0 -598
  170. package/src/ansi.ts +0 -18
  171. package/src/benchmark/latest-all-bench-run.json +0 -707
  172. package/src/benchmark/latest-async-bench-run.json +0 -336
  173. package/src/benchmark/latest-default-bench-run.json +0 -657
  174. package/src/benchmark/latest-large-bench-run.json +0 -707
  175. package/src/benchmark/latest-quick-bench-run.json +0 -207
  176. package/src/benchmark/markdown-benchmark.ts +0 -1804
  177. package/src/benchmark/native-span-feed-async-benchmark.ts +0 -355
  178. package/src/benchmark/native-span-feed-benchmark.md +0 -56
  179. package/src/benchmark/native-span-feed-benchmark.ts +0 -596
  180. package/src/benchmark/native-span-feed-compare.ts +0 -280
  181. package/src/benchmark/renderer-benchmark.ts +0 -754
  182. package/src/benchmark/text-table-benchmark.ts +0 -947
  183. package/src/buffer.test.ts +0 -291
  184. package/src/buffer.ts +0 -519
  185. package/src/console.test.ts +0 -612
  186. package/src/console.ts +0 -1255
  187. package/src/edit-buffer.test.ts +0 -1769
  188. package/src/edit-buffer.ts +0 -411
  189. package/src/editor-view.test.ts +0 -1032
  190. package/src/editor-view.ts +0 -284
  191. package/src/examples/ascii-font-selection-demo.ts +0 -245
  192. package/src/examples/assets/Water_2_M_Normal.jpg +0 -0
  193. package/src/examples/assets/concrete.png +0 -0
  194. package/src/examples/assets/crate.png +0 -0
  195. package/src/examples/assets/crate_emissive.png +0 -0
  196. package/src/examples/assets/forrest_background.png +0 -0
  197. package/src/examples/assets/hast-example.json +0 -1018
  198. package/src/examples/assets/heart.png +0 -0
  199. package/src/examples/assets/main_char_heavy_attack.png +0 -0
  200. package/src/examples/assets/main_char_idle.png +0 -0
  201. package/src/examples/assets/main_char_jump_end.png +0 -0
  202. package/src/examples/assets/main_char_jump_landing.png +0 -0
  203. package/src/examples/assets/main_char_jump_start.png +0 -0
  204. package/src/examples/assets/main_char_run_loop.png +0 -0
  205. package/src/examples/assets/roughness_map.jpg +0 -0
  206. package/src/examples/build.ts +0 -115
  207. package/src/examples/code-demo.ts +0 -584
  208. package/src/examples/console-demo.ts +0 -358
  209. package/src/examples/core-plugin-slots-demo.ts +0 -759
  210. package/src/examples/diff-demo.ts +0 -699
  211. package/src/examples/draggable-three-demo.ts +0 -259
  212. package/src/examples/editor-demo.ts +0 -322
  213. package/src/examples/extmarks-demo.ts +0 -204
  214. package/src/examples/focus-restore-demo.ts +0 -310
  215. package/src/examples/fonts.ts +0 -245
  216. package/src/examples/fractal-shader-demo.ts +0 -268
  217. package/src/examples/framebuffer-demo.ts +0 -674
  218. package/src/examples/full-unicode-demo.ts +0 -181
  219. package/src/examples/golden-star-demo.ts +0 -933
  220. package/src/examples/grayscale-buffer-demo.ts +0 -249
  221. package/src/examples/hast-syntax-highlighting-demo.ts +0 -129
  222. package/src/examples/index.ts +0 -925
  223. package/src/examples/input-demo.ts +0 -377
  224. package/src/examples/input-select-layout-demo.ts +0 -425
  225. package/src/examples/install.sh +0 -143
  226. package/src/examples/keypress-debug-demo.ts +0 -452
  227. package/src/examples/lib/HexList.ts +0 -122
  228. package/src/examples/lib/PaletteGrid.ts +0 -125
  229. package/src/examples/lib/standalone-keys.ts +0 -25
  230. package/src/examples/lib/tab-controller.ts +0 -243
  231. package/src/examples/lights-phong-demo.ts +0 -290
  232. package/src/examples/link-demo.ts +0 -220
  233. package/src/examples/live-state-demo.ts +0 -480
  234. package/src/examples/markdown-demo.ts +0 -620
  235. package/src/examples/mouse-interaction-demo.ts +0 -428
  236. package/src/examples/nested-zindex-demo.ts +0 -357
  237. package/src/examples/opacity-example.ts +0 -235
  238. package/src/examples/opentui-demo.ts +0 -1057
  239. package/src/examples/physx-planck-2d-demo.ts +0 -507
  240. package/src/examples/physx-rapier-2d-demo.ts +0 -526
  241. package/src/examples/relative-positioning-demo.ts +0 -323
  242. package/src/examples/scroll-example.ts +0 -214
  243. package/src/examples/scrollbox-mouse-test.ts +0 -112
  244. package/src/examples/scrollbox-overlay-hit-test.ts +0 -206
  245. package/src/examples/select-demo.ts +0 -237
  246. package/src/examples/shader-cube-demo.ts +0 -772
  247. package/src/examples/simple-layout-example.ts +0 -591
  248. package/src/examples/slider-demo.ts +0 -617
  249. package/src/examples/split-mode-demo.ts +0 -445
  250. package/src/examples/sprite-animation-demo.ts +0 -443
  251. package/src/examples/sprite-particle-generator-demo.ts +0 -486
  252. package/src/examples/static-sprite-demo.ts +0 -193
  253. package/src/examples/sticky-scroll-example.ts +0 -308
  254. package/src/examples/styled-text-demo.ts +0 -282
  255. package/src/examples/tab-select-demo.ts +0 -219
  256. package/src/examples/terminal-title.ts +0 -29
  257. package/src/examples/terminal.ts +0 -305
  258. package/src/examples/text-node-demo.ts +0 -416
  259. package/src/examples/text-selection-demo.ts +0 -377
  260. package/src/examples/text-table-demo.ts +0 -503
  261. package/src/examples/text-truncation-demo.ts +0 -481
  262. package/src/examples/text-wrap.ts +0 -757
  263. package/src/examples/texture-loading-demo.ts +0 -259
  264. package/src/examples/timeline-example.ts +0 -670
  265. package/src/examples/transparency-demo.ts +0 -241
  266. package/src/examples/vnode-composition-demo.ts +0 -404
  267. package/src/index.ts +0 -22
  268. package/src/lib/KeyHandler.integration.test.ts +0 -292
  269. package/src/lib/KeyHandler.stopPropagation.test.ts +0 -289
  270. package/src/lib/KeyHandler.test.ts +0 -662
  271. package/src/lib/KeyHandler.ts +0 -222
  272. package/src/lib/RGBA.test.ts +0 -984
  273. package/src/lib/RGBA.ts +0 -204
  274. package/src/lib/ascii.font.ts +0 -330
  275. package/src/lib/border.test.ts +0 -83
  276. package/src/lib/border.ts +0 -168
  277. package/src/lib/bunfs.test.ts +0 -27
  278. package/src/lib/bunfs.ts +0 -18
  279. package/src/lib/clipboard.test.ts +0 -41
  280. package/src/lib/clipboard.ts +0 -47
  281. package/src/lib/clock.ts +0 -31
  282. package/src/lib/data-paths.test.ts +0 -133
  283. package/src/lib/data-paths.ts +0 -109
  284. package/src/lib/debounce.ts +0 -106
  285. package/src/lib/detect-links.test.ts +0 -98
  286. package/src/lib/detect-links.ts +0 -56
  287. package/src/lib/env.test.ts +0 -228
  288. package/src/lib/env.ts +0 -209
  289. package/src/lib/extmarks-history.ts +0 -51
  290. package/src/lib/extmarks-multiwidth.test.ts +0 -322
  291. package/src/lib/extmarks.test.ts +0 -3457
  292. package/src/lib/extmarks.ts +0 -843
  293. package/src/lib/fonts/block.json +0 -405
  294. package/src/lib/fonts/grid.json +0 -265
  295. package/src/lib/fonts/huge.json +0 -741
  296. package/src/lib/fonts/pallet.json +0 -314
  297. package/src/lib/fonts/shade.json +0 -591
  298. package/src/lib/fonts/slick.json +0 -321
  299. package/src/lib/fonts/tiny.json +0 -69
  300. package/src/lib/hast-styled-text.ts +0 -59
  301. package/src/lib/index.ts +0 -21
  302. package/src/lib/keymapping.test.ts +0 -280
  303. package/src/lib/keymapping.ts +0 -87
  304. package/src/lib/objects-in-viewport.test.ts +0 -787
  305. package/src/lib/objects-in-viewport.ts +0 -153
  306. package/src/lib/output.capture.ts +0 -58
  307. package/src/lib/parse.keypress-kitty.protocol.test.ts +0 -340
  308. package/src/lib/parse.keypress-kitty.test.ts +0 -663
  309. package/src/lib/parse.keypress-kitty.ts +0 -439
  310. package/src/lib/parse.keypress.test.ts +0 -1849
  311. package/src/lib/parse.keypress.ts +0 -397
  312. package/src/lib/parse.mouse.test.ts +0 -552
  313. package/src/lib/parse.mouse.ts +0 -232
  314. package/src/lib/paste.ts +0 -16
  315. package/src/lib/queue.ts +0 -65
  316. package/src/lib/renderable.validations.test.ts +0 -87
  317. package/src/lib/renderable.validations.ts +0 -83
  318. package/src/lib/scroll-acceleration.ts +0 -98
  319. package/src/lib/selection.ts +0 -240
  320. package/src/lib/singleton.ts +0 -28
  321. package/src/lib/stdin-parser.test.ts +0 -1676
  322. package/src/lib/stdin-parser.ts +0 -1248
  323. package/src/lib/styled-text.ts +0 -178
  324. package/src/lib/terminal-capability-detection.test.ts +0 -202
  325. package/src/lib/terminal-capability-detection.ts +0 -79
  326. package/src/lib/terminal-palette.test.ts +0 -878
  327. package/src/lib/terminal-palette.ts +0 -383
  328. package/src/lib/tree-sitter/assets/README.md +0 -118
  329. package/src/lib/tree-sitter/assets/update.ts +0 -331
  330. package/src/lib/tree-sitter/assets.d.ts +0 -9
  331. package/src/lib/tree-sitter/cache.test.ts +0 -270
  332. package/src/lib/tree-sitter/client.test.ts +0 -1061
  333. package/src/lib/tree-sitter/client.ts +0 -615
  334. package/src/lib/tree-sitter/default-parsers.ts +0 -80
  335. package/src/lib/tree-sitter/download-utils.ts +0 -148
  336. package/src/lib/tree-sitter/index.ts +0 -28
  337. package/src/lib/tree-sitter/parser.worker.ts +0 -1001
  338. package/src/lib/tree-sitter/parsers-config.ts +0 -75
  339. package/src/lib/tree-sitter/resolve-ft.ts +0 -62
  340. package/src/lib/tree-sitter/types.ts +0 -81
  341. package/src/lib/tree-sitter-styled-text.test.ts +0 -1253
  342. package/src/lib/tree-sitter-styled-text.ts +0 -306
  343. package/src/lib/validate-dir-name.ts +0 -55
  344. package/src/lib/yoga.options.test.ts +0 -628
  345. package/src/lib/yoga.options.ts +0 -346
  346. package/src/plugins/core-slot.ts +0 -579
  347. package/src/plugins/registry.ts +0 -377
  348. package/src/plugins/types.ts +0 -46
  349. package/src/post/filters.ts +0 -888
  350. package/src/renderables/ASCIIFont.ts +0 -219
  351. package/src/renderables/Box.test.ts +0 -160
  352. package/src/renderables/Box.ts +0 -295
  353. package/src/renderables/Code.test.ts +0 -2062
  354. package/src/renderables/Code.ts +0 -357
  355. package/src/renderables/Diff.regression.test.ts +0 -226
  356. package/src/renderables/Diff.test.ts +0 -3027
  357. package/src/renderables/Diff.ts +0 -1209
  358. package/src/renderables/EditBufferRenderable.ts +0 -764
  359. package/src/renderables/FrameBuffer.ts +0 -47
  360. package/src/renderables/Input.test.ts +0 -1228
  361. package/src/renderables/Input.ts +0 -245
  362. package/src/renderables/LineNumberRenderable.ts +0 -675
  363. package/src/renderables/Markdown.ts +0 -1106
  364. package/src/renderables/ScrollBar.ts +0 -422
  365. package/src/renderables/ScrollBox.ts +0 -883
  366. package/src/renderables/Select.test.ts +0 -1010
  367. package/src/renderables/Select.ts +0 -523
  368. package/src/renderables/Slider.test.ts +0 -456
  369. package/src/renderables/Slider.ts +0 -347
  370. package/src/renderables/TabSelect.test.ts +0 -197
  371. package/src/renderables/TabSelect.ts +0 -455
  372. package/src/renderables/Text.selection-buffer.test.ts +0 -123
  373. package/src/renderables/Text.test.ts +0 -2660
  374. package/src/renderables/Text.ts +0 -147
  375. package/src/renderables/TextBufferRenderable.ts +0 -518
  376. package/src/renderables/TextNode.test.ts +0 -1058
  377. package/src/renderables/TextNode.ts +0 -325
  378. package/src/renderables/TextTable.test.ts +0 -1421
  379. package/src/renderables/TextTable.ts +0 -1344
  380. package/src/renderables/Textarea.ts +0 -732
  381. package/src/renderables/TimeToFirstDraw.ts +0 -89
  382. package/src/renderables/__snapshots__/Code.test.ts.snap +0 -13
  383. package/src/renderables/__snapshots__/Diff.test.ts.snap +0 -785
  384. package/src/renderables/__snapshots__/Text.test.ts.snap +0 -421
  385. package/src/renderables/__snapshots__/TextTable.test.ts.snap +0 -215
  386. package/src/renderables/__tests__/LineNumberRenderable.scrollbox-simple.test.ts +0 -144
  387. package/src/renderables/__tests__/LineNumberRenderable.scrollbox.test.ts +0 -816
  388. package/src/renderables/__tests__/LineNumberRenderable.test.ts +0 -1787
  389. package/src/renderables/__tests__/LineNumberRenderable.wrapping.test.ts +0 -85
  390. package/src/renderables/__tests__/Markdown.test.ts +0 -2287
  391. package/src/renderables/__tests__/MultiRenderable.selection.test.ts +0 -87
  392. package/src/renderables/__tests__/Textarea.buffer.test.ts +0 -682
  393. package/src/renderables/__tests__/Textarea.destroyed-events.test.ts +0 -675
  394. package/src/renderables/__tests__/Textarea.editing.test.ts +0 -2041
  395. package/src/renderables/__tests__/Textarea.error-handling.test.ts +0 -35
  396. package/src/renderables/__tests__/Textarea.events.test.ts +0 -738
  397. package/src/renderables/__tests__/Textarea.highlights.test.ts +0 -590
  398. package/src/renderables/__tests__/Textarea.keybinding.test.ts +0 -3149
  399. package/src/renderables/__tests__/Textarea.paste.test.ts +0 -357
  400. package/src/renderables/__tests__/Textarea.rendering.test.ts +0 -1864
  401. package/src/renderables/__tests__/Textarea.scroll.test.ts +0 -733
  402. package/src/renderables/__tests__/Textarea.selection.test.ts +0 -1590
  403. package/src/renderables/__tests__/Textarea.stress.test.ts +0 -670
  404. package/src/renderables/__tests__/Textarea.undo-redo.test.ts +0 -383
  405. package/src/renderables/__tests__/Textarea.visual-lines.test.ts +0 -310
  406. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.code.test.ts.snap +0 -221
  407. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox-simple.test.ts.snap +0 -89
  408. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox.test.ts.snap +0 -457
  409. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.test.ts.snap +0 -158
  410. package/src/renderables/__tests__/__snapshots__/Textarea.rendering.test.ts.snap +0 -387
  411. package/src/renderables/__tests__/markdown-parser.test.ts +0 -217
  412. package/src/renderables/__tests__/renderable-test-utils.ts +0 -60
  413. package/src/renderables/composition/README.md +0 -8
  414. package/src/renderables/composition/VRenderable.ts +0 -32
  415. package/src/renderables/composition/constructs.ts +0 -127
  416. package/src/renderables/composition/vnode.ts +0 -289
  417. package/src/renderables/index.ts +0 -22
  418. package/src/renderables/markdown-parser.ts +0 -66
  419. package/src/renderer.ts +0 -2363
  420. package/src/runtime-plugin-support.ts +0 -39
  421. package/src/runtime-plugin.ts +0 -144
  422. package/src/syntax-style.test.ts +0 -841
  423. package/src/syntax-style.ts +0 -264
  424. package/src/testing/README.md +0 -210
  425. package/src/testing/capture-spans.test.ts +0 -194
  426. package/src/testing/integration.test.ts +0 -276
  427. package/src/testing/manual-clock.ts +0 -106
  428. package/src/testing/mock-keys.test.ts +0 -1356
  429. package/src/testing/mock-keys.ts +0 -449
  430. package/src/testing/mock-mouse.test.ts +0 -218
  431. package/src/testing/mock-mouse.ts +0 -247
  432. package/src/testing/mock-tree-sitter-client.ts +0 -73
  433. package/src/testing/spy.ts +0 -13
  434. package/src/testing/test-recorder.test.ts +0 -415
  435. package/src/testing/test-recorder.ts +0 -145
  436. package/src/testing/test-renderer.ts +0 -116
  437. package/src/testing.ts +0 -7
  438. package/src/tests/__snapshots__/absolute-positioning.snapshot.test.ts.snap +0 -481
  439. package/src/tests/__snapshots__/renderable.snapshot.test.ts.snap +0 -19
  440. package/src/tests/__snapshots__/scrollbox.test.ts.snap +0 -29
  441. package/src/tests/absolute-positioning.snapshot.test.ts +0 -638
  442. package/src/tests/allocator-stats.test.ts +0 -38
  443. package/src/tests/destroy-during-render.test.ts +0 -200
  444. package/src/tests/hover-cursor.test.ts +0 -98
  445. package/src/tests/native-span-feed-async.test.ts +0 -173
  446. package/src/tests/native-span-feed-close.test.ts +0 -120
  447. package/src/tests/native-span-feed-coverage.test.ts +0 -227
  448. package/src/tests/native-span-feed-edge-cases.test.ts +0 -352
  449. package/src/tests/native-span-feed-use-after-free.test.ts +0 -45
  450. package/src/tests/opacity.test.ts +0 -123
  451. package/src/tests/renderable.snapshot.test.ts +0 -524
  452. package/src/tests/renderable.test.ts +0 -1281
  453. package/src/tests/renderer.console-startup.test.ts +0 -65
  454. package/src/tests/renderer.control.test.ts +0 -364
  455. package/src/tests/renderer.core-slot-binding.test.ts +0 -952
  456. package/src/tests/renderer.cursor.test.ts +0 -26
  457. package/src/tests/renderer.destroy-during-render.test.ts +0 -110
  458. package/src/tests/renderer.focus-restore.test.ts +0 -228
  459. package/src/tests/renderer.focus.test.ts +0 -251
  460. package/src/tests/renderer.idle.test.ts +0 -219
  461. package/src/tests/renderer.input.test.ts +0 -2145
  462. package/src/tests/renderer.kitty-flags.test.ts +0 -195
  463. package/src/tests/renderer.mouse.test.ts +0 -1269
  464. package/src/tests/renderer.palette.test.ts +0 -629
  465. package/src/tests/renderer.selection.test.ts +0 -49
  466. package/src/tests/renderer.slot-registry.test.ts +0 -649
  467. package/src/tests/renderer.useMouse.test.ts +0 -50
  468. package/src/tests/runtime-plugin-support.fixture.ts +0 -11
  469. package/src/tests/runtime-plugin-support.test.ts +0 -28
  470. package/src/tests/runtime-plugin.fixture.ts +0 -40
  471. package/src/tests/runtime-plugin.test.ts +0 -190
  472. package/src/tests/scrollbox-culling-bug.test.ts +0 -114
  473. package/src/tests/scrollbox-hitgrid-resize.test.ts +0 -136
  474. package/src/tests/scrollbox-hitgrid.test.ts +0 -909
  475. package/src/tests/scrollbox.test.ts +0 -1530
  476. package/src/tests/wrap-resize-perf.test.ts +0 -229
  477. package/src/tests/yoga-setters.test.ts +0 -921
  478. package/src/text-buffer-view.test.ts +0 -705
  479. package/src/text-buffer-view.ts +0 -189
  480. package/src/text-buffer.test.ts +0 -347
  481. package/src/text-buffer.ts +0 -250
  482. package/src/types.ts +0 -152
  483. package/src/utils.ts +0 -88
  484. package/src/zig/ansi.zig +0 -268
  485. package/src/zig/bench/README.md +0 -50
  486. package/src/zig/bench/buffer-draw-text-buffer_bench.zig +0 -887
  487. package/src/zig/bench/edit-buffer_bench.zig +0 -476
  488. package/src/zig/bench/native-span-feed_bench.zig +0 -100
  489. package/src/zig/bench/rope-markers_bench.zig +0 -713
  490. package/src/zig/bench/rope_bench.zig +0 -514
  491. package/src/zig/bench/styled-text_bench.zig +0 -470
  492. package/src/zig/bench/text-buffer-coords_bench.zig +0 -362
  493. package/src/zig/bench/text-buffer-view_bench.zig +0 -459
  494. package/src/zig/bench/text-chunk-graphemes_bench.zig +0 -273
  495. package/src/zig/bench/utf8_bench.zig +0 -799
  496. package/src/zig/bench-utils.zig +0 -431
  497. package/src/zig/bench.zig +0 -217
  498. package/src/zig/buffer.zig +0 -2223
  499. package/src/zig/build.zig +0 -289
  500. package/src/zig/build.zig.zon +0 -16
  501. package/src/zig/edit-buffer.zig +0 -825
  502. package/src/zig/editor-view.zig +0 -802
  503. package/src/zig/event-bus.zig +0 -13
  504. package/src/zig/event-emitter.zig +0 -65
  505. package/src/zig/file-logger.zig +0 -92
  506. package/src/zig/grapheme.zig +0 -599
  507. package/src/zig/lib.zig +0 -1834
  508. package/src/zig/link.zig +0 -333
  509. package/src/zig/logger.zig +0 -43
  510. package/src/zig/mem-registry.zig +0 -125
  511. package/src/zig/native-span-feed-bench-lib.zig +0 -7
  512. package/src/zig/native-span-feed.zig +0 -708
  513. package/src/zig/renderer.zig +0 -1386
  514. package/src/zig/rope.zig +0 -1220
  515. package/src/zig/syntax-style.zig +0 -161
  516. package/src/zig/terminal.zig +0 -975
  517. package/src/zig/test.zig +0 -70
  518. package/src/zig/tests/README.md +0 -18
  519. package/src/zig/tests/buffer_test.zig +0 -2526
  520. package/src/zig/tests/edit-buffer-history_test.zig +0 -271
  521. package/src/zig/tests/edit-buffer_test.zig +0 -1689
  522. package/src/zig/tests/editor-view_test.zig +0 -3299
  523. package/src/zig/tests/event-emitter_test.zig +0 -249
  524. package/src/zig/tests/grapheme_test.zig +0 -1304
  525. package/src/zig/tests/link_test.zig +0 -190
  526. package/src/zig/tests/mem-registry_test.zig +0 -473
  527. package/src/zig/tests/memory_leak_regression_test.zig +0 -159
  528. package/src/zig/tests/native-span-feed_test.zig +0 -1264
  529. package/src/zig/tests/renderer_test.zig +0 -1010
  530. package/src/zig/tests/rope-nested_test.zig +0 -712
  531. package/src/zig/tests/rope_fuzz_test.zig +0 -238
  532. package/src/zig/tests/rope_test.zig +0 -2362
  533. package/src/zig/tests/segment-merge.test.zig +0 -148
  534. package/src/zig/tests/syntax-style_test.zig +0 -557
  535. package/src/zig/tests/terminal_test.zig +0 -719
  536. package/src/zig/tests/text-buffer-drawing_test.zig +0 -3237
  537. package/src/zig/tests/text-buffer-highlights_test.zig +0 -666
  538. package/src/zig/tests/text-buffer-iterators_test.zig +0 -776
  539. package/src/zig/tests/text-buffer-segment_test.zig +0 -320
  540. package/src/zig/tests/text-buffer-selection_test.zig +0 -1035
  541. package/src/zig/tests/text-buffer-selection_viewport_test.zig +0 -358
  542. package/src/zig/tests/text-buffer-view_test.zig +0 -3649
  543. package/src/zig/tests/text-buffer_test.zig +0 -2191
  544. package/src/zig/tests/unicode-width-map.zon +0 -3909
  545. package/src/zig/tests/utf8_no_zwj_test.zig +0 -260
  546. package/src/zig/tests/utf8_test.zig +0 -4057
  547. package/src/zig/tests/utf8_wcwidth_cursor_test.zig +0 -267
  548. package/src/zig/tests/utf8_wcwidth_test.zig +0 -357
  549. package/src/zig/tests/word-wrap-editing_test.zig +0 -498
  550. package/src/zig/tests/wrap-cache-perf_test.zig +0 -113
  551. package/src/zig/text-buffer-iterators.zig +0 -499
  552. package/src/zig/text-buffer-segment.zig +0 -404
  553. package/src/zig/text-buffer-view.zig +0 -1371
  554. package/src/zig/text-buffer.zig +0 -1180
  555. package/src/zig/utf8.zig +0 -1948
  556. package/src/zig/utils.zig +0 -9
  557. package/src/zig-structs.ts +0 -261
  558. package/src/zig.ts +0 -3843
  559. package/tsconfig.build.json +0 -22
  560. package/tsconfig.json +0 -28
  561. /package/{src/lib/tree-sitter/assets → assets}/javascript/highlights.scm +0 -0
  562. /package/{src/lib/tree-sitter/assets → assets}/javascript/tree-sitter-javascript.wasm +0 -0
  563. /package/{src/lib/tree-sitter/assets → assets}/markdown/highlights.scm +0 -0
  564. /package/{src/lib/tree-sitter/assets → assets}/markdown/injections.scm +0 -0
  565. /package/{src/lib/tree-sitter/assets → assets}/markdown/tree-sitter-markdown.wasm +0 -0
  566. /package/{src/lib/tree-sitter/assets → assets}/markdown_inline/highlights.scm +0 -0
  567. /package/{src/lib/tree-sitter/assets → assets}/markdown_inline/tree-sitter-markdown_inline.wasm +0 -0
  568. /package/{src/lib/tree-sitter/assets → assets}/typescript/highlights.scm +0 -0
  569. /package/{src/lib/tree-sitter/assets → assets}/typescript/tree-sitter-typescript.wasm +0 -0
  570. /package/{src/lib/tree-sitter/assets → assets}/zig/highlights.scm +0 -0
  571. /package/{src/lib/tree-sitter/assets → assets}/zig/tree-sitter-zig.wasm +0 -0
@@ -1,975 +0,0 @@
1
- const std = @import("std");
2
- const builtin = @import("builtin");
3
- const atomic = std.atomic;
4
- const assert = std.debug.assert;
5
- const ansi = @import("ansi.zig");
6
- const utf8 = @import("utf8.zig");
7
- const logger = @import("logger.zig");
8
-
9
- const WidthMethod = utf8.WidthMethod;
10
-
11
- /// Terminal capability detection and management
12
- pub const Terminal = @This();
13
-
14
- pub const Capabilities = struct {
15
- kitty_keyboard: bool = false,
16
- kitty_graphics: bool = false,
17
- rgb: bool = false,
18
- unicode: WidthMethod = .unicode,
19
- sgr_pixels: bool = false,
20
- color_scheme_updates: bool = false,
21
- explicit_width: bool = false,
22
- scaled_text: bool = false,
23
- sixel: bool = false,
24
- focus_tracking: bool = false,
25
- sync: bool = false,
26
- bracketed_paste: bool = false,
27
- hyperlinks: bool = false,
28
- osc52: bool = false,
29
- explicit_cursor_positioning: bool = false,
30
- };
31
-
32
- pub const MouseLevel = enum {
33
- none,
34
- basic, // click only
35
- drag, // click + drag
36
- motion, // all motion
37
- pixels, // pixel coordinates
38
- };
39
-
40
- pub const CursorStyle = enum {
41
- block,
42
- line,
43
- underline,
44
- default,
45
- };
46
-
47
- pub const MousePointerStyle = enum(u8) {
48
- default = 0,
49
- pointer = 1,
50
- text = 2,
51
- crosshair = 3,
52
- move = 4,
53
- not_allowed = 5,
54
-
55
- pub fn toName(self: MousePointerStyle) []const u8 {
56
- return if (self == .not_allowed) "not-allowed" else @tagName(self);
57
- }
58
- };
59
-
60
- pub const ClipboardTarget = enum {
61
- clipboard, // "c"
62
- primary, // "p"
63
- secondary, // "s"
64
- query, // "q"
65
-
66
- pub fn toChar(self: ClipboardTarget) u8 {
67
- return switch (self) {
68
- .clipboard => 'c',
69
- .primary => 'p',
70
- .secondary => 's',
71
- .query => 'q',
72
- };
73
- }
74
- };
75
-
76
- pub const Options = struct {
77
- // Kitty keyboard protocol flags (progressive enhancement):
78
- // See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/#progressive-enhancement
79
- // Bit 0 (0b1): Disambiguate escape codes (fixes ESC timing, alt+key ambiguity, ctrl+c as event)
80
- // Bit 1 (0b10): Report event types (press/repeat/release)
81
- // Bit 2 (0b100): Report alternate keys (e.g., numpad vs regular, shifted, base layout)
82
- // Bit 3 (0b1000): Report all keys as escape codes
83
- // Bit 4 (0b10000): Report text associated with key events
84
- // Default 0b00101 (5) = disambiguate + alternate keys
85
- // Use 0b00111 (7) to also enable event types for key release detection
86
- kitty_keyboard_flags: u8 = 0b00101,
87
- remote: bool = false,
88
- // Optional override for environment lookups. Caller owns the map.
89
- env_map: ?*const std.process.EnvMap = null,
90
- };
91
-
92
- pub const TerminalInfo = struct {
93
- name: [64]u8 = [_]u8{0} ** 64,
94
- name_len: usize = 0,
95
- version: [32]u8 = [_]u8{0} ** 32,
96
- version_len: usize = 0,
97
- from_xtversion: bool = false,
98
- };
99
-
100
- caps: Capabilities = .{},
101
- opts: Options = .{},
102
- host_env_map: ?std.process.EnvMap = null,
103
-
104
- in_tmux: bool = false,
105
- skip_graphics_query: bool = false,
106
- skip_explicit_width_query: bool = false,
107
- graphics_query_pending: bool = false,
108
- capability_queries_pending: bool = false,
109
-
110
- state: struct {
111
- alt_screen: bool = false,
112
- kitty_keyboard: bool = false,
113
- kitty_keyboard_flags: u8 = 0,
114
- bracketed_paste: bool = false,
115
- mouse: bool = false,
116
- mouse_movement: bool = true,
117
- pixel_mouse: bool = false,
118
- color_scheme_updates: bool = false,
119
- focus_tracking: bool = false,
120
- modify_other_keys: bool = false,
121
- mouse_pointer: MousePointerStyle = .default,
122
- cursor: struct {
123
- row: u16 = 0,
124
- col: u16 = 0,
125
- x: u32 = 1, // 1-based for rendering
126
- y: u32 = 1, // 1-based for rendering
127
- visible: bool = true,
128
- style: CursorStyle = .default,
129
- blinking: bool = false,
130
- color: [4]f32 = .{ 1.0, 1.0, 1.0, 1.0 }, // RGBA
131
- } = .{},
132
- } = .{},
133
-
134
- term_info: TerminalInfo = .{},
135
-
136
- pub fn init(opts: Options) Terminal {
137
- var term: Terminal = .{
138
- .opts = opts,
139
- };
140
-
141
- term.checkEnvironmentOverrides();
142
- return term;
143
- }
144
-
145
- pub fn deinit(self: *Terminal) void {
146
- if (self.host_env_map) |*env_map| {
147
- env_map.deinit();
148
- self.host_env_map = null;
149
- }
150
- self.opts.env_map = null;
151
- }
152
-
153
- pub fn setHostEnvVar(self: *Terminal, allocator: std.mem.Allocator, key: []const u8, value: []const u8) !void {
154
- if (self.host_env_map == null) {
155
- self.host_env_map = std.process.EnvMap.init(allocator);
156
- }
157
-
158
- const env_map = &self.host_env_map.?;
159
- try env_map.put(key, value);
160
- self.opts.env_map = env_map;
161
- self.checkEnvironmentOverrides();
162
- }
163
-
164
- pub fn resetState(self: *Terminal, tty: anytype) !void {
165
- try tty.writeAll(ansi.ANSI.showCursor);
166
- try tty.writeAll(ansi.ANSI.reset);
167
- try tty.writeAll(ansi.ANSI.resetMousePointer);
168
- self.state.mouse_pointer = .default;
169
-
170
- if (self.state.kitty_keyboard) {
171
- try self.setKittyKeyboard(tty, false, 0);
172
- }
173
-
174
- if (self.state.modify_other_keys) {
175
- try self.setModifyOtherKeys(tty, false);
176
- }
177
-
178
- if (self.state.mouse) {
179
- try self.setMouseMode(tty, false, self.state.mouse_movement);
180
- }
181
-
182
- if (self.state.bracketed_paste) {
183
- try self.setBracketedPaste(tty, false);
184
- }
185
-
186
- if (self.state.focus_tracking) {
187
- try self.setFocusTracking(tty, false);
188
- }
189
-
190
- if (self.state.alt_screen) {
191
- try self.exitAltScreen(tty);
192
- } else {
193
- switch (builtin.os.tag) {
194
- .windows => {
195
- try tty.writeByte('\r');
196
- var i: u16 = 0;
197
- while (i < self.state.cursor.row) : (i += 1) {
198
- try tty.writeAll(ansi.ANSI.reverseIndex);
199
- }
200
- try tty.writeAll(ansi.ANSI.eraseBelowCursor);
201
- },
202
- else => {},
203
- }
204
- }
205
-
206
- if (self.state.color_scheme_updates) {
207
- try self.setColorSchemeUpdates(tty, false);
208
- }
209
-
210
- self.setTerminalTitle(tty, "");
211
- }
212
-
213
- pub fn enterAltScreen(self: *Terminal, tty: anytype) !void {
214
- try tty.writeAll(ansi.ANSI.switchToAlternateScreen);
215
- self.state.alt_screen = true;
216
- }
217
-
218
- pub fn exitAltScreen(self: *Terminal, tty: anytype) !void {
219
- try tty.writeAll(ansi.ANSI.switchToMainScreen);
220
- self.state.alt_screen = false;
221
- }
222
-
223
- pub fn queryTerminalSend(self: *Terminal, tty: anytype) !void {
224
- self.checkEnvironmentOverrides();
225
- self.graphics_query_pending = !self.skip_graphics_query;
226
- self.capability_queries_pending = false;
227
-
228
- // Send xtversion first (doesn't need DCS wrapping - used for tmux detection)
229
- try tty.writeAll(ansi.ANSI.xtversion ++
230
- ansi.ANSI.hideCursor ++
231
- ansi.ANSI.saveCursorState);
232
-
233
- if (self.in_tmux) {
234
- try tty.writeAll(ansi.ANSI.capabilityQueriesTmux);
235
- } else {
236
- try tty.writeAll(ansi.ANSI.capabilityQueries);
237
- self.capability_queries_pending = true;
238
- }
239
-
240
- if (!self.skip_explicit_width_query) {
241
- try tty.writeAll(ansi.ANSI.home ++
242
- ansi.ANSI.explicitWidthQuery ++
243
- ansi.ANSI.cursorPositionRequest ++
244
- ansi.ANSI.home ++
245
- ansi.ANSI.scaledTextQuery ++
246
- ansi.ANSI.cursorPositionRequest);
247
- }
248
-
249
- try tty.writeAll(ansi.ANSI.restoreCursorState);
250
- }
251
-
252
- pub fn sendPendingQueries(self: *Terminal, tty: anytype) !bool {
253
- var sent = false;
254
- const is_tmux = self.in_tmux or self.isXtversionTmux();
255
-
256
- // Re-send capability queries DCS wrapped if tmux detected via xtversion
257
- // Only needed if we got xtversion response indicating tmux
258
- if (self.capability_queries_pending) {
259
- if (self.term_info.from_xtversion and is_tmux) {
260
- try tty.writeAll(ansi.ANSI.capabilityQueriesTmux);
261
- sent = true;
262
- }
263
- // Clear pending flag regardless - non-tmux terminals already received unwrapped queries
264
- self.capability_queries_pending = false;
265
- }
266
-
267
- if (self.graphics_query_pending and !self.skip_graphics_query) {
268
- if (is_tmux) {
269
- try tty.writeAll(ansi.ANSI.kittyGraphicsQueryTmux);
270
- } else {
271
- try tty.writeAll(ansi.ANSI.kittyGraphicsQuery);
272
- }
273
- self.graphics_query_pending = false;
274
- sent = true;
275
- }
276
-
277
- return sent;
278
- }
279
-
280
- pub fn enableDetectedFeatures(self: *Terminal, tty: anytype, use_kitty_keyboard: bool) !void {
281
- if (builtin.os.tag == .windows) {
282
- // Windows-specific defaults for ConPTY
283
- self.caps.rgb = true;
284
- self.caps.bracketed_paste = true;
285
- }
286
-
287
- self.checkEnvironmentOverrides();
288
-
289
- if (!self.state.modify_other_keys and !self.state.kitty_keyboard) {
290
- try self.setModifyOtherKeys(tty, true);
291
- }
292
-
293
- if (self.caps.kitty_keyboard and use_kitty_keyboard) {
294
- if (self.state.modify_other_keys) {
295
- try self.setModifyOtherKeys(tty, false);
296
- }
297
- try self.setKittyKeyboard(tty, true, self.opts.kitty_keyboard_flags);
298
- }
299
-
300
- if (self.caps.unicode == .unicode and !self.caps.explicit_width) {
301
- try tty.writeAll(ansi.ANSI.unicodeSet);
302
- }
303
-
304
- if (self.caps.bracketed_paste) {
305
- try self.setBracketedPaste(tty, true);
306
- }
307
-
308
- if (self.caps.focus_tracking) {
309
- try self.setFocusTracking(tty, true);
310
- }
311
-
312
- if (!self.state.color_scheme_updates) {
313
- try self.setColorSchemeUpdates(tty, true);
314
- try tty.writeAll(ansi.ANSI.colorSchemeRequest);
315
- }
316
- }
317
-
318
- fn checkEnvironmentOverrides(self: *Terminal) void {
319
- self.in_tmux = false;
320
- self.skip_graphics_query = false;
321
- self.skip_explicit_width_query = false;
322
-
323
- // Always just try to enable bracketed paste, even if it was reported as not supported
324
- self.caps.bracketed_paste = true;
325
-
326
- if (self.caps.rgb) {
327
- self.caps.hyperlinks = true;
328
- }
329
-
330
- if (self.opts.remote) {
331
- return;
332
- }
333
-
334
- var env_map_storage: ?std.process.EnvMap = null;
335
- const env_map: *const std.process.EnvMap = self.opts.env_map orelse blk: {
336
- env_map_storage = std.process.getEnvMap(std.heap.page_allocator) catch |err| {
337
- logger.err("Failed to get environment map: {}", .{err});
338
- return;
339
- };
340
- break :blk &env_map_storage.?;
341
- };
342
- defer if (env_map_storage) |*map| map.deinit();
343
-
344
- if (!self.term_info.from_xtversion) {
345
- if (env_map.get("TMUX")) |_| {
346
- self.in_tmux = true;
347
- self.caps.unicode = .wcwidth;
348
- self.caps.explicit_cursor_positioning = true;
349
- } else if (env_map.get("TERM")) |term| {
350
- if (std.mem.startsWith(u8, term, "tmux")) {
351
- self.in_tmux = true;
352
- self.caps.unicode = .wcwidth;
353
- self.caps.explicit_cursor_positioning = true;
354
- } else if (std.mem.startsWith(u8, term, "screen")) {
355
- self.skip_graphics_query = true;
356
- self.caps.unicode = .wcwidth;
357
- self.caps.explicit_cursor_positioning = true;
358
- }
359
- if (std.mem.indexOf(u8, term, "alacritty") != null) {
360
- self.caps.explicit_cursor_positioning = true;
361
- }
362
- }
363
- }
364
-
365
- if (env_map.get("OPENTUI_GRAPHICS")) |val| {
366
- if (std.mem.eql(u8, val, "false") or std.mem.eql(u8, val, "0")) {
367
- self.skip_graphics_query = true;
368
- } else if (std.mem.eql(u8, val, "true") or std.mem.eql(u8, val, "1")) {
369
- self.skip_graphics_query = false;
370
- }
371
- }
372
-
373
- if (!self.term_info.from_xtversion) {
374
- if (env_map.get("TERM_PROGRAM")) |prog| {
375
- const copy_len = @min(prog.len, self.term_info.name.len);
376
- @memcpy(self.term_info.name[0..copy_len], prog[0..copy_len]);
377
- self.term_info.name_len = copy_len;
378
-
379
- if (env_map.get("TERM_PROGRAM_VERSION")) |ver| {
380
- const ver_len = @min(ver.len, self.term_info.version.len);
381
- @memcpy(self.term_info.version[0..ver_len], ver[0..ver_len]);
382
- self.term_info.version_len = ver_len;
383
- }
384
- }
385
-
386
- if (env_map.get("TERM_PROGRAM")) |prog| {
387
- if (std.mem.eql(u8, prog, "vscode")) {
388
- self.caps.kitty_keyboard = false;
389
- self.caps.kitty_graphics = false;
390
- self.caps.unicode = .unicode;
391
- } else if (std.mem.eql(u8, prog, "Apple_Terminal")) {
392
- self.caps.unicode = .wcwidth;
393
- } else if (std.mem.eql(u8, prog, "Alacritty")) {
394
- self.caps.explicit_cursor_positioning = true;
395
- }
396
- }
397
-
398
- if (env_map.get("ALACRITTY_SOCKET") != null or env_map.get("ALACRITTY_LOG") != null) {
399
- self.caps.explicit_cursor_positioning = true;
400
- if (self.term_info.name_len == 0) {
401
- const name = "Alacritty";
402
- @memcpy(self.term_info.name[0..name.len], name);
403
- self.term_info.name_len = name.len;
404
- }
405
- }
406
- }
407
-
408
- if (env_map.get("COLORTERM")) |colorterm| {
409
- if (std.mem.eql(u8, colorterm, "truecolor") or
410
- std.mem.eql(u8, colorterm, "24bit"))
411
- {
412
- self.caps.rgb = true;
413
- }
414
- }
415
-
416
- if (!self.term_info.from_xtversion) {
417
- if (env_map.get("TERMUX_VERSION")) |_| {
418
- self.caps.unicode = .wcwidth;
419
- }
420
-
421
- if (env_map.get("VHS_RECORD")) |_| {
422
- self.caps.unicode = .wcwidth;
423
- self.caps.kitty_keyboard = false;
424
- self.caps.kitty_graphics = false;
425
- }
426
- }
427
-
428
- if (env_map.get("OPENTUI_FORCE_WCWIDTH")) |_| {
429
- self.caps.unicode = .wcwidth;
430
- }
431
- if (env_map.get("OPENTUI_FORCE_UNICODE")) |_| {
432
- self.caps.unicode = .unicode;
433
- }
434
- if (env_map.get("OPENTUI_FORCE_NOZWJ")) |_| {
435
- self.caps.unicode = .no_zwj;
436
- }
437
-
438
- if (env_map.get("OPENTUI_FORCE_EXPLICIT_WIDTH")) |val| {
439
- if (std.mem.eql(u8, val, "true") or std.mem.eql(u8, val, "1")) {
440
- self.caps.explicit_width = true;
441
- } else if (std.mem.eql(u8, val, "false") or std.mem.eql(u8, val, "0")) {
442
- self.caps.explicit_width = false;
443
- self.skip_explicit_width_query = true;
444
- }
445
- }
446
-
447
- if (!self.caps.hyperlinks and self.term_info.from_xtversion) {
448
- if (isHyperlinkTerm(self.getTerminalName())) {
449
- self.caps.hyperlinks = true;
450
- }
451
- }
452
-
453
- if (!self.caps.hyperlinks and !self.term_info.from_xtversion) {
454
- if (env_map.get("TERM")) |term| {
455
- if (isHyperlinkTerm(term)) {
456
- self.caps.hyperlinks = true;
457
- }
458
- }
459
- }
460
-
461
- if (!self.caps.osc52 and !self.term_info.from_xtversion) {
462
- if (env_map.get("WT_SESSION") != null) {
463
- self.caps.osc52 = true;
464
- }
465
-
466
- if (!self.caps.osc52 and (self.in_tmux or env_map.get("STY") != null)) {
467
- self.caps.osc52 = true;
468
- }
469
-
470
- if (!self.caps.osc52) {
471
- if (env_map.get("TERM_PROGRAM")) |prog| {
472
- if (isOsc52Term(prog)) {
473
- self.caps.osc52 = true;
474
- }
475
- }
476
- }
477
-
478
- if (!self.caps.osc52) {
479
- if (env_map.get("TERM")) |term| {
480
- if (isOsc52Term(term) or std.mem.indexOf(u8, term, "256color") != null or std.mem.indexOf(u8, term, "xterm") != null) {
481
- self.caps.osc52 = true;
482
- }
483
- }
484
- }
485
- }
486
- }
487
-
488
- // TODO: Allow pixel mouse mode to be enabled,
489
- // currently does not make sense and is not supported by higher levels
490
- pub fn setMouseMode(self: *Terminal, tty: anytype, enable: bool, enable_movement: bool) !void {
491
- if (enable) {
492
- if (self.state.mouse and self.state.mouse_movement == enable_movement) return;
493
- } else if (!self.state.mouse) {
494
- return;
495
- }
496
-
497
- if (enable) {
498
- self.state.mouse = true;
499
- self.state.mouse_movement = enable_movement;
500
- if (!enable_movement) {
501
- // Some terminals treat ?1000/?1002/?1003 as one family and let the
502
- // last sequence win. Reset any-event tracking first, then enable
503
- // click/drag modes so they remain active.
504
- try tty.writeAll(ansi.ANSI.disableAnyEventTracking);
505
- }
506
- try tty.writeAll(ansi.ANSI.enableMouseTracking);
507
- try tty.writeAll(ansi.ANSI.enableButtonEventTracking);
508
- if (enable_movement) {
509
- try tty.writeAll(ansi.ANSI.enableAnyEventTracking);
510
- }
511
- try tty.writeAll(ansi.ANSI.enableSGRMouseMode);
512
- } else {
513
- self.state.mouse = false;
514
- self.state.pixel_mouse = false;
515
- try tty.writeAll(ansi.ANSI.disableAnyEventTracking);
516
- try tty.writeAll(ansi.ANSI.disableButtonEventTracking);
517
- try tty.writeAll(ansi.ANSI.disableMouseTracking);
518
- try tty.writeAll(ansi.ANSI.disableSGRMouseMode);
519
- }
520
- }
521
-
522
- pub fn setBracketedPaste(self: *Terminal, tty: anytype, enable: bool) !void {
523
- const seq = if (enable) ansi.ANSI.bracketedPasteSet else ansi.ANSI.bracketedPasteReset;
524
- try tty.writeAll(seq);
525
- self.state.bracketed_paste = enable;
526
- }
527
-
528
- pub fn setFocusTracking(self: *Terminal, tty: anytype, enable: bool) !void {
529
- const seq = if (enable) ansi.ANSI.focusSet else ansi.ANSI.focusReset;
530
- try tty.writeAll(seq);
531
- self.state.focus_tracking = enable;
532
- }
533
-
534
- pub fn setKittyKeyboard(self: *Terminal, tty: anytype, enable: bool, flags: u8) !void {
535
- if (enable) {
536
- if (!self.state.kitty_keyboard) {
537
- try tty.print(ansi.ANSI.csiUPush, .{flags});
538
- self.state.kitty_keyboard = true;
539
- self.state.kitty_keyboard_flags = flags;
540
- }
541
- } else {
542
- if (self.state.kitty_keyboard) {
543
- try tty.writeAll(ansi.ANSI.csiUPop);
544
- self.state.kitty_keyboard = false;
545
- self.state.kitty_keyboard_flags = 0;
546
- }
547
- }
548
- }
549
-
550
- pub fn setModifyOtherKeys(self: *Terminal, tty: anytype, enable: bool) !void {
551
- const seq = if (enable) ansi.ANSI.modifyOtherKeysSet else ansi.ANSI.modifyOtherKeysReset;
552
- try tty.writeAll(seq);
553
- self.state.modify_other_keys = enable;
554
- }
555
-
556
- pub fn setColorSchemeUpdates(self: *Terminal, tty: anytype, enable: bool) !void {
557
- const seq = if (enable) ansi.ANSI.colorSchemeSet else ansi.ANSI.colorSchemeReset;
558
- try tty.writeAll(seq);
559
- self.state.color_scheme_updates = enable;
560
- }
561
-
562
- /// Re-send all currently-active terminal mode escape sequences unconditionally.
563
- ///
564
- /// When the terminal loses and regains focus (e.g. alt-tab, tab switch, minimize),
565
- /// some terminal emulators (notably Windows Terminal / ConPTY) strip or reset
566
- /// DEC private modes like mouse tracking (?1000/?1002/?1003/?1006), focus
567
- /// tracking (?1004), and bracketed paste (?2004). This function re-emits the
568
- /// enable sequences for every mode that our state tracking says is currently on,
569
- /// without checking whether the mode "should" already be enabled — because the
570
- /// terminal may have silently disabled it.
571
- ///
572
- /// This should be called in response to the focus-in event (\x1b[I).
573
- ///
574
- /// Per the xterm ctlseqs spec (Patch #401, 2025/06/22) and the Microsoft
575
- /// Console Virtual Terminal Sequences documentation, the relevant DECSET
576
- /// private modes are:
577
- /// ?1000h - Normal mouse tracking (sends button press/release)
578
- /// ?1002h - Button-event tracking (adds drag reporting)
579
- /// ?1003h - Any-event tracking (adds all motion reporting)
580
- /// ?1006h - SGR extended mouse mode (extended coordinate encoding)
581
- /// ?1004h - Focus event tracking (sends \x1b[I / \x1b[O)
582
- /// ?2004h - Bracketed paste mode (wraps pasted text in markers)
583
- /// Kitty keyboard protocol (CSI > flags u) - progressive enhancement
584
- /// modifyOtherKeys (CSI > 4 ; 1 m) - xterm key modification
585
- pub fn restoreTerminalModes(self: *Terminal, tty: anytype) !void {
586
- // Re-enable mouse tracking modes if active
587
- if (self.state.mouse) {
588
- if (!self.state.mouse_movement) {
589
- try tty.writeAll(ansi.ANSI.disableAnyEventTracking);
590
- }
591
- try tty.writeAll(ansi.ANSI.enableMouseTracking);
592
- try tty.writeAll(ansi.ANSI.enableButtonEventTracking);
593
- if (self.state.mouse_movement) {
594
- try tty.writeAll(ansi.ANSI.enableAnyEventTracking);
595
- }
596
- try tty.writeAll(ansi.ANSI.enableSGRMouseMode);
597
- }
598
-
599
- // Re-enable focus tracking if active
600
- if (self.state.focus_tracking) {
601
- try tty.writeAll(ansi.ANSI.focusSet);
602
- }
603
-
604
- // Re-enable bracketed paste if active
605
- if (self.state.bracketed_paste) {
606
- try tty.writeAll(ansi.ANSI.bracketedPasteSet);
607
- }
608
-
609
- // Pop stale entry then re-push kitty keyboard protocol to avoid stack growth.
610
- // Both sequences are in the same write buffer so the terminal processes them atomically.
611
- if (self.state.kitty_keyboard) {
612
- try tty.writeAll(ansi.ANSI.csiUPop);
613
- try tty.print(ansi.ANSI.csiUPush, .{self.state.kitty_keyboard_flags});
614
- }
615
-
616
- // Re-enable modifyOtherKeys if active
617
- if (self.state.modify_other_keys) {
618
- try tty.writeAll(ansi.ANSI.modifyOtherKeysSet);
619
- }
620
- }
621
-
622
- /// The responses look like these:
623
- /// kitty - '\x1B[?1016;2$y\x1B[?2027;0$y\x1B[?2031;2$y\x1B[?1004;1$y\x1B[?2026;2$y\x1B[1;2R\x1B[1;3R\x1BP>|kitty(0.40.1)\x1B\\\x1B[?0u\x1B_Gi=1;EINVAL:Zero width/height not allowed\x1B\\\x1B[?62;c'
624
- /// ghostty - '\x1B[?1016;1$y\x1B[?2027;1$y\x1B[?2031;2$y\x1B[?1004;1$y\x1B[?2004;2$y\x1B[?2026;2$y\x1B[1;1R\x1B[1;1R\x1BP>|ghostty 1.1.3\x1B\\\x1B[?0u\x1B_Gi=1;OK\x1B\\\x1B[?62;22c'
625
- /// tmux - '\x1B[1;1R\x1B[1;1R\x1BP>|tmux 3.5a\x1B\\\x1B[?1;2;4c\x1B[?2;3;0S'
626
- /// vscode - '\x1B[?1016;2$y'
627
- /// alacritty - '\x1B[?1016;0$y\x1B[?2027;0$y\x1B[?2031;0$y\x1B[?1004;2$y\x1B[?2004;2$y\x1B[?2026;2$y\x1B[1;1R\x1B[1;1R\x1B[?0u\x1B[?6c'
628
- ///
629
- /// Parsing these is not complete yet
630
- pub fn processCapabilityResponse(self: *Terminal, response: []const u8) void {
631
- // DECRPM responses
632
- if (std.mem.indexOf(u8, response, "1016;2$y")) |_| {
633
- self.caps.sgr_pixels = true;
634
- }
635
- if (std.mem.indexOf(u8, response, "2027;2$y")) |_| {
636
- self.caps.unicode = .unicode;
637
- }
638
- if (std.mem.indexOf(u8, response, "2031;1$y") != null or std.mem.indexOf(u8, response, "2031;2$y") != null) {
639
- self.caps.color_scheme_updates = true;
640
- }
641
- if (std.mem.indexOf(u8, response, "1004;1$y") != null or std.mem.indexOf(u8, response, "1004;2$y") != null) {
642
- self.caps.focus_tracking = true;
643
- }
644
- if (std.mem.indexOf(u8, response, "2026;1$y") != null or std.mem.indexOf(u8, response, "2026;2$y") != null) {
645
- self.caps.sync = true;
646
- }
647
- if (std.mem.indexOf(u8, response, "2004;1$y") != null or std.mem.indexOf(u8, response, "2004;2$y") != null) {
648
- self.caps.bracketed_paste = true;
649
- }
650
-
651
- // Explicit width detection - cursor position report [1;NR where N >= 2 means explicit width supported
652
- // We look for ESC[1; followed by a digit >= 2
653
- // This handles cases where the cursor isn't at exact home position when queries are sent
654
- if (std.mem.indexOf(u8, response, "\x1b[1;")) |pos| {
655
- const after = response[pos + 4 ..];
656
- if (after.len > 0) {
657
- var end: usize = 0;
658
- while (end < after.len and after[end] >= '0' and after[end] <= '9') : (end += 1) {}
659
- if (end > 0 and end < after.len and after[end] == 'R') {
660
- const col = std.fmt.parseInt(u16, after[0..end], 10) catch 0;
661
- if (col >= 2) {
662
- self.caps.explicit_width = true;
663
- }
664
- if (col >= 3) {
665
- self.caps.scaled_text = true;
666
- }
667
- }
668
- }
669
- }
670
-
671
- // Parse xtversion response: ESC P > | name version ESC \
672
- // Examples: "\x1BP>|kitty(0.40.1)\x1B\\" or "\x1BP>|ghostty 1.1.3\x1B\\" or "\x1BP>|tmux 3.5a\x1B\\"
673
- if (std.mem.indexOf(u8, response, "\x1bP>|")) |pos| {
674
- const start = pos + 4; // Skip past "\x1BP>|"
675
- if (std.mem.indexOf(u8, response[start..], "\x1b\\")) |end_offset| {
676
- const term_str = response[start .. start + end_offset];
677
- self.parseXtversion(term_str);
678
- }
679
- }
680
-
681
- // Kitty detection
682
- if (std.mem.indexOf(u8, response, "kitty")) |_| {
683
- self.caps.kitty_keyboard = true;
684
- self.caps.kitty_graphics = true;
685
- self.caps.unicode = .unicode;
686
- self.caps.rgb = true;
687
- self.caps.sixel = true;
688
- self.caps.bracketed_paste = true;
689
- self.caps.hyperlinks = true;
690
- }
691
-
692
- // Kitty keyboard protocol detection via CSI ? u response
693
- // Terminals supporting the protocol respond to CSI ? u with CSI ? <flags> u
694
- // Examples: \x1b[?0u (ghostty, alacritty), \x1b[?1u, etc.
695
- if (std.mem.indexOf(u8, response, "\x1b[?") != null and std.mem.indexOf(u8, response, "u") != null) {
696
- // Look for pattern \x1b[?Nu where N is 0-31
697
- var i: usize = 0;
698
- while (i + 4 < response.len) : (i += 1) {
699
- if (response[i] == '\x1b' and i + 1 < response.len and response[i + 1] == '[' and i + 2 < response.len and response[i + 2] == '?') {
700
- var num_end = i + 3;
701
- while (num_end < response.len and response[num_end] >= '0' and response[num_end] <= '9') : (num_end += 1) {}
702
- if (num_end > i + 3 and num_end < response.len and response[num_end] == 'u') {
703
- self.caps.kitty_keyboard = true;
704
- break;
705
- }
706
- }
707
- }
708
- }
709
-
710
- if (std.mem.indexOf(u8, response, "tmux")) |_| {
711
- self.caps.unicode = .wcwidth;
712
- self.caps.explicit_cursor_positioning = true;
713
- }
714
-
715
- if (std.mem.indexOf(u8, response, "alacritty")) |_| {
716
- self.caps.explicit_cursor_positioning = true;
717
- }
718
-
719
- // Sixel detection via device attributes (capability 4 in DA1 response ending with 'c')
720
- if (std.mem.indexOf(u8, response, ";c")) |pos| {
721
- var start: usize = 0;
722
- if (pos >= 4) {
723
- start = pos;
724
- while (start > 0 and response[start] != '\x1b') {
725
- start -= 1;
726
- }
727
-
728
- const da_response = response[start .. pos + 2];
729
-
730
- if (std.mem.indexOf(u8, da_response, "\x1b[?") == 0) {
731
- if (std.mem.indexOf(u8, da_response, "4;") != null or std.mem.indexOf(u8, da_response, ";4;") != null or std.mem.indexOf(u8, da_response, ";4c") != null) {
732
- self.caps.sixel = true;
733
- }
734
- }
735
- }
736
- }
737
-
738
- // Kitty graphics response: ESC_Gi=31337;OK ESC\ or ESC_Gi=31337;EERROR... ESC\
739
- // We look for our specific query ID (31337) to avoid false positives
740
- if (std.mem.indexOf(u8, response, "\x1b_G")) |_| {
741
- if (std.mem.indexOf(u8, response, "i=31337")) |_| {
742
- // Got a response to our graphics query with our ID
743
- // If it contains "OK" or even an error, the protocol is supported
744
- // (errors mean the query was understood, just parameters were wrong)
745
- self.caps.kitty_graphics = true;
746
- }
747
- }
748
-
749
- if (!self.caps.osc52 and isOsc52Term(response)) {
750
- self.caps.osc52 = true;
751
- }
752
-
753
- if (!self.caps.hyperlinks and isHyperlinkTerm(response)) {
754
- self.caps.hyperlinks = true;
755
- }
756
- }
757
-
758
- fn isOsc52Term(value: []const u8) bool {
759
- return std.ascii.indexOfIgnoreCase(value, "iterm") != null or
760
- std.ascii.indexOfIgnoreCase(value, "kitty") != null or
761
- std.ascii.indexOfIgnoreCase(value, "alacritty") != null or
762
- std.ascii.indexOfIgnoreCase(value, "wezterm") != null or
763
- std.ascii.indexOfIgnoreCase(value, "contour") != null or
764
- std.ascii.indexOfIgnoreCase(value, "foot") != null or
765
- std.ascii.indexOfIgnoreCase(value, "rio") != null or
766
- std.ascii.indexOfIgnoreCase(value, "ghostty") != null or
767
- std.ascii.indexOfIgnoreCase(value, "tmux") != null or
768
- std.ascii.indexOfIgnoreCase(value, "screen") != null;
769
- }
770
-
771
- fn isHyperlinkTerm(value: []const u8) bool {
772
- return std.ascii.indexOfIgnoreCase(value, "ghostty") != null or
773
- std.ascii.indexOfIgnoreCase(value, "kitty") != null or
774
- std.ascii.indexOfIgnoreCase(value, "wezterm") != null or
775
- std.ascii.indexOfIgnoreCase(value, "alacritty") != null or
776
- std.ascii.indexOfIgnoreCase(value, "iterm") != null;
777
- }
778
-
779
- pub fn getCapabilities(self: *Terminal) Capabilities {
780
- return self.caps;
781
- }
782
-
783
- pub fn setMousePointerStyle(self: *Terminal, style: MousePointerStyle) void {
784
- self.state.mouse_pointer = style;
785
- }
786
-
787
- pub fn getMousePointer(self: *Terminal) MousePointerStyle {
788
- return self.state.mouse_pointer;
789
- }
790
-
791
- pub fn setCursorPosition(self: *Terminal, x: u32, y: u32, visible: bool) void {
792
- self.state.cursor.x = @max(1, x);
793
- self.state.cursor.y = @max(1, y);
794
- self.state.cursor.visible = visible;
795
-
796
- // Update 0-based coordinates for terminal operations
797
- self.state.cursor.col = @intCast(@max(0, x - 1));
798
- self.state.cursor.row = @intCast(@max(0, y - 1));
799
- }
800
-
801
- pub fn setCursorStyle(self: *Terminal, style: CursorStyle, blinking: bool) void {
802
- self.state.cursor.style = style;
803
- self.state.cursor.blinking = blinking;
804
- }
805
-
806
- pub fn setCursorColor(self: *Terminal, color: [4]f32) void {
807
- self.state.cursor.color = color;
808
- }
809
-
810
- pub fn getCursorPosition(self: *Terminal) struct { x: u32, y: u32, visible: bool } {
811
- return .{
812
- .x = self.state.cursor.x,
813
- .y = self.state.cursor.y,
814
- .visible = self.state.cursor.visible,
815
- };
816
- }
817
-
818
- pub fn getCursorStyle(self: *Terminal) struct { style: CursorStyle, blinking: bool } {
819
- return .{
820
- .style = self.state.cursor.style,
821
- .blinking = self.state.cursor.blinking,
822
- };
823
- }
824
-
825
- pub fn getCursorColor(self: *Terminal) [4]f32 {
826
- return self.state.cursor.color;
827
- }
828
-
829
- pub fn setKittyKeyboardFlags(self: *Terminal, flags: u8) void {
830
- self.opts.kitty_keyboard_flags = flags;
831
- }
832
-
833
- pub fn setTerminalTitle(_: *Terminal, tty: anytype, title: []const u8) void {
834
- // For Windows, we might need to use different approach, but ANSI sequences work in Windows Terminal, ConPTY, etc.
835
- // For other platforms, ANSI OSC sequences work reliably
836
- ansi.ANSI.setTerminalTitleOutput(tty, title) catch {};
837
- }
838
-
839
- /// Write OSC 52 clipboard sequence to the terminal
840
- /// Supports tmux/screen passthrough, including nested tmux sessions
841
- pub fn writeClipboard(self: *Terminal, tty: anytype, target: ClipboardTarget, payload: []const u8) !void {
842
- if (!self.canWriteClipboard()) {
843
- return error.NotSupported;
844
- }
845
-
846
- var buf: [1024]u8 = undefined;
847
- var stream = std.io.fixedBufferStream(&buf);
848
- const writer = stream.writer();
849
-
850
- // Build OSC 52 sequence: ESC]52;<target>;<payload>ESC\
851
- try writer.writeAll("\x1b]52;");
852
- try writer.writeByte(target.toChar());
853
- try writer.writeByte(';');
854
- try writer.writeAll(payload);
855
- try writer.writeAll("\x1b\\");
856
-
857
- const osc52 = stream.getWritten();
858
-
859
- // Use self.in_tmux which is set by checkEnvironmentOverrides() considering
860
- // env vars, xtversion response, and remote option
861
- const is_tmux = self.in_tmux or self.isXtversionTmux();
862
-
863
- if (is_tmux) {
864
- // For nested tmux, we use a fixed level of 1 as we don't have access
865
- // to env vars here (by design - detection already happened in checkEnvironmentOverrides)
866
- // In practice, single-level wrapping works for most cases
867
- var wrapped_buf: [4096]u8 = undefined;
868
- var wrapped_stream = std.io.fixedBufferStream(&wrapped_buf);
869
- const wrap_writer = wrapped_stream.writer();
870
- for (osc52) |c| {
871
- if (c == '\x1b') {
872
- try wrap_writer.writeByte('\x1b');
873
- }
874
- try wrap_writer.writeByte(c);
875
- }
876
- const doubled = wrapped_stream.getWritten();
877
-
878
- try tty.writeAll(ansi.ANSI.tmuxDcsStart);
879
- try tty.writeAll(doubled);
880
- try tty.writeAll(ansi.ANSI.tmuxDcsEnd);
881
- } else if (self.opts.remote) {
882
- try tty.writeAll(osc52);
883
- } else {
884
- var env_map_storage: ?std.process.EnvMap = null;
885
- const env_map: *const std.process.EnvMap = self.opts.env_map orelse blk: {
886
- env_map_storage = std.process.getEnvMap(std.heap.page_allocator) catch |err| {
887
- logger.err("Failed to get environment map: {}", .{err});
888
- return;
889
- };
890
- break :blk &env_map_storage.?;
891
- };
892
- defer if (env_map_storage) |*map| map.deinit();
893
-
894
- if (env_map.get("STY")) |_| {
895
- var wrapped_buf: [2048]u8 = undefined;
896
- var wrapped_stream = std.io.fixedBufferStream(&wrapped_buf);
897
- const wrapped_writer = wrapped_stream.writer();
898
-
899
- for (osc52) |c| {
900
- if (c == '\x1b') {
901
- try wrapped_writer.writeByte('\x1b');
902
- }
903
- try wrapped_writer.writeByte(c);
904
- }
905
- const doubled = wrapped_stream.getWritten();
906
-
907
- try tty.writeAll(ansi.ANSI.screenDcsStart);
908
- try tty.writeAll(doubled);
909
- try tty.writeAll(ansi.ANSI.screenDcsEnd);
910
- } else {
911
- try tty.writeAll(osc52);
912
- }
913
- }
914
- }
915
-
916
- /// Check if we can write to the clipboard (TTY and OSC 52 supported)
917
- fn canWriteClipboard(self: *Terminal) bool {
918
- // In a real TTY environment, we'd check isTTY here
919
- // For now, we just check if OSC 52 is supported
920
- return self.caps.osc52;
921
- }
922
-
923
- /// Parse xtversion response string and extract terminal name and version
924
- /// Examples: "kitty(0.40.1)", "ghostty 1.1.3", "tmux 3.5a"
925
- fn parseXtversion(self: *Terminal, term_str: []const u8) void {
926
- if (term_str.len == 0) return;
927
-
928
- if (std.mem.indexOf(u8, term_str, "(")) |paren_pos| {
929
- const name_len = @min(paren_pos, self.term_info.name.len);
930
- @memcpy(self.term_info.name[0..name_len], term_str[0..name_len]);
931
- self.term_info.name_len = name_len;
932
-
933
- if (std.mem.indexOf(u8, term_str[paren_pos..], ")")) |close_offset| {
934
- const ver_start = paren_pos + 1;
935
- const ver_end = paren_pos + close_offset;
936
- const ver_len = @min(ver_end - ver_start, self.term_info.version.len);
937
- @memcpy(self.term_info.version[0..ver_len], term_str[ver_start .. ver_start + ver_len]);
938
- self.term_info.version_len = ver_len;
939
- }
940
- } else {
941
- if (std.mem.indexOf(u8, term_str, " ")) |space_pos| {
942
- const name_len = @min(space_pos, self.term_info.name.len);
943
- @memcpy(self.term_info.name[0..name_len], term_str[0..name_len]);
944
- self.term_info.name_len = name_len;
945
-
946
- const ver_start = space_pos + 1;
947
- const ver_len = @min(term_str.len - ver_start, self.term_info.version.len);
948
- @memcpy(self.term_info.version[0..ver_len], term_str[ver_start .. ver_start + ver_len]);
949
- self.term_info.version_len = ver_len;
950
- } else {
951
- const name_len = @min(term_str.len, self.term_info.name.len);
952
- @memcpy(self.term_info.name[0..name_len], term_str[0..name_len]);
953
- self.term_info.name_len = name_len;
954
- self.term_info.version_len = 0;
955
- }
956
- }
957
-
958
- self.term_info.from_xtversion = true;
959
- }
960
-
961
- pub fn isXtversionTmux(self: *Terminal) bool {
962
- return self.term_info.from_xtversion and std.mem.eql(u8, self.getTerminalName(), "tmux");
963
- }
964
-
965
- pub fn getTerminalInfo(self: *Terminal) TerminalInfo {
966
- return self.term_info;
967
- }
968
-
969
- pub fn getTerminalName(self: *Terminal) []const u8 {
970
- return self.term_info.name[0..self.term_info.name_len];
971
- }
972
-
973
- pub fn getTerminalVersion(self: *Terminal) []const u8 {
974
- return self.term_info.version[0..self.term_info.version_len];
975
- }