buninu-linux 0.14.57 → 0.16.59

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 (299) hide show
  1. package/LICENSES/linux-firmware/LICENCE.nvidia +131 -0
  2. package/LICENSES/linux-firmware/LICENSE.amdgpu +51 -0
  3. package/LICENSES/linux-firmware/LICENSE.amdisp +31 -0
  4. package/LICENSES/linux-firmware/LICENSE.i915 +39 -0
  5. package/LICENSES/linux-firmware/LICENSE.radeon +51 -0
  6. package/LICENSES/linux-firmware/LICENSE.xe +39 -0
  7. package/LICENSES/linux-firmware/WHENCE +10280 -0
  8. package/NOTICE.md +64 -46
  9. package/README.md +378 -87
  10. package/README.zh.md +2041 -0
  11. package/build-image.sh +10 -1
  12. package/build-uki.sh +3 -1
  13. package/fetch-alpine.sh +14 -0
  14. package/graphics.md +31 -0
  15. package/index.js +28 -11
  16. package/initramfs/bin/buninu-browser +4 -1
  17. package/initramfs/bin/buninu-land +1 -1
  18. package/initramfs/bin/bunterm +3 -3
  19. package/initramfs/bin/chroot +13 -0
  20. package/initramfs/bin/chvt +11 -0
  21. package/initramfs/bin/mount +4 -0
  22. package/initramfs/bin/umount +6 -0
  23. package/initramfs/bin/xdg-open +33 -0
  24. package/initramfs/buninu/CHANGELOG.md +66 -0
  25. package/initramfs/buninu/apps/bunmsh/CHANGELOG.md +4 -0
  26. package/initramfs/buninu/apps/bunmsh/package.json +1 -1
  27. package/initramfs/buninu/apps/bunmsh/src/main.js +1 -1
  28. package/initramfs/buninu/apps/jsgotty/LICENSES/MIT-jsmdcui.txt +22 -0
  29. package/initramfs/buninu/apps/jsgotty/NOTICE +5 -0
  30. package/initramfs/buninu/apps/jsgotty/README.en.md +61 -0
  31. package/initramfs/buninu/apps/jsgotty/README.md +61 -0
  32. package/initramfs/buninu/apps/jsgotty/client-modes.mjs +117 -0
  33. package/initramfs/buninu/apps/jsgotty/client.mjs +100 -10
  34. package/initramfs/buninu/apps/jsgotty/clipboard-powershell.js +18 -0
  35. package/initramfs/buninu/apps/jsgotty/clipboard.js +148 -0
  36. package/initramfs/buninu/apps/jsgotty/gotty.js +13 -0
  37. package/initramfs/buninu/apps/jsgotty/package-lock.json +2 -2
  38. package/initramfs/buninu/apps/jsgotty/package.json +1 -1
  39. package/initramfs/buninu/apps/jsgotty/static/css/index.css +14 -1
  40. package/initramfs/buninu/apps/jsgotty/static/index.html +1 -0
  41. package/initramfs/buninu/apps/jsgotty/static/js/gotty.js +187 -23
  42. package/initramfs/buninu/apps/jsgotty/static/js/kitty-keyboard.js +193 -0
  43. package/initramfs/buninu/apps/jsgotty/static/js/kitty.js +115 -7
  44. package/initramfs/buninu/apps/jsgotty/terminal-modes.js +332 -0
  45. package/initramfs/buninu/apps/jsgotty/tests/android-alt.test.js +115 -0
  46. package/initramfs/buninu/apps/jsgotty/tests/arrow-modifiers.test.js +80 -0
  47. package/initramfs/buninu/apps/jsgotty/tests/client-exit.test.mjs +45 -0
  48. package/initramfs/buninu/apps/jsgotty/tests/client-modes.test.mjs +105 -0
  49. package/initramfs/buninu/apps/jsgotty/tests/clipboard-browser.test.js +81 -0
  50. package/initramfs/buninu/apps/jsgotty/tests/clipboard.test.js +75 -0
  51. package/initramfs/buninu/apps/jsgotty/tests/kitty-keyboard-browser.test.js +53 -0
  52. package/initramfs/buninu/apps/jsgotty/tests/kitty-keyboard.test.js +102 -0
  53. package/initramfs/buninu/apps/jsgotty/tests/manual/README.md +20 -0
  54. package/initramfs/buninu/apps/jsgotty/tests/manual/keyboard-collector.cjs +55 -0
  55. package/initramfs/buninu/apps/jsgotty/tests/manual/keyboard-debug.js +74 -0
  56. package/initramfs/buninu/apps/jsgotty/tests/manual/kitty-keyboard.js +80 -0
  57. package/initramfs/buninu/apps/jsgotty/tests/manual/zoom-collector.cjs +55 -0
  58. package/initramfs/buninu/apps/jsgotty/tests/manual/zoom-debug.js +39 -0
  59. package/initramfs/buninu/apps/jsgotty/tests/manual-touch-diagnostics.js +33 -0
  60. package/initramfs/buninu/apps/jsgotty/tests/manual-touch-diagnostics.mjs +22 -0
  61. package/initramfs/buninu/apps/jsgotty/tests/nested-cli-pty.test.mjs +116 -0
  62. package/initramfs/buninu/apps/jsgotty/tests/reconnect-modes-browser.test.js +144 -0
  63. package/initramfs/buninu/apps/jsgotty/tests/reconnect-modes.md +44 -0
  64. package/initramfs/buninu/apps/jsgotty/tests/reconnect-modes.test.js +166 -0
  65. package/initramfs/buninu/apps/jsgotty/tests/touch-drag-browser.test.js +106 -0
  66. package/initramfs/buninu/apps/jsgotty/tests/wheel-browser.test.js +60 -0
  67. package/initramfs/buninu/apps/jsmdcui/CHANGELOG.md +44 -0
  68. package/initramfs/buninu/apps/jsmdcui/package.json +1 -1
  69. package/initramfs/buninu/apps/jsmdcui/src/highlight/go-regexp.js +83 -0
  70. package/initramfs/buninu/apps/jsmdcui/src/highlight/highlighter.js +49 -62
  71. package/initramfs/buninu/apps/jsmdcui/src/highlight/parser.js +8 -5
  72. package/initramfs/buninu/apps/jsmdcui/tests/go-regexp.test.js +98 -0
  73. package/initramfs/buninu/apps/jsmdcui/tests/heading-ids.test.js +21 -16
  74. package/initramfs/buninu/apps/jsmdcui/tests/highlight-regions.test.js +73 -0
  75. package/initramfs/buninu/apps/jsmdcui/tests/id-collision.test.js +32 -9
  76. package/initramfs/buninu/apps/jsmdcui/tests/markdown-behavior.mjs +9 -0
  77. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/NORMAL-HTML.md +46 -0
  78. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/README.md +85 -0
  79. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/REPORT.md +328 -0
  80. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/compare.mjs +75 -0
  81. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/go.mod +5 -0
  82. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/normal-html-report.json +619 -0
  83. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/normal-html.html +9 -0
  84. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/oracle.go +49 -0
  85. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/report.json +2174 -0
  86. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/PowerShell.txt +39 -0
  87. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/ada.txt +25 -0
  88. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/apacheconf.txt +49 -0
  89. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/arduino.txt +38 -0
  90. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/asciidoc.txt +33 -0
  91. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/asm.txt +77 -0
  92. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/ats.txt +48 -0
  93. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/awk.txt +28 -0
  94. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/b.txt +27 -0
  95. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/bat.txt +39 -0
  96. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/c.txt +34 -0
  97. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/caddyfile.txt +14 -0
  98. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/cake.txt +7 -0
  99. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/clojure.txt +18 -0
  100. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/cmake.txt +20 -0
  101. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/coffeescript.txt +32 -0
  102. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/colortest.txt +19 -0
  103. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/conky.txt +12 -0
  104. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/cpp.txt +46 -0
  105. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/crontab.txt +16 -0
  106. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/crystal.txt +28 -0
  107. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/csharp.txt +28 -0
  108. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/css.txt +19 -0
  109. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/csx.txt +7 -0
  110. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/cuda.txt +37 -0
  111. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/cython.txt +22 -0
  112. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/d.txt +52 -0
  113. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/dart.txt +27 -0
  114. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/default.txt +8 -0
  115. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/dockerfile.txt +10 -0
  116. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/dot.txt +15 -0
  117. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/elixir.txt +23 -0
  118. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/elm.txt +20 -0
  119. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/erb.txt +32 -0
  120. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/erlang.txt +23 -0
  121. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/fish.txt +20 -0
  122. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/forth.txt +17 -0
  123. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/fortran.txt +40 -0
  124. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/freebsd-kernel.txt +10 -0
  125. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/fsharp.txt +27 -0
  126. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/gdscript.txt +26 -0
  127. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/gemini.txt +11 -0
  128. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/gentoo-ebuild.txt +28 -0
  129. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/gentoo-etc-portage.txt +14 -0
  130. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/git-commit.txt +19 -0
  131. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/git-config.txt +11 -0
  132. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/git-rebase-todo.txt +10 -0
  133. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/gleam.txt +44 -0
  134. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/glsl.txt +18 -0
  135. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/gnuplot.txt +11 -0
  136. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/go.txt +33 -0
  137. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/godoc.txt +9 -0
  138. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/golo.txt +50 -0
  139. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/gomod.txt +16 -0
  140. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/graphql.txt +20 -0
  141. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/groff.txt +18 -0
  142. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/groovy.txt +42 -0
  143. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/haml.txt +16 -0
  144. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/hare.txt +31 -0
  145. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/haskell.txt +26 -0
  146. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/hc.txt +28 -0
  147. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/html.txt +26 -0
  148. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/html4.txt +20 -0
  149. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/html5.txt +20 -0
  150. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/ini.txt +16 -0
  151. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/inputrc.txt +14 -0
  152. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/java.txt +18 -0
  153. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/javascript.txt +41 -0
  154. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/jinja2.txt +13 -0
  155. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/json.txt +21 -0
  156. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/jsonnet.txt +28 -0
  157. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/julia.txt +24 -0
  158. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/justfile.txt +26 -0
  159. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/keymap.txt +15 -0
  160. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/kickstart.txt +16 -0
  161. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/kotlin.txt +30 -0
  162. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/kvlang.txt +37 -0
  163. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/ledger.txt +13 -0
  164. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/lfe.txt +17 -0
  165. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/lilypond.txt +15 -0
  166. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/lisp.txt +17 -0
  167. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/log.txt +45 -0
  168. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/lua.txt +48 -0
  169. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/mail.txt +17 -0
  170. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/makefile.txt +25 -0
  171. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/man.txt +12 -0
  172. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/markdown.txt +21 -0
  173. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/mc.txt +11 -0
  174. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/meson.txt +29 -0
  175. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/micro.txt +25 -0
  176. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/mpdconf.txt +13 -0
  177. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/msbuild.txt +7 -0
  178. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/nanorc.txt +16 -0
  179. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/nftables.txt +22 -0
  180. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/nginx.txt +17 -0
  181. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/nim.txt +23 -0
  182. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/nix.txt +15 -0
  183. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/nu.txt +92 -0
  184. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/objc.txt +36 -0
  185. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/ocaml.txt +25 -0
  186. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/octave.txt +35 -0
  187. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/odin.txt +35 -0
  188. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/pascal.txt +22 -0
  189. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/patch.txt +13 -0
  190. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/peg.txt +16 -0
  191. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/perl.txt +27 -0
  192. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/php.txt +44 -0
  193. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/pkg-config.txt +12 -0
  194. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/po.txt +12 -0
  195. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/pony.txt +29 -0
  196. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/pov.txt +17 -0
  197. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/privoxy-action.txt +14 -0
  198. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/privoxy-config.txt +10 -0
  199. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/privoxy-filter.txt +12 -0
  200. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/proto.txt +22 -0
  201. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/prql.txt +42 -0
  202. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/puppet.txt +22 -0
  203. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/python2.txt +24 -0
  204. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/python3.txt +28 -0
  205. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/r.txt +16 -0
  206. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/raku.txt +19 -0
  207. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/reST.txt +18 -0
  208. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/renpy.txt +11 -0
  209. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/rpmspec.txt +31 -0
  210. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/ruby.txt +34 -0
  211. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/rust.txt +27 -0
  212. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/sage.txt +24 -0
  213. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/scad.txt +23 -0
  214. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/scala.txt +16 -0
  215. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/sed.txt +12 -0
  216. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/sh.txt +20 -0
  217. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/sls.txt +15 -0
  218. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/smalltalk.txt +28 -0
  219. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/solidity.txt +26 -0
  220. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/sql.txt +35 -0
  221. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/stata.txt +32 -0
  222. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/svelte.txt +10 -0
  223. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/swift.txt +53 -0
  224. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/systemd.txt +15 -0
  225. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/tcl.txt +17 -0
  226. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/terraform.txt +28 -0
  227. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/tex.txt +15 -0
  228. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/toml.txt +31 -0
  229. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/twig.txt +29 -0
  230. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/typescript.txt +32 -0
  231. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/v.txt +47 -0
  232. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/vala.txt +22 -0
  233. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/verilog.txt +37 -0
  234. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/vhdl.txt +37 -0
  235. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/vi.txt +17 -0
  236. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/vue.txt +29 -0
  237. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/xml.txt +14 -0
  238. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/xresources.txt +14 -0
  239. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/yaml.txt +19 -0
  240. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/yum.txt +12 -0
  241. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/zig.txt +24 -0
  242. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/zscript.txt +31 -0
  243. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/zsh.txt +21 -0
  244. package/initramfs/buninu/package.json +1 -1
  245. package/initramfs/init.js +19 -3
  246. package/initramfs/lib/bunterm/clipboard.js +14 -0
  247. package/initramfs/lib/bunterm/commands.js +37 -0
  248. package/initramfs/lib/bunterm/fps.js +38 -0
  249. package/initramfs/lib/bunterm/images.js +14 -6
  250. package/initramfs/lib/bunterm/input.js +58 -15
  251. package/initramfs/lib/bunterm/keyboard.js +62 -0
  252. package/initramfs/lib/bunterm/keycodes.js +104 -0
  253. package/initramfs/lib/bunterm/kitty-keyboard.cjs +195 -0
  254. package/initramfs/lib/bunterm/raw-protocol.js +111 -0
  255. package/initramfs/lib/bunterm/renderer.js +116 -28
  256. package/initramfs/lib/bunterm/selection.js +60 -0
  257. package/initramfs/lib/bunterm/terminal.js +157 -12
  258. package/initramfs/lib/bunterm/vt-menu.js +181 -0
  259. package/initramfs/lib/bunterm/vt.js +27 -1
  260. package/initramfs/lib/canvas.js +99 -0
  261. package/initramfs/lib/chvt.js +31 -0
  262. package/initramfs/lib/fbdev.js +32 -8
  263. package/initramfs/lib/gpu.js +77 -0
  264. package/initramfs/lib/mapped-frame.js +28 -0
  265. package/initramfs/lib/raw-image.js +71 -0
  266. package/initramfs/lib/xdg-open.js +42 -0
  267. package/initramfs/usr/share/doc/buninu-linux/bunterm.md +85 -11
  268. package/initramfs/usr/share/doc/buninu-linux/chvt.md +34 -0
  269. package/initramfs/usr/share/doc/buninu-linux/xdg-open.md +43 -0
  270. package/package.json +1 -1
  271. package/scripts/arch.js +7 -5
  272. package/scripts/arch.sh +5 -5
  273. package/scripts/build.js +16 -3
  274. package/scripts/fetch-gpu.js +105 -0
  275. package/scripts/fetch.js +11 -1
  276. package/scripts/gpu-firmware.json +22 -0
  277. package/scripts/modules.js +4 -1
  278. package/scripts/npm-packages.md +18 -17
  279. package/test/bunterm-fps.test.js +17 -0
  280. package/test/bunterm-image-bytes.test.js +15 -0
  281. package/test/bunterm-keyboard.test.js +116 -0
  282. package/test/bunterm-mapped-lifetime.test.js +147 -0
  283. package/test/bunterm-next-vt.test.js +9 -0
  284. package/test/bunterm-raw-protocol.test.js +39 -0
  285. package/test/bunterm-renderer.test.js +167 -0
  286. package/test/bunterm-selection.test.js +38 -0
  287. package/test/bunterm-vt-menu.test.js +178 -0
  288. package/test/chroot-bind.test.js +40 -2
  289. package/test/chvt.test.js +46 -0
  290. package/test/fbdev-sync.test.js +42 -0
  291. package/test/fetch-npm.test.js +2 -2
  292. package/test/gpu.test.js +155 -0
  293. package/test/image-size.test.js +17 -0
  294. package/test/manual-bunterm-image-paths.js +31 -0
  295. package/test/mount-libc-lifetime.test.js +50 -0
  296. package/test/no-gpu.test.js +43 -0
  297. package/test/readme-cli.test.js +29 -0
  298. package/test/stage-npm.test.js +11 -4
  299. package/test/xdg-open.test.js +55 -0
@@ -0,0 +1,111 @@
1
+ import fs from "node:fs";
2
+ import {ownMapping, retainMapping} from "../mapped-frame.js";
3
+ // Buninu private extension; not a registered Kitty pixel format.
4
+ export const BGRA_FORMAT = 0x42475241;
5
+ export function preferredPixelFormat(display, littleEndian = new Uint8Array(new Uint32Array([1]).buffer)[0] === 1) {
6
+ if (!littleEndian || display?.bitsPerPixel !== 32) return 'png';
7
+ const f=display.fields;
8
+ const channel=(field,offset)=>field?.offset===offset&&field.length===8&&!field.msbRight;
9
+ const alpha=f?.transp;
10
+ if(alpha?.length && !channel(alpha,24))return 'png';
11
+ if(!channel(f?.green,8))return 'png';
12
+ if(channel(f?.red,16)&&channel(f?.blue,0))return 'bgra';
13
+ if(channel(f?.red,0)&&channel(f?.blue,16))return 'rgba';
14
+ return 'png';
15
+ }
16
+ // Only the native renderer advertises these formats; browser jsgotty is unchanged.
17
+ export function bgraParser(Base,display) {
18
+ return class extends Base {
19
+ constructor(...args) {
20
+ super(...args);
21
+ // The parser cache and renderer have independent lifetimes. Replacing a
22
+ // cache entry must not detach a frame still being drawn or handled.
23
+ this.images = new MappedImages(this.images);
24
+ this.mappingReads = [];
25
+ this.disposed = false;
26
+ }
27
+
28
+ dispose() {
29
+ if (this.disposed) return;
30
+ this.disposed = true;
31
+ this.images.clear();
32
+ this.transfers.clear();
33
+ this.pending = Buffer.alloc(0);
34
+ for (const release of this.mappingReads) release?.();
35
+ this.mappingReads = [];
36
+ }
37
+
38
+ _readImageFile(control,payloadText,deleteAfterRead) {
39
+ // Only complete raw temporary frames are immutable producer handoffs.
40
+ // Ordinary files, compressed/partial transfers keep the copying reader.
41
+ const format=Number(control.f);
42
+ if(!deleteAfterRead || ![32,BGRA_FORMAT].includes(format) || control.O || control.S || control.o || typeof Bun.mmap!=="function")
43
+ return super._readImageFile(control,payloadText,deleteAfterRead);
44
+ const path=fs.realpathSync(Buffer.from(payloadText,"base64").toString("utf8"));
45
+ const stat=fs.statSync(path),w=Number(control.s),h=Number(control.v);
46
+ if(!this._isSafeTempGraphicsPath(path)||!stat.isFile()||!Number.isInteger(w)||!Number.isInteger(h)||w<1||h<1||w*h>16777216||stat.size!==w*h*4)
47
+ return super._readImageFile(control,payloadText,deleteAfterRead);
48
+ let bytes;
49
+ try { bytes=Bun.mmap(path,{shared:false}); }
50
+ catch { return super._readImageFile(control,payloadText,deleteAfterRead); }
51
+ // Keep the mapping through parsing, even for queries/errors that do not
52
+ // enter the image cache. Never truncate/reuse producer files.
53
+ this.mappingReads.push(ownMapping(bytes));
54
+ try { fs.unlinkSync(path); } catch {}
55
+ return Buffer.from(bytes.buffer,bytes.byteOffset,bytes.byteLength);
56
+ }
57
+
58
+ _resolveImageData(control,payload) {
59
+ const bytes=super._resolveImageData(control,payload);
60
+ if(Number(control.f)===BGRA_FORMAT){
61
+ const w=Number(control.s),h=Number(control.v);
62
+ if(!Number.isInteger(w)||!Number.isInteger(h)||w<1||h<1||w*h>16777216||bytes.length!==w*h*4)
63
+ throw Error('Invalid BGRA dimensions or byte count');
64
+ }
65
+ return bytes;
66
+ }
67
+ _parsePacket(packet,cursor) {
68
+ if (this.disposed) return null;
69
+ const previousReads = this.mappingReads;
70
+ this.mappingReads = [];
71
+ try {
72
+ const result=super._parsePacket(packet,cursor);
73
+ const release = retainMapping(result?.image?.data);
74
+ // The consumer uses `using` while awaiting image handling/ACKs. This
75
+ // protects the result even if the parser cache is replaced or closed.
76
+ if (release) result[Symbol.dispose] = release;
77
+ if(result?.kind==='query'&&Number(result.control.f)===BGRA_FORMAT&&result.responseMessage==='OK')
78
+ result.responseMessage='OK Buninu1 '+preferredPixelFormat(display);
79
+ return result;
80
+ } finally {
81
+ for (const release of this.mappingReads) release?.();
82
+ this.mappingReads = previousReads;
83
+ }
84
+ }
85
+ };
86
+ }
87
+
88
+ class MappedImages extends Map {
89
+ constructor(entries) {
90
+ super();
91
+ this.releases = new Map();
92
+ for (const [id, image] of entries) this.set(id, image);
93
+ }
94
+ set(id, image) {
95
+ const release = retainMapping(image?.data);
96
+ this.delete(id);
97
+ super.set(id, image);
98
+ if (release) this.releases.set(id, release);
99
+ return this;
100
+ }
101
+ delete(id) {
102
+ this.releases.get(id)?.();
103
+ this.releases.delete(id);
104
+ return super.delete(id);
105
+ }
106
+ clear() {
107
+ for (const release of this.releases.values()) release();
108
+ this.releases.clear();
109
+ super.clear();
110
+ }
111
+ }
@@ -1,3 +1,4 @@
1
+ import {skiaImage} from '../raw-image.js';
1
2
  // /lib/bunterm/renderer.js — paints an xterm.js headless buffer onto a Skia
2
3
  // canvas as a grid of cells.
3
4
  //
@@ -64,6 +65,7 @@ export class Renderer {
64
65
  this.canvas = screen.canvas;
65
66
  this.fonts = fonts;
66
67
  this.fontSize = fontSize;
68
+ this.lineHeight = lineHeight;
67
69
  this.theme = theme;
68
70
  this.palette = buildPalette(theme);
69
71
  this.foreground = parseColor(theme.foreground);
@@ -127,6 +129,30 @@ export class Renderer {
127
129
  return font;
128
130
  }
129
131
 
132
+ setFontSize(size) {
133
+ if (!Number.isInteger(size) || size < 6 || size > 96) throw new Error("font size must be an integer from 6 to 96");
134
+ if (size === this.fontSize) return;
135
+ for (const font of this.fontCache.values()) font.delete();
136
+ for (const paragraph of this.paragraphCache.values()) paragraph.delete();
137
+ this.fontCache.clear();
138
+ this.metricsCache.clear();
139
+ this.paragraphCache.clear();
140
+ this.fontSize = size;
141
+ const font = this.fontFor(this.fonts.regular, size), metrics = font.getMetrics();
142
+ this.cellWidth = Math.max(1, Math.round(font.getGlyphWidths(this.fonts.regular.getGlyphIDs("M"))[0]));
143
+ this.cellHeight = Math.max(1, Math.round((metrics.descent-metrics.ascent+(metrics.leading||0))*this.lineHeight));
144
+ this.columns = Math.max(1, Math.floor(this.screen.width/this.cellWidth));
145
+ this.rows = Math.max(1, Math.floor(this.screen.height/this.cellHeight));
146
+ this.offsetX = Math.floor((this.screen.width-this.columns*this.cellWidth)/2);
147
+ this.offsetY = Math.floor((this.screen.height-this.rows*this.cellHeight)/2);
148
+ this.rowHashes = new Int32Array(this.rows);
149
+ this.rawCoveredRows = new Set();
150
+ this.forcedRows.clear();
151
+ this.lastCursor = {x:-1,y:-1,visible:false};
152
+ this.lastPointer = null;
153
+ this.invalidate();
154
+ }
155
+
130
156
  metricsFor(font) {
131
157
  let metrics = this.metricsCache.get(font);
132
158
  if (!metrics) {
@@ -214,7 +240,7 @@ export class Renderer {
214
240
  width * this.cellWidth, height * this.cellHeight);
215
241
  }
216
242
 
217
- drawText(text, x, y, cells, color, { bold, italic, emoji }) {
243
+ drawText(text, x, y, cells, color, { bold, italic, emoji, align = "center" }) {
218
244
  const { CanvasKit, canvas } = this;
219
245
  const available = cells * this.cellWidth;
220
246
  const paint = this.paintFor(color);
@@ -235,7 +261,7 @@ export class Renderer {
235
261
  }
236
262
  const metrics = this.metricsFor(font);
237
263
  const baseline = y + (this.cellHeight - (metrics.descent - metrics.ascent)) / 2 - metrics.ascent;
238
- canvas.drawGlyphs([glyph], [x + (available - advance) / 2, baseline], 0, 0, font, paint);
264
+ canvas.drawGlyphs([glyph], [align === "left" ? x : x + (available - advance) / 2, baseline], 0, 0, font, paint);
239
265
  return;
240
266
  }
241
267
  // Grapheme clusters are shaped by the Paragraph API and cached.
@@ -272,13 +298,13 @@ export class Renderer {
272
298
  const height = paragraph.getHeight();
273
299
  canvas.save();
274
300
  canvas.clipRect(CanvasKit.XYWHRect(x, y, available, this.cellHeight), CanvasKit.ClipOp.Intersect, false);
275
- if (width > available) {
301
+ if (width > available && align !== "left") {
276
302
  const scale = available / width;
277
303
  canvas.translate(x, y + (this.cellHeight - height * scale) / 2);
278
304
  canvas.scale(scale, scale);
279
305
  canvas.drawParagraph(paragraph, 0, 0);
280
306
  } else {
281
- canvas.drawParagraph(paragraph, x + (available - width) / 2, y + (this.cellHeight - height) / 2);
307
+ canvas.drawParagraph(paragraph, align === "left" ? x : x + (available - width) / 2, y + (this.cellHeight - height) / 2);
282
308
  }
283
309
  canvas.restore();
284
310
  }
@@ -322,15 +348,24 @@ export class Renderer {
322
348
  }
323
349
  }
324
350
 
325
- drawRow(line, row) {
326
- const { canvas } = this;
327
- canvas.drawRect(this.cellRect(0, row, this.columns, 1), this.paintFor(this.background));
328
- if (!line) return;
329
- for (let column = 0; column < this.columns; column++) {
330
- const cell = line.getCell(column);
331
- if (!cell) break;
332
- this.drawCell(cell, column, row);
351
+ drawRow(line, row, hidden = []) {
352
+ const draw = (first, end) => {
353
+ if(end<=first)return;
354
+ this.canvas.drawRect(this.cellRect(first,row,end-first,1),this.paintFor(this.background));
355
+ if(!line)return;
356
+ for(let column=first;column<end;column++){
357
+ const cell=line.getCell(column);if(!cell)break;
358
+ this.drawCell(cell,column,row);
359
+ }
360
+ };
361
+ // Retain two boundary cells for wide glyphs and italic overhang. Interior
362
+ // pixels will be replaced by the opaque image; omit their background too.
363
+ let column=0;
364
+ for(const [first,end] of hidden.map(([a,b])=>[a+2,b-2]).sort((a,b)=>a[0]-b[0])){
365
+ draw(column,Math.min(this.columns,first));
366
+ column=Math.max(column,end);
333
367
  }
368
+ draw(column,this.columns);
334
369
  }
335
370
 
336
371
  drawCursor(line, x, y) {
@@ -395,25 +430,54 @@ export class Renderer {
395
430
  // screen pixels, from images.js, drawn over the text; `pointer` is the
396
431
  // mouse position in pixels, drawn last. Returns true when anything was
397
432
  // painted.
398
- render(term, { cursor, images = [], pointer = null } = {}) {
433
+ render(term, { cursor, images = [], pointer = null, overlay = null } = {}) {
399
434
  const buffer = term.buffer.active;
400
435
  const top = buffer.viewportY;
401
436
  const dirty = [];
437
+ // Only proven opaque, exact raw copies may hide text work. Partial-height
438
+ // rows, scaling, transparency and unsupported layouts remain unchanged.
439
+ const coveredRows = new Set(), coveredSpans = new Map();
440
+ const previousSpans = this.rawCoveredSpans ?? new Map();
441
+ const previouslyCovered = this.rawCoveredRows ?? new Set();
442
+ for (const {image, rect, source} of images) {
443
+ const bounds = source || [0, 0, image.width(), image.height()];
444
+ if (!this.screen.canDrawRawImage?.(image, rect, bounds)) continue;
445
+ const left=Math.max(0,Math.ceil((rect[0]-this.offsetX)/this.cellWidth));
446
+ const right=Math.min(this.columns,Math.floor((rect[2]-this.offsetX)/this.cellWidth));
447
+ const first = Math.max(0, Math.ceil((rect[1] - this.offsetY) / this.cellHeight));
448
+ const end = Math.min(this.rows, Math.floor((rect[3] - this.offsetY) / this.cellHeight));
449
+ for (let row = first; row < end; row++) {
450
+ if(left===0 && right===this.columns)coveredRows.add(row);
451
+ else if(right-left>4){
452
+ const spans=coveredSpans.get(row)??[];spans.push([left,right]);coveredSpans.set(row,spans);
453
+ }
454
+ }
455
+ }
402
456
  for (let row = 0; row < this.rows; row++) {
403
457
  const line = buffer.getLine(top + row);
404
- const hash = line ? this.rowHash(line, this.columns) : 0;
405
- if (this.dirtyAll || hash !== this.rowHashes[row] || this.forcedRows.has(row)) {
458
+ const hash = coveredRows.has(row) ? this.rowHashes[row] : line ? this.rowHash(line, this.columns) : 0;
459
+ if (this.dirtyAll || hash !== this.rowHashes[row] || this.forcedRows.has(row)
460
+ || coveredRows.has(row) !== previouslyCovered.has(row)
461
+ || (coveredSpans.get(row)?.length??0)!==(previousSpans.get(row)?.length??0)
462
+ || coveredSpans.get(row)?.some(([a,b],i)=>a!==previousSpans.get(row)?.[i]?.[0]||b!==previousSpans.get(row)?.[i]?.[1])) {
406
463
  dirty.push(row);
407
464
  this.rowHashes[row] = hash;
408
465
  }
409
466
  }
467
+ this.rawCoveredRows = coveredRows;
468
+ this.rawCoveredSpans = coveredSpans;
410
469
  this.forcedRows.clear();
470
+ const localPointer = Boolean(this.screen.saveRegion && this.screen.restoreRegion);
471
+ const pointerChanged = this.lastPointer?.x !== pointer?.x || this.lastPointer?.y !== pointer?.y;
472
+ const cursorChanged = this.lastCursor.x !== (cursor?.x ?? -1)
473
+ || this.lastCursor.y !== (cursor?.y ?? -1)
474
+ || this.lastCursor.visible !== Boolean(cursor?.visible);
411
475
  const cursorRows = new Set();
412
- if (this.lastCursor.visible) cursorRows.add(this.lastCursor.y);
413
- if (cursor?.visible) cursorRows.add(cursor.y);
476
+ if ((!localPointer || cursorChanged) && this.lastCursor.visible) cursorRows.add(this.lastCursor.y);
477
+ if ((!localPointer || cursorChanged) && cursor?.visible) cursorRows.add(cursor.y);
414
478
  // Wherever the pointer was and is has to be repainted: the text under it
415
479
  // has not changed, so no row hash would say so.
416
- for (const position of [this.lastPointer, pointer]) {
480
+ for (const position of localPointer ? [] : [this.lastPointer, pointer]) {
417
481
  if (!position) continue;
418
482
  const [first, last] = this.pointerRows(position);
419
483
  for (let row = Math.max(0, first); row < Math.min(this.rows, last); row++) cursorRows.add(row);
@@ -421,19 +485,35 @@ export class Renderer {
421
485
  for (const row of cursorRows) {
422
486
  if (row >= 0 && row < this.rows && !dirty.includes(row)) dirty.push(row);
423
487
  }
488
+ if (!dirty.length && !this.dirtyAll && (!localPointer || !pointerChanged)) return false;
489
+ if (this.pointerBackground) {
490
+ this.screen.restoreRegion(this.pointerBackground);
491
+ this.pointerBackground = null;
492
+ }
424
493
  if (this.dirtyAll) {
425
494
  this.canvas.clear(this.CanvasKit.Color(this.background[0], this.background[1], this.background[2]));
426
495
  }
427
496
  this.dirtyAll = false;
428
- if (!dirty.length) return false;
429
497
  dirty.sort((a, b) => a - b);
430
- for (const row of dirty) this.drawRow(buffer.getLine(top + row), row);
431
- if (cursor?.visible && cursor.y >= 0 && cursor.y < this.rows) {
498
+ for (const row of dirty) {
499
+ if (!coveredRows.has(row)) this.drawRow(buffer.getLine(top + row), row, coveredSpans.get(row));
500
+ }
501
+ if (cursor?.visible && !coveredRows.has(cursor.y) && dirty.includes(cursor.y)) {
432
502
  this.drawCursor(buffer.getLine(top + cursor.y), cursor.x, cursor.y);
433
503
  }
434
504
  this.lastCursor = { x: cursor?.x ?? -1, y: cursor?.y ?? -1, visible: Boolean(cursor?.visible) };
435
- if (images.length) this.drawImages(images, dirty);
436
- if (pointer) this.drawPointer(pointer);
505
+ if (images.length && dirty.length) this.drawImages(images, dirty);
506
+ if (overlay && dirty.length) overlay();
507
+ if (pointer) {
508
+ if (localPointer) {
509
+ const size = Math.max(10, Math.round(this.fontSize * 0.9));
510
+ // Include the mitered outline and anti-aliasing outside the arrow path.
511
+ const padding = Math.ceil(Math.max(1, size / 8) * 2) + 2;
512
+ this.pointerBackground = this.screen.saveRegion(pointer.x - padding, pointer.y - padding,
513
+ pointer.x + size * 0.72 + padding, pointer.y + size * 1.08 + padding);
514
+ }
515
+ this.drawPointer(pointer);
516
+ }
437
517
  this.lastPointer = pointer ? { x: pointer.x, y: pointer.y } : null;
438
518
  this.screen.flush();
439
519
  return true;
@@ -442,16 +522,24 @@ export class Renderer {
442
522
  // Redraws the parts of image placements that intersect the repainted rows.
443
523
  drawImages(images, dirtyRows) {
444
524
  const { CanvasKit, canvas } = this;
525
+ const bands = [];
526
+ for (const row of dirtyRows) {
527
+ const top = this.offsetY + row * this.cellHeight, bottom = top + this.cellHeight;
528
+ const last = bands.at(-1);
529
+ if (last && last[1] === top) last[1] = bottom;
530
+ else bands.push([top, bottom]);
531
+ }
445
532
  for (const { image, rect, source } of images) {
446
533
  const [left, top, right, bottom] = rect;
447
- const sourceRect = source ? CanvasKit.LTRBRect(...source) : CanvasKit.LTRBRect(0, 0, image.width(), image.height());
448
- for (const row of dirtyRows) {
449
- const rowTop = this.offsetY + row * this.cellHeight;
450
- const rowBottom = rowTop + this.cellHeight;
534
+ if (!bands.some(([y0, y1]) => bottom > y0 && top < y1)) continue;
535
+ const bounds = source || [0, 0, image.width(), image.height()];
536
+ if (this.screen.drawOpaqueImage?.(image, rect, bounds, bands)) continue;
537
+ const sourceRect = CanvasKit.LTRBRect(...bounds);
538
+ for (const [rowTop, rowBottom] of bands) {
451
539
  if (bottom <= rowTop || top >= rowBottom) continue;
452
540
  canvas.save();
453
541
  canvas.clipRect(CanvasKit.LTRBRect(0, rowTop, this.screen.width, rowBottom), CanvasKit.ClipOp.Intersect, false);
454
- canvas.drawImageRectOptions(image, sourceRect, CanvasKit.LTRBRect(left, top, right, bottom),
542
+ canvas.drawImageRectOptions(skiaImage(image), sourceRect, CanvasKit.LTRBRect(left, top, right, bottom),
455
543
  CanvasKit.FilterMode.Linear, CanvasKit.MipmapMode.Linear, null);
456
544
  canvas.restore();
457
545
  }
@@ -0,0 +1,60 @@
1
+ // Coordinates are buffer cells, not UTF-16 indices. Endpoints include a whole
2
+ // grapheme, even when the mouse hits the continuation cell of a wide character.
3
+ export function createSelection(term, renderer, changed) {
4
+ let anchor = null, end = null, dragging = false;
5
+ const clear = () => { if (anchor) { anchor = end = null; dragging = false; changed(); } };
6
+ const point = report => {
7
+ const x = Math.max(0, Math.min(term.cols - 1, Math.floor((report.x - renderer.offsetX) / renderer.cellWidth)));
8
+ const y = term.buffer.active.viewportY + Math.max(0, Math.min(term.rows - 1,
9
+ Math.floor((report.y - renderer.offsetY) / renderer.cellHeight)));
10
+ return {x,y};
11
+ };
12
+ const bounds = () => {
13
+ if (!anchor) return null;
14
+ let [a,b] = anchor.y < end.y || anchor.y === end.y && anchor.x <= end.x ? [anchor,end] : [end,anchor];
15
+ const first = term.buffer.active.getLine(a.y), last = term.buffer.active.getLine(b.y);
16
+ let start = a.x, stop = b.x;
17
+ if (first?.getCell(start)?.getWidth() === 0) start = Math.max(0,start-1);
18
+ if (last?.getCell(stop)?.getWidth() === 0) stop = Math.max(0,stop-1);
19
+ stop += Math.max(1,last?.getCell(stop)?.getWidth() || 1);
20
+ return {a:{x:start,y:a.y},b:{x:stop,y:b.y}};
21
+ };
22
+ return {
23
+ clear,
24
+ stop() { dragging = false; },
25
+ get active() { return !!anchor; },
26
+ pointer(report) {
27
+ if (term._core?.coreMouseService?.areMouseEventsActive) { clear(); return false; }
28
+ if (report.pressed.includes("left")) { anchor = end = point(report); dragging = true; changed(); }
29
+ if (dragging && (report.moved || report.released.includes("left"))) { end = point(report); changed(); }
30
+ if (report.released.includes("left")) dragging = false;
31
+ return true;
32
+ },
33
+ text() {
34
+ const range = bounds();
35
+ if (!range) return "";
36
+ const {a,b} = range;
37
+ let text = "";
38
+ for (let y = a.y; y <= b.y; y++) {
39
+ const line = term.buffer.active.getLine(y);
40
+ if (!line) continue;
41
+ const start = y === a.y ? a.x : 0, stop = y === b.y ? b.x : term.cols;
42
+ if (y > a.y && !line.isWrapped) text += "\n";
43
+ // Wrapped rows join without a newline or lost meaningful spaces.
44
+ const nextWrapped = y < b.y && term.buffer.active.getLine(y + 1)?.isWrapped;
45
+ text += line.translateToString(!nextWrapped, start, stop);
46
+ }
47
+ return text;
48
+ },
49
+ draw() {
50
+ const range = bounds();
51
+ if (!range) return;
52
+ const {a,b} = range, top = term.buffer.active.viewportY;
53
+ for (let y = Math.max(a.y,top); y <= Math.min(b.y,top+term.rows-1); y++) {
54
+ const start = y === a.y ? a.x : 0, stop = y === b.y ? b.x : term.cols;
55
+ renderer.canvas.drawRect(renderer.cellRect(start,y-top,stop-start),
56
+ renderer.paintFor([70,150,220],95));
57
+ }
58
+ },
59
+ };
60
+ }