@dst0/p-tui 0.4.41 → 5.0.2

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 (387) hide show
  1. package/dist/autocomplete.d.ts.map +1 -1
  2. package/dist/autocomplete.js.map +1 -1
  3. package/dist/components/box.d.ts +3 -1
  4. package/dist/components/box.d.ts.map +1 -1
  5. package/dist/components/box.js +19 -10
  6. package/dist/components/box.js.map +1 -1
  7. package/dist/components/cancellable-loader.d.ts.map +1 -1
  8. package/dist/components/cancellable-loader.js.map +1 -1
  9. package/dist/components/editor/constants.d.ts +9 -0
  10. package/dist/components/editor/constants.d.ts.map +1 -0
  11. package/dist/components/editor/constants.js +12 -0
  12. package/dist/components/editor/constants.js.map +1 -0
  13. package/dist/components/editor/editor-methods/autocomplete-matching.d.ts +29 -0
  14. package/dist/components/editor/editor-methods/autocomplete-matching.d.ts.map +1 -0
  15. package/dist/components/editor/editor-methods/autocomplete-matching.js +104 -0
  16. package/dist/components/editor/editor-methods/autocomplete-matching.js.map +1 -0
  17. package/dist/components/editor/editor-methods/autocomplete-request.d.ts +14 -0
  18. package/dist/components/editor/editor-methods/autocomplete-request.d.ts.map +1 -0
  19. package/dist/components/editor/editor-methods/autocomplete-request.js +72 -0
  20. package/dist/components/editor/editor-methods/autocomplete-request.js.map +1 -0
  21. package/dist/components/editor/editor-methods/backspace-cursor.d.ts +9 -0
  22. package/dist/components/editor/editor-methods/backspace-cursor.d.ts.map +1 -0
  23. package/dist/components/editor/editor-methods/backspace-cursor.js +122 -0
  24. package/dist/components/editor/editor-methods/backspace-cursor.js.map +1 -0
  25. package/dist/components/editor/editor-methods/configuration.d.ts +17 -0
  26. package/dist/components/editor/editor-methods/configuration.d.ts.map +1 -0
  27. package/dist/components/editor/editor-methods/configuration.js +107 -0
  28. package/dist/components/editor/editor-methods/configuration.js.map +1 -0
  29. package/dist/components/editor/editor-methods/cursor-movement.d.ts +7 -0
  30. package/dist/components/editor/editor-methods/cursor-movement.d.ts.map +1 -0
  31. package/dist/components/editor/editor-methods/cursor-movement.js +112 -0
  32. package/dist/components/editor/editor-methods/cursor-movement.js.map +1 -0
  33. package/dist/components/editor/editor-methods/input-handling.d.ts +3 -0
  34. package/dist/components/editor/editor-methods/input-handling.d.ts.map +1 -0
  35. package/dist/components/editor/editor-methods/input-handling.js +257 -0
  36. package/dist/components/editor/editor-methods/input-handling.js.map +1 -0
  37. package/dist/components/editor/editor-methods/paste-submit.d.ts +7 -0
  38. package/dist/components/editor/editor-methods/paste-submit.d.ts.map +1 -0
  39. package/dist/components/editor/editor-methods/paste-submit.js +105 -0
  40. package/dist/components/editor/editor-methods/paste-submit.js.map +1 -0
  41. package/dist/components/editor/editor-methods/render.d.ts +3 -0
  42. package/dist/components/editor/editor-methods/render.d.ts.map +1 -0
  43. package/dist/components/editor/editor-methods/render.js +114 -0
  44. package/dist/components/editor/editor-methods/render.js.map +1 -0
  45. package/dist/components/editor/editor-methods/text-insertion.d.ts +4 -0
  46. package/dist/components/editor/editor-methods/text-insertion.d.ts.map +1 -0
  47. package/dist/components/editor/editor-methods/text-insertion.js +91 -0
  48. package/dist/components/editor/editor-methods/text-insertion.js.map +1 -0
  49. package/dist/components/editor/editor-methods/text-layout.d.ts +15 -0
  50. package/dist/components/editor/editor-methods/text-layout.d.ts.map +1 -0
  51. package/dist/components/editor/editor-methods/text-layout.js +129 -0
  52. package/dist/components/editor/editor-methods/text-layout.js.map +1 -0
  53. package/dist/components/editor/editor-methods/vertical-movement.d.ts +8 -0
  54. package/dist/components/editor/editor-methods/vertical-movement.d.ts.map +1 -0
  55. package/dist/components/editor/editor-methods/vertical-movement.js +123 -0
  56. package/dist/components/editor/editor-methods/vertical-movement.js.map +1 -0
  57. package/dist/components/editor/editor-methods/word-operations.d.ts +19 -0
  58. package/dist/components/editor/editor-methods/word-operations.d.ts.map +1 -0
  59. package/dist/components/editor/editor-methods/word-operations.js +122 -0
  60. package/dist/components/editor/editor-methods/word-operations.js.map +1 -0
  61. package/dist/components/editor/editor-methods/yank-undo.d.ts +11 -0
  62. package/dist/components/editor/editor-methods/yank-undo.d.ts.map +1 -0
  63. package/dist/components/editor/editor-methods/yank-undo.js +132 -0
  64. package/dist/components/editor/editor-methods/yank-undo.js.map +1 -0
  65. package/dist/components/editor/editor.d.ts +67 -0
  66. package/dist/components/editor/editor.d.ts.map +1 -0
  67. package/dist/components/editor/editor.js +93 -0
  68. package/dist/components/editor/editor.js.map +1 -0
  69. package/dist/components/editor/helpers.d.ts +3 -0
  70. package/dist/components/editor/helpers.d.ts.map +1 -0
  71. package/dist/components/editor/helpers.js +3 -0
  72. package/dist/components/editor/helpers.js.map +1 -0
  73. package/dist/components/editor/index.d.ts +4 -0
  74. package/dist/components/editor/index.d.ts.map +1 -0
  75. package/dist/components/editor/index.js +3 -0
  76. package/dist/components/editor/index.js.map +1 -0
  77. package/dist/components/editor/paste-marker.d.ts +5 -0
  78. package/dist/components/editor/paste-marker.d.ts.map +1 -0
  79. package/dist/components/editor/paste-marker.js +134 -0
  80. package/dist/components/editor/paste-marker.js.map +1 -0
  81. package/dist/components/editor/trigger-patterns.d.ts +4 -0
  82. package/dist/components/editor/trigger-patterns.d.ts.map +1 -0
  83. package/dist/components/editor/trigger-patterns.js +11 -0
  84. package/dist/components/editor/trigger-patterns.js.map +1 -0
  85. package/dist/components/editor/types.d.ts +25 -0
  86. package/dist/components/editor/types.d.ts.map +1 -0
  87. package/dist/components/editor/types.js +2 -0
  88. package/dist/components/editor/types.js.map +1 -0
  89. package/dist/components/editor.d.ts +1 -253
  90. package/dist/components/editor.d.ts.map +1 -1
  91. package/dist/components/editor.js +1 -1915
  92. package/dist/components/editor.js.map +1 -1
  93. package/dist/components/image.d.ts.map +1 -1
  94. package/dist/components/image.js.map +1 -1
  95. package/dist/components/input/constants.d.ts +2 -0
  96. package/dist/components/input/constants.d.ts.map +1 -0
  97. package/dist/components/input/constants.js +3 -0
  98. package/dist/components/input/constants.js.map +1 -0
  99. package/dist/components/input/index.d.ts +2 -0
  100. package/dist/components/input/index.d.ts.map +1 -0
  101. package/dist/components/input/index.js +2 -0
  102. package/dist/components/input/index.js.map +1 -0
  103. package/dist/components/input/input-methods/input-handling.d.ts +3 -0
  104. package/dist/components/input/input-methods/input-handling.d.ts.map +1 -0
  105. package/dist/components/input/input-methods/input-handling.js +145 -0
  106. package/dist/components/input/input-methods/input-handling.js.map +1 -0
  107. package/dist/components/input/input-methods/render.d.ts +3 -0
  108. package/dist/components/input/input-methods/render.d.ts.map +1 -0
  109. package/dist/components/input/input-methods/render.js +62 -0
  110. package/dist/components/input/input-methods/render.js.map +1 -0
  111. package/dist/components/input/input-methods/text-editing.d.ts +17 -0
  112. package/dist/components/input/input-methods/text-editing.d.ts.map +1 -0
  113. package/dist/components/input/input-methods/text-editing.js +145 -0
  114. package/dist/components/input/input-methods/text-editing.js.map +1 -0
  115. package/dist/components/input/input-methods/value-access.d.ts +4 -0
  116. package/dist/components/input/input-methods/value-access.d.ts.map +1 -0
  117. package/dist/components/input/input-methods/value-access.js +20 -0
  118. package/dist/components/input/input-methods/value-access.js.map +1 -0
  119. package/dist/components/input/input.d.ts +37 -0
  120. package/dist/components/input/input.d.ts.map +1 -0
  121. package/dist/components/input/input.js +77 -0
  122. package/dist/components/input/input.js.map +1 -0
  123. package/dist/components/input/types.d.ts +5 -0
  124. package/dist/components/input/types.d.ts.map +1 -0
  125. package/dist/components/input/types.js +2 -0
  126. package/dist/components/input/types.js.map +1 -0
  127. package/dist/components/input.d.ts +1 -36
  128. package/dist/components/input.d.ts.map +1 -1
  129. package/dist/components/input.js +1 -377
  130. package/dist/components/input.js.map +1 -1
  131. package/dist/components/loader.d.ts.map +1 -1
  132. package/dist/components/loader.js.map +1 -1
  133. package/dist/components/markdown/constants.d.ts +4 -0
  134. package/dist/components/markdown/constants.d.ts.map +1 -0
  135. package/dist/components/markdown/constants.js +8 -0
  136. package/dist/components/markdown/constants.js.map +1 -0
  137. package/dist/components/markdown/index.d.ts +3 -0
  138. package/dist/components/markdown/index.d.ts.map +1 -0
  139. package/dist/components/markdown/index.js +2 -0
  140. package/dist/components/markdown/index.js.map +1 -0
  141. package/dist/components/markdown/markdown-methods/inline-rendering.d.ts +7 -0
  142. package/dist/components/markdown/markdown-methods/inline-rendering.d.ts.map +1 -0
  143. package/dist/components/markdown/markdown-methods/inline-rendering.js +95 -0
  144. package/dist/components/markdown/markdown-methods/inline-rendering.js.map +1 -0
  145. package/dist/components/markdown/markdown-methods/list-table-helpers.d.ts +7 -0
  146. package/dist/components/markdown/markdown-methods/list-table-helpers.d.ts.map +1 -0
  147. package/dist/components/markdown/markdown-methods/list-table-helpers.js +61 -0
  148. package/dist/components/markdown/markdown-methods/list-table-helpers.js.map +1 -0
  149. package/dist/components/markdown/markdown-methods/table-rendering.d.ts +5 -0
  150. package/dist/components/markdown/markdown-methods/table-rendering.d.ts.map +1 -0
  151. package/dist/components/markdown/markdown-methods/table-rendering.js +146 -0
  152. package/dist/components/markdown/markdown-methods/table-rendering.js.map +1 -0
  153. package/dist/components/markdown/markdown-methods/text-rendering.d.ts +6 -0
  154. package/dist/components/markdown/markdown-methods/text-rendering.d.ts.map +1 -0
  155. package/dist/components/markdown/markdown-methods/text-rendering.js +115 -0
  156. package/dist/components/markdown/markdown-methods/text-rendering.js.map +1 -0
  157. package/dist/components/markdown/markdown-methods/theming.d.ts +6 -0
  158. package/dist/components/markdown/markdown-methods/theming.d.ts.map +1 -0
  159. package/dist/components/markdown/markdown-methods/theming.js +41 -0
  160. package/dist/components/markdown/markdown-methods/theming.js.map +1 -0
  161. package/dist/components/markdown/markdown-methods/token-rendering.d.ts +5 -0
  162. package/dist/components/markdown/markdown-methods/token-rendering.d.ts.map +1 -0
  163. package/dist/components/markdown/markdown-methods/token-rendering.js +142 -0
  164. package/dist/components/markdown/markdown-methods/token-rendering.js.map +1 -0
  165. package/dist/components/markdown/markdown.d.ts +32 -0
  166. package/dist/components/markdown/markdown.d.ts.map +1 -0
  167. package/dist/components/markdown/markdown.js +72 -0
  168. package/dist/components/markdown/markdown.js.map +1 -0
  169. package/dist/components/markdown/strictstrikethroughtokenizer.d.ts +6 -0
  170. package/dist/components/markdown/strictstrikethroughtokenizer.d.ts.map +1 -0
  171. package/dist/components/markdown/strictstrikethroughtokenizer.js +18 -0
  172. package/dist/components/markdown/strictstrikethroughtokenizer.js.map +1 -0
  173. package/dist/components/markdown/types.d.ts +42 -0
  174. package/dist/components/markdown/types.d.ts.map +1 -0
  175. package/dist/components/markdown/types.js +2 -0
  176. package/dist/components/markdown/types.js.map +1 -0
  177. package/dist/components/markdown.d.ts +1 -96
  178. package/dist/components/markdown.d.ts.map +1 -1
  179. package/dist/components/markdown.js +1 -653
  180. package/dist/components/markdown.js.map +1 -1
  181. package/dist/components/select-list.d.ts.map +1 -1
  182. package/dist/components/select-list.js +8 -3
  183. package/dist/components/select-list.js.map +1 -1
  184. package/dist/components/settings-list.d.ts.map +1 -1
  185. package/dist/components/settings-list.js +2 -6
  186. package/dist/components/settings-list.js.map +1 -1
  187. package/dist/components/spacer.d.ts.map +1 -1
  188. package/dist/components/spacer.js.map +1 -1
  189. package/dist/components/text.d.ts.map +1 -1
  190. package/dist/components/text.js +2 -2
  191. package/dist/components/text.js.map +1 -1
  192. package/dist/components/truncated-text.d.ts.map +1 -1
  193. package/dist/components/truncated-text.js.map +1 -1
  194. package/dist/editor-component.d.ts.map +1 -1
  195. package/dist/editor-component.js.map +1 -1
  196. package/dist/fuzzy.d.ts.map +1 -1
  197. package/dist/fuzzy.js.map +1 -1
  198. package/dist/index.d.ts +1 -1
  199. package/dist/index.d.ts.map +1 -1
  200. package/dist/index.js +1 -1
  201. package/dist/index.js.map +1 -1
  202. package/dist/keybindings.d.ts.map +1 -1
  203. package/dist/keybindings.js.map +1 -1
  204. package/dist/keys.d.ts.map +1 -1
  205. package/dist/keys.js +145 -14
  206. package/dist/keys.js.map +1 -1
  207. package/dist/kill-ring.d.ts.map +1 -1
  208. package/dist/kill-ring.js.map +1 -1
  209. package/dist/native-modifiers.d.ts +9 -0
  210. package/dist/native-modifiers.d.ts.map +1 -1
  211. package/dist/native-modifiers.js +5 -0
  212. package/dist/native-modifiers.js.map +1 -1
  213. package/dist/stdin-buffer.d.ts +3 -0
  214. package/dist/stdin-buffer.d.ts.map +1 -1
  215. package/dist/stdin-buffer.js +24 -21
  216. package/dist/stdin-buffer.js.map +1 -1
  217. package/dist/terminal/constants.d.ts +9 -0
  218. package/dist/terminal/constants.d.ts.map +1 -0
  219. package/dist/terminal/constants.js +10 -0
  220. package/dist/terminal/constants.js.map +1 -0
  221. package/dist/terminal/helpers.d.ts +6 -0
  222. package/dist/terminal/helpers.d.ts.map +1 -0
  223. package/dist/terminal/helpers.js +23 -0
  224. package/dist/terminal/helpers.js.map +1 -0
  225. package/dist/terminal/index.d.ts +4 -0
  226. package/dist/terminal/index.d.ts.map +1 -0
  227. package/dist/terminal/index.js +3 -0
  228. package/dist/terminal/index.js.map +1 -0
  229. package/dist/terminal/processterminal-methods/cursor-screen.d.ts +11 -0
  230. package/dist/terminal/processterminal-methods/cursor-screen.d.ts.map +1 -0
  231. package/dist/terminal/processterminal-methods/cursor-screen.js +50 -0
  232. package/dist/terminal/processterminal-methods/cursor-screen.js.map +1 -0
  233. package/dist/terminal/processterminal-methods/keyboard-protocol.d.ts +14 -0
  234. package/dist/terminal/processterminal-methods/keyboard-protocol.d.ts.map +1 -0
  235. package/dist/terminal/processterminal-methods/keyboard-protocol.js +147 -0
  236. package/dist/terminal/processterminal-methods/keyboard-protocol.js.map +1 -0
  237. package/dist/terminal/processterminal-methods/terminal-io.d.ts +9 -0
  238. package/dist/terminal/processterminal-methods/terminal-io.d.ts.map +1 -0
  239. package/dist/terminal/processterminal-methods/terminal-io.js +153 -0
  240. package/dist/terminal/processterminal-methods/terminal-io.js.map +1 -0
  241. package/dist/terminal/processterminal.d.ts +49 -0
  242. package/dist/terminal/processterminal.d.ts.map +1 -0
  243. package/dist/terminal/processterminal.js +129 -0
  244. package/dist/terminal/processterminal.js.map +1 -0
  245. package/dist/terminal/types.d.ts +31 -0
  246. package/dist/terminal/types.d.ts.map +1 -0
  247. package/dist/terminal/types.js +2 -0
  248. package/dist/terminal/types.js.map +1 -0
  249. package/dist/terminal-colors.d.ts +2 -0
  250. package/dist/terminal-colors.d.ts.map +1 -1
  251. package/dist/terminal-colors.js +17 -5
  252. package/dist/terminal-colors.js.map +1 -1
  253. package/dist/terminal-image.d.ts.map +1 -1
  254. package/dist/terminal-image.js.map +1 -1
  255. package/dist/terminal.d.ts +1 -109
  256. package/dist/terminal.d.ts.map +1 -1
  257. package/dist/terminal.js +1 -432
  258. package/dist/terminal.js.map +1 -1
  259. package/dist/tui/constants.d.ts +3 -0
  260. package/dist/tui/constants.d.ts.map +1 -0
  261. package/dist/tui/constants.js +3 -0
  262. package/dist/tui/constants.js.map +1 -0
  263. package/dist/tui/container.d.ts +10 -0
  264. package/dist/tui/container.d.ts.map +1 -0
  265. package/dist/tui/container.js +31 -0
  266. package/dist/tui/container.js.map +1 -0
  267. package/dist/tui/helpers.d.ts +8 -0
  268. package/dist/tui/helpers.d.ts.map +1 -0
  269. package/dist/tui/helpers.js +53 -0
  270. package/dist/tui/helpers.js.map +1 -0
  271. package/dist/tui/index.d.ts +6 -0
  272. package/dist/tui/index.d.ts.map +1 -0
  273. package/dist/tui/index.js +5 -0
  274. package/dist/tui/index.js.map +1 -0
  275. package/dist/tui/tui-methods/configuration.d.ts +20 -0
  276. package/dist/tui/tui-methods/configuration.d.ts.map +1 -0
  277. package/dist/tui/tui-methods/configuration.js +131 -0
  278. package/dist/tui/tui-methods/configuration.js.map +1 -0
  279. package/dist/tui/tui-methods/cursor-background.d.ts +10 -0
  280. package/dist/tui/tui-methods/cursor-background.d.ts.map +1 -0
  281. package/dist/tui/tui-methods/cursor-background.js +52 -0
  282. package/dist/tui/tui-methods/cursor-background.js.map +1 -0
  283. package/dist/tui/tui-methods/incremental-render.d.ts +17 -0
  284. package/dist/tui/tui-methods/incremental-render.d.ts.map +1 -0
  285. package/dist/tui/tui-methods/incremental-render.js +259 -0
  286. package/dist/tui/tui-methods/incremental-render.js.map +1 -0
  287. package/dist/tui/tui-methods/input-handling.d.ts +5 -0
  288. package/dist/tui/tui-methods/input-handling.d.ts.map +1 -0
  289. package/dist/tui/tui-methods/input-handling.js +111 -0
  290. package/dist/tui/tui-methods/input-handling.js.map +1 -0
  291. package/dist/tui/tui-methods/line-compositing.d.ts +7 -0
  292. package/dist/tui/tui-methods/line-compositing.d.ts.map +1 -0
  293. package/dist/tui/tui-methods/line-compositing.js +61 -0
  294. package/dist/tui/tui-methods/line-compositing.js.map +1 -0
  295. package/dist/tui/tui-methods/overlay-compositing.d.ts +12 -0
  296. package/dist/tui/tui-methods/overlay-compositing.d.ts.map +1 -0
  297. package/dist/tui/tui-methods/overlay-compositing.js +123 -0
  298. package/dist/tui/tui-methods/overlay-compositing.js.map +1 -0
  299. package/dist/tui/tui-methods/overlay-layout.d.ts +11 -0
  300. package/dist/tui/tui-methods/overlay-layout.d.ts.map +1 -0
  301. package/dist/tui/tui-methods/overlay-layout.js +124 -0
  302. package/dist/tui/tui-methods/overlay-layout.js.map +1 -0
  303. package/dist/tui/tui-methods/overlay-management.d.ts +11 -0
  304. package/dist/tui/tui-methods/overlay-management.d.ts.map +1 -0
  305. package/dist/tui/tui-methods/overlay-management.js +152 -0
  306. package/dist/tui/tui-methods/overlay-management.js.map +1 -0
  307. package/dist/tui/tui-methods/render-pipeline.d.ts +3 -0
  308. package/dist/tui/tui-methods/render-pipeline.d.ts.map +1 -0
  309. package/dist/tui/tui-methods/render-pipeline.js +176 -0
  310. package/dist/tui/tui-methods/render-pipeline.js.map +1 -0
  311. package/dist/tui/tui-methods/render-width-error.d.ts +3 -0
  312. package/dist/tui/tui-methods/render-width-error.d.ts.map +1 -0
  313. package/dist/tui/tui-methods/render-width-error.js +28 -0
  314. package/dist/tui/tui-methods/render-width-error.js.map +1 -0
  315. package/dist/tui/tui-methods/terminal-control.d.ts +8 -0
  316. package/dist/tui/tui-methods/terminal-control.d.ts.map +1 -0
  317. package/dist/tui/tui-methods/terminal-control.js +101 -0
  318. package/dist/tui/tui-methods/terminal-control.js.map +1 -0
  319. package/dist/tui/tui.d.ts +59 -0
  320. package/dist/tui/tui.d.ts.map +1 -0
  321. package/dist/tui/tui.js +78 -0
  322. package/dist/tui/tui.js.map +1 -0
  323. package/dist/tui/types.d.ts +124 -0
  324. package/dist/tui/types.d.ts.map +1 -0
  325. package/dist/tui/types.js +2 -0
  326. package/dist/tui/types.js.map +1 -0
  327. package/dist/tui.d.ts +1 -254
  328. package/dist/tui.d.ts.map +1 -1
  329. package/dist/tui.js +1 -1344
  330. package/dist/tui.js.map +1 -1
  331. package/dist/undo-stack.d.ts.map +1 -1
  332. package/dist/undo-stack.js.map +1 -1
  333. package/dist/utils/ansi-wrapping.d.ts +5 -0
  334. package/dist/utils/ansi-wrapping.d.ts.map +1 -0
  335. package/dist/utils/ansi-wrapping.js +52 -0
  336. package/dist/utils/ansi-wrapping.js.map +1 -0
  337. package/dist/utils/ansicodetracker.d.ts +27 -0
  338. package/dist/utils/ansicodetracker.d.ts.map +1 -0
  339. package/dist/utils/ansicodetracker.js +222 -0
  340. package/dist/utils/ansicodetracker.js.map +1 -0
  341. package/dist/utils/column-slicing.d.ts +12 -0
  342. package/dist/utils/column-slicing.d.ts.map +1 -0
  343. package/dist/utils/column-slicing.js +111 -0
  344. package/dist/utils/column-slicing.js.map +1 -0
  345. package/dist/utils/column-truncation.d.ts +2 -0
  346. package/dist/utils/column-truncation.d.ts.map +1 -0
  347. package/dist/utils/column-truncation.js +129 -0
  348. package/dist/utils/column-truncation.js.map +1 -0
  349. package/dist/utils/constants.d.ts +12 -0
  350. package/dist/utils/constants.d.ts.map +1 -0
  351. package/dist/utils/constants.js +12 -0
  352. package/dist/utils/constants.js.map +1 -0
  353. package/dist/utils/index.d.ts +8 -0
  354. package/dist/utils/index.d.ts.map +1 -0
  355. package/dist/utils/index.js +8 -0
  356. package/dist/utils/index.js.map +1 -0
  357. package/dist/utils/install-delegated-methods.d.ts +5 -0
  358. package/dist/utils/install-delegated-methods.d.ts.map +1 -0
  359. package/dist/utils/install-delegated-methods.js +27 -0
  360. package/dist/utils/install-delegated-methods.js.map +1 -0
  361. package/dist/utils/segmentation.d.ts +10 -0
  362. package/dist/utils/segmentation.d.ts.map +1 -0
  363. package/dist/utils/segmentation.js +111 -0
  364. package/dist/utils/segmentation.js.map +1 -0
  365. package/dist/utils/terminal-output.d.ts +10 -0
  366. package/dist/utils/terminal-output.d.ts.map +1 -0
  367. package/dist/utils/terminal-output.js +122 -0
  368. package/dist/utils/terminal-output.js.map +1 -0
  369. package/dist/utils/types.d.ts +7 -0
  370. package/dist/utils/types.d.ts.map +1 -0
  371. package/dist/utils/types.js +2 -0
  372. package/dist/utils/types.js.map +1 -0
  373. package/dist/utils/width-truncation.d.ts +6 -0
  374. package/dist/utils/width-truncation.d.ts.map +1 -0
  375. package/dist/utils/width-truncation.js +121 -0
  376. package/dist/utils/width-truncation.js.map +1 -0
  377. package/dist/utils/word-wrapping.d.ts +4 -0
  378. package/dist/utils/word-wrapping.d.ts.map +1 -0
  379. package/dist/utils/word-wrapping.js +139 -0
  380. package/dist/utils/word-wrapping.js.map +1 -0
  381. package/dist/utils.d.ts +1 -84
  382. package/dist/utils.d.ts.map +1 -1
  383. package/dist/utils.js +1 -1059
  384. package/dist/utils.js.map +1 -1
  385. package/dist/word-navigation.d.ts.map +1 -1
  386. package/dist/word-navigation.js.map +1 -1
  387. package/package.json +2 -1
@@ -0,0 +1,9 @@
1
+ import type { SelectListLayoutOptions } from "../select-list.ts";
2
+ export declare const graphemeSegmenter: Intl.Segmenter;
3
+ export declare const wordSegmenter: Intl.Segmenter;
4
+ export declare const PASTE_MARKER_REGEX: RegExp;
5
+ export declare const PASTE_MARKER_SINGLE: RegExp;
6
+ export declare const SLASH_COMMAND_SELECT_LIST_LAYOUT: SelectListLayoutOptions;
7
+ export declare const ATTACHMENT_AUTOCOMPLETE_DEBOUNCE_MS = 20;
8
+ export declare const DEFAULT_AUTOCOMPLETE_TRIGGER_CHARACTERS: string[];
9
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/components/editor/constants.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAEjE,eAAO,MAAM,iBAAiB,gBAAyB,CAAC;AAExD,eAAO,MAAM,aAAa,gBAAqB,CAAC;AAEhD,eAAO,MAAM,kBAAkB,QAAiD,CAAC;AAEjF,eAAO,MAAM,mBAAmB,QAAkD,CAAC;AAEnF,eAAO,MAAM,gCAAgC,EAAE,uBAG9C,CAAC;AAEF,eAAO,MAAM,mCAAmC,KAAK,CAAC;AAEtD,eAAO,MAAM,uCAAuC,UAAa,CAAC","sourcesContent":["import { getGraphemeSegmenter, getWordSegmenter } from \"../../utils.ts\";\nimport type { SelectListLayoutOptions } from \"../select-list.ts\";\n\nexport const graphemeSegmenter = getGraphemeSegmenter();\n\nexport const wordSegmenter = getWordSegmenter();\n\nexport const PASTE_MARKER_REGEX = /\\[paste #(\\d+)( (\\+\\d+ lines|\\d+ chars))?\\]/g;\n\nexport const PASTE_MARKER_SINGLE = /^\\[paste #(\\d+)( (\\+\\d+ lines|\\d+ chars))?\\]$/;\n\nexport const SLASH_COMMAND_SELECT_LIST_LAYOUT: SelectListLayoutOptions = {\n minPrimaryColumnWidth: 12,\n maxPrimaryColumnWidth: 32,\n};\n\nexport const ATTACHMENT_AUTOCOMPLETE_DEBOUNCE_MS = 20;\n\nexport const DEFAULT_AUTOCOMPLETE_TRIGGER_CHARACTERS = [\"@\", \"#\"];\n"]}
@@ -0,0 +1,12 @@
1
+ import { getGraphemeSegmenter, getWordSegmenter } from "../../utils.js";
2
+ export const graphemeSegmenter = getGraphemeSegmenter();
3
+ export const wordSegmenter = getWordSegmenter();
4
+ export const PASTE_MARKER_REGEX = /\[paste #(\d+)( (\+\d+ lines|\d+ chars))?\]/g;
5
+ export const PASTE_MARKER_SINGLE = /^\[paste #(\d+)( (\+\d+ lines|\d+ chars))?\]$/;
6
+ export const SLASH_COMMAND_SELECT_LIST_LAYOUT = {
7
+ minPrimaryColumnWidth: 12,
8
+ maxPrimaryColumnWidth: 32,
9
+ };
10
+ export const ATTACHMENT_AUTOCOMPLETE_DEBOUNCE_MS = 20;
11
+ export const DEFAULT_AUTOCOMPLETE_TRIGGER_CHARACTERS = ["@", "#"];
12
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/components/editor/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGxE,MAAM,CAAC,MAAM,iBAAiB,GAAG,oBAAoB,EAAE,CAAC;AAExD,MAAM,CAAC,MAAM,aAAa,GAAG,gBAAgB,EAAE,CAAC;AAEhD,MAAM,CAAC,MAAM,kBAAkB,GAAG,8CAA8C,CAAC;AAEjF,MAAM,CAAC,MAAM,mBAAmB,GAAG,+CAA+C,CAAC;AAEnF,MAAM,CAAC,MAAM,gCAAgC,GAA4B;IACvE,qBAAqB,EAAE,EAAE;IACzB,qBAAqB,EAAE,EAAE;CAC1B,CAAC;AAEF,MAAM,CAAC,MAAM,mCAAmC,GAAG,EAAE,CAAC;AAEtD,MAAM,CAAC,MAAM,uCAAuC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC","sourcesContent":["import { getGraphemeSegmenter, getWordSegmenter } from \"../../utils.ts\";\nimport type { SelectListLayoutOptions } from \"../select-list.ts\";\n\nexport const graphemeSegmenter = getGraphemeSegmenter();\n\nexport const wordSegmenter = getWordSegmenter();\n\nexport const PASTE_MARKER_REGEX = /\\[paste #(\\d+)( (\\+\\d+ lines|\\d+ chars))?\\]/g;\n\nexport const PASTE_MARKER_SINGLE = /^\\[paste #(\\d+)( (\\+\\d+ lines|\\d+ chars))?\\]$/;\n\nexport const SLASH_COMMAND_SELECT_LIST_LAYOUT: SelectListLayoutOptions = {\n minPrimaryColumnWidth: 12,\n maxPrimaryColumnWidth: 32,\n};\n\nexport const ATTACHMENT_AUTOCOMPLETE_DEBOUNCE_MS = 20;\n\nexport const DEFAULT_AUTOCOMPLETE_TRIGGER_CHARACTERS = [\"@\", \"#\"];\n"]}
@@ -0,0 +1,29 @@
1
+ import { SelectList } from "../../select-list.ts";
2
+ import type { Editor } from "../editor.ts";
3
+ export declare function do_getBestAutocompleteMatchIndex(_self: Editor, items: Array<{
4
+ value: string;
5
+ label: string;
6
+ }>, prefix: string): number;
7
+ export declare function do_createAutocompleteList(self: Editor, prefix: string, items: Array<{
8
+ value: string;
9
+ label: string;
10
+ description?: string;
11
+ }>): SelectList;
12
+ export declare function do_tryTriggerAutocomplete(self: Editor, explicitTab?: boolean): void;
13
+ export declare function do_handleTabCompletion(self: Editor): void;
14
+ export declare function do_handleSlashCommandCompletion(self: Editor): void;
15
+ export declare function do_forceFileAutocomplete(self: Editor, explicitTab?: boolean): void;
16
+ export declare function do_requestAutocomplete(self: Editor, options: {
17
+ force: boolean;
18
+ explicitTab: boolean;
19
+ }): void;
20
+ export declare function do_startAutocompleteRequest(self: Editor, startToken: number, options: {
21
+ force: boolean;
22
+ explicitTab: boolean;
23
+ }): Promise<void>;
24
+ export declare function do_setAutocompleteTriggerCharacters(self: Editor, triggerCharacters: string[]): void;
25
+ export declare function do_getAutocompleteDebounceMs(self: Editor, options: {
26
+ force: boolean;
27
+ explicitTab: boolean;
28
+ }): number;
29
+ //# sourceMappingURL=autocomplete-matching.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autocomplete-matching.d.ts","sourceRoot":"","sources":["../../../../src/components/editor/editor-methods/autocomplete-matching.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAMlD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAG3C,wBAAgB,gCAAgC,CAC9C,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,EAC9C,MAAM,EAAE,MAAM,GACb,MAAM,CAgBR;AAED,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GACnE,UAAU,CAGZ;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,GAAE,OAAe,GAAG,IAAI,CAE1F;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAWzD;AAED,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAElE;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,GAAE,OAAe,GAAG,IAAI,CAEzF;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CA6B5G;AAED,wBAAsB,2BAA2B,CAC/C,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,GAChD,OAAO,CAAC,IAAI,CAAC,CAkBf;AAED,wBAAgB,mCAAmC,CAAC,IAAI,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,GAAG,IAAI,CAWnG;AAED,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAQpH","sourcesContent":["import { isWhitespaceChar } from \"../../../utils.ts\";\nimport { SelectList } from \"../../select-list.ts\";\nimport {\n ATTACHMENT_AUTOCOMPLETE_DEBOUNCE_MS,\n DEFAULT_AUTOCOMPLETE_TRIGGER_CHARACTERS,\n SLASH_COMMAND_SELECT_LIST_LAYOUT,\n} from \"../constants.ts\";\nimport type { Editor } from \"../editor.ts\";\nimport { buildDebouncePattern, buildTriggerPattern } from \"../trigger-patterns.ts\";\n\nexport function do_getBestAutocompleteMatchIndex(\n _self: Editor,\n items: Array<{ value: string; label: string }>,\n prefix: string,\n): number {\n if (!prefix) return -1;\n\n let firstPrefixIndex = -1;\n\n for (let i = 0; i < items.length; i++) {\n const value = items[i]!.value;\n if (value === prefix) {\n return i; // Exact match always wins\n }\n if (firstPrefixIndex === -1 && value.startsWith(prefix)) {\n firstPrefixIndex = i;\n }\n }\n\n return firstPrefixIndex;\n}\n\nexport function do_createAutocompleteList(\n self: Editor,\n prefix: string,\n items: Array<{ value: string; label: string; description?: string }>,\n): SelectList {\n const layout = prefix.startsWith(\"/\") ? SLASH_COMMAND_SELECT_LIST_LAYOUT : undefined;\n return new SelectList(items, self.autocompleteMaxVisible, self.theme.selectList, layout);\n}\n\nexport function do_tryTriggerAutocomplete(self: Editor, explicitTab: boolean = false): void {\n self.requestAutocomplete({ force: false, explicitTab });\n}\n\nexport function do_handleTabCompletion(self: Editor): void {\n if (!self.autocompleteProvider) return;\n\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n const beforeCursor = currentLine.slice(0, self.state.cursorCol);\n\n if (self.isInSlashCommandContext(beforeCursor) && !beforeCursor.trimStart().includes(\" \")) {\n self.handleSlashCommandCompletion();\n } else {\n self.forceFileAutocomplete(true);\n }\n}\n\nexport function do_handleSlashCommandCompletion(self: Editor): void {\n self.requestAutocomplete({ force: false, explicitTab: true });\n}\n\nexport function do_forceFileAutocomplete(self: Editor, explicitTab: boolean = false): void {\n self.requestAutocomplete({ force: true, explicitTab });\n}\n\nexport function do_requestAutocomplete(self: Editor, options: { force: boolean; explicitTab: boolean }): void {\n if (!self.autocompleteProvider) return;\n\n if (options.force) {\n const shouldTrigger =\n !self.autocompleteProvider.shouldTriggerFileCompletion ||\n self.autocompleteProvider.shouldTriggerFileCompletion(\n self.state.lines,\n self.state.cursorLine,\n self.state.cursorCol,\n );\n if (!shouldTrigger) {\n return;\n }\n }\n\n self.cancelAutocompleteRequest();\n const startToken = ++self.autocompleteStartToken;\n\n const debounceMs = self.getAutocompleteDebounceMs(options);\n if (debounceMs > 0) {\n self.autocompleteDebounceTimer = setTimeout(() => {\n self.autocompleteDebounceTimer = undefined;\n void self.startAutocompleteRequest(startToken, options);\n }, debounceMs);\n return;\n }\n\n void self.startAutocompleteRequest(startToken, options);\n}\n\nexport async function do_startAutocompleteRequest(\n self: Editor,\n startToken: number,\n options: { force: boolean; explicitTab: boolean },\n): Promise<void> {\n const previousTask = self.autocompleteRequestTask;\n self.autocompleteRequestTask = (async () => {\n await previousTask;\n if (startToken !== self.autocompleteStartToken || !self.autocompleteProvider) {\n return;\n }\n\n const controller = new AbortController();\n self.autocompleteAbort = controller;\n const requestId = ++self.autocompleteRequestId;\n const snapshotText = self.getText();\n const snapshotLine = self.state.cursorLine;\n const snapshotCol = self.state.cursorCol;\n\n await self.runAutocompleteRequest(requestId, controller, snapshotText, snapshotLine, snapshotCol, options);\n })();\n await self.autocompleteRequestTask;\n}\n\nexport function do_setAutocompleteTriggerCharacters(self: Editor, triggerCharacters: string[]): void {\n const next = [...DEFAULT_AUTOCOMPLETE_TRIGGER_CHARACTERS];\n for (const character of triggerCharacters) {\n if (character.length !== 1 || character === \"/\" || isWhitespaceChar(character) || next.includes(character)) {\n continue;\n }\n next.push(character);\n }\n self.autocompleteTriggerCharacters = next;\n self.autocompleteTriggerPattern = buildTriggerPattern(next);\n self.autocompleteDebouncePattern = buildDebouncePattern(next);\n}\n\nexport function do_getAutocompleteDebounceMs(self: Editor, options: { force: boolean; explicitTab: boolean }): number {\n if (options.explicitTab || options.force) {\n return 0;\n }\n\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n const textBeforeCursor = currentLine.slice(0, self.state.cursorCol);\n return self.autocompleteDebouncePattern.test(textBeforeCursor) ? ATTACHMENT_AUTOCOMPLETE_DEBOUNCE_MS : 0;\n}\n"]}
@@ -0,0 +1,104 @@
1
+ import { isWhitespaceChar } from "../../../utils.js";
2
+ import { SelectList } from "../../select-list.js";
3
+ import { ATTACHMENT_AUTOCOMPLETE_DEBOUNCE_MS, DEFAULT_AUTOCOMPLETE_TRIGGER_CHARACTERS, SLASH_COMMAND_SELECT_LIST_LAYOUT, } from "../constants.js";
4
+ import { buildDebouncePattern, buildTriggerPattern } from "../trigger-patterns.js";
5
+ export function do_getBestAutocompleteMatchIndex(_self, items, prefix) {
6
+ if (!prefix)
7
+ return -1;
8
+ let firstPrefixIndex = -1;
9
+ for (let i = 0; i < items.length; i++) {
10
+ const value = items[i].value;
11
+ if (value === prefix) {
12
+ return i; // Exact match always wins
13
+ }
14
+ if (firstPrefixIndex === -1 && value.startsWith(prefix)) {
15
+ firstPrefixIndex = i;
16
+ }
17
+ }
18
+ return firstPrefixIndex;
19
+ }
20
+ export function do_createAutocompleteList(self, prefix, items) {
21
+ const layout = prefix.startsWith("/") ? SLASH_COMMAND_SELECT_LIST_LAYOUT : undefined;
22
+ return new SelectList(items, self.autocompleteMaxVisible, self.theme.selectList, layout);
23
+ }
24
+ export function do_tryTriggerAutocomplete(self, explicitTab = false) {
25
+ self.requestAutocomplete({ force: false, explicitTab });
26
+ }
27
+ export function do_handleTabCompletion(self) {
28
+ if (!self.autocompleteProvider)
29
+ return;
30
+ const currentLine = self.state.lines[self.state.cursorLine] || "";
31
+ const beforeCursor = currentLine.slice(0, self.state.cursorCol);
32
+ if (self.isInSlashCommandContext(beforeCursor) && !beforeCursor.trimStart().includes(" ")) {
33
+ self.handleSlashCommandCompletion();
34
+ }
35
+ else {
36
+ self.forceFileAutocomplete(true);
37
+ }
38
+ }
39
+ export function do_handleSlashCommandCompletion(self) {
40
+ self.requestAutocomplete({ force: false, explicitTab: true });
41
+ }
42
+ export function do_forceFileAutocomplete(self, explicitTab = false) {
43
+ self.requestAutocomplete({ force: true, explicitTab });
44
+ }
45
+ export function do_requestAutocomplete(self, options) {
46
+ if (!self.autocompleteProvider)
47
+ return;
48
+ if (options.force) {
49
+ const shouldTrigger = !self.autocompleteProvider.shouldTriggerFileCompletion ||
50
+ self.autocompleteProvider.shouldTriggerFileCompletion(self.state.lines, self.state.cursorLine, self.state.cursorCol);
51
+ if (!shouldTrigger) {
52
+ return;
53
+ }
54
+ }
55
+ self.cancelAutocompleteRequest();
56
+ const startToken = ++self.autocompleteStartToken;
57
+ const debounceMs = self.getAutocompleteDebounceMs(options);
58
+ if (debounceMs > 0) {
59
+ self.autocompleteDebounceTimer = setTimeout(() => {
60
+ self.autocompleteDebounceTimer = undefined;
61
+ void self.startAutocompleteRequest(startToken, options);
62
+ }, debounceMs);
63
+ return;
64
+ }
65
+ void self.startAutocompleteRequest(startToken, options);
66
+ }
67
+ export async function do_startAutocompleteRequest(self, startToken, options) {
68
+ const previousTask = self.autocompleteRequestTask;
69
+ self.autocompleteRequestTask = (async () => {
70
+ await previousTask;
71
+ if (startToken !== self.autocompleteStartToken || !self.autocompleteProvider) {
72
+ return;
73
+ }
74
+ const controller = new AbortController();
75
+ self.autocompleteAbort = controller;
76
+ const requestId = ++self.autocompleteRequestId;
77
+ const snapshotText = self.getText();
78
+ const snapshotLine = self.state.cursorLine;
79
+ const snapshotCol = self.state.cursorCol;
80
+ await self.runAutocompleteRequest(requestId, controller, snapshotText, snapshotLine, snapshotCol, options);
81
+ })();
82
+ await self.autocompleteRequestTask;
83
+ }
84
+ export function do_setAutocompleteTriggerCharacters(self, triggerCharacters) {
85
+ const next = [...DEFAULT_AUTOCOMPLETE_TRIGGER_CHARACTERS];
86
+ for (const character of triggerCharacters) {
87
+ if (character.length !== 1 || character === "/" || isWhitespaceChar(character) || next.includes(character)) {
88
+ continue;
89
+ }
90
+ next.push(character);
91
+ }
92
+ self.autocompleteTriggerCharacters = next;
93
+ self.autocompleteTriggerPattern = buildTriggerPattern(next);
94
+ self.autocompleteDebouncePattern = buildDebouncePattern(next);
95
+ }
96
+ export function do_getAutocompleteDebounceMs(self, options) {
97
+ if (options.explicitTab || options.force) {
98
+ return 0;
99
+ }
100
+ const currentLine = self.state.lines[self.state.cursorLine] || "";
101
+ const textBeforeCursor = currentLine.slice(0, self.state.cursorCol);
102
+ return self.autocompleteDebouncePattern.test(textBeforeCursor) ? ATTACHMENT_AUTOCOMPLETE_DEBOUNCE_MS : 0;
103
+ }
104
+ //# sourceMappingURL=autocomplete-matching.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autocomplete-matching.js","sourceRoot":"","sources":["../../../../src/components/editor/editor-methods/autocomplete-matching.ts"],"names":[],"mappings":"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","sourcesContent":["import { isWhitespaceChar } from \"../../../utils.ts\";\nimport { SelectList } from \"../../select-list.ts\";\nimport {\n ATTACHMENT_AUTOCOMPLETE_DEBOUNCE_MS,\n DEFAULT_AUTOCOMPLETE_TRIGGER_CHARACTERS,\n SLASH_COMMAND_SELECT_LIST_LAYOUT,\n} from \"../constants.ts\";\nimport type { Editor } from \"../editor.ts\";\nimport { buildDebouncePattern, buildTriggerPattern } from \"../trigger-patterns.ts\";\n\nexport function do_getBestAutocompleteMatchIndex(\n _self: Editor,\n items: Array<{ value: string; label: string }>,\n prefix: string,\n): number {\n if (!prefix) return -1;\n\n let firstPrefixIndex = -1;\n\n for (let i = 0; i < items.length; i++) {\n const value = items[i]!.value;\n if (value === prefix) {\n return i; // Exact match always wins\n }\n if (firstPrefixIndex === -1 && value.startsWith(prefix)) {\n firstPrefixIndex = i;\n }\n }\n\n return firstPrefixIndex;\n}\n\nexport function do_createAutocompleteList(\n self: Editor,\n prefix: string,\n items: Array<{ value: string; label: string; description?: string }>,\n): SelectList {\n const layout = prefix.startsWith(\"/\") ? SLASH_COMMAND_SELECT_LIST_LAYOUT : undefined;\n return new SelectList(items, self.autocompleteMaxVisible, self.theme.selectList, layout);\n}\n\nexport function do_tryTriggerAutocomplete(self: Editor, explicitTab: boolean = false): void {\n self.requestAutocomplete({ force: false, explicitTab });\n}\n\nexport function do_handleTabCompletion(self: Editor): void {\n if (!self.autocompleteProvider) return;\n\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n const beforeCursor = currentLine.slice(0, self.state.cursorCol);\n\n if (self.isInSlashCommandContext(beforeCursor) && !beforeCursor.trimStart().includes(\" \")) {\n self.handleSlashCommandCompletion();\n } else {\n self.forceFileAutocomplete(true);\n }\n}\n\nexport function do_handleSlashCommandCompletion(self: Editor): void {\n self.requestAutocomplete({ force: false, explicitTab: true });\n}\n\nexport function do_forceFileAutocomplete(self: Editor, explicitTab: boolean = false): void {\n self.requestAutocomplete({ force: true, explicitTab });\n}\n\nexport function do_requestAutocomplete(self: Editor, options: { force: boolean; explicitTab: boolean }): void {\n if (!self.autocompleteProvider) return;\n\n if (options.force) {\n const shouldTrigger =\n !self.autocompleteProvider.shouldTriggerFileCompletion ||\n self.autocompleteProvider.shouldTriggerFileCompletion(\n self.state.lines,\n self.state.cursorLine,\n self.state.cursorCol,\n );\n if (!shouldTrigger) {\n return;\n }\n }\n\n self.cancelAutocompleteRequest();\n const startToken = ++self.autocompleteStartToken;\n\n const debounceMs = self.getAutocompleteDebounceMs(options);\n if (debounceMs > 0) {\n self.autocompleteDebounceTimer = setTimeout(() => {\n self.autocompleteDebounceTimer = undefined;\n void self.startAutocompleteRequest(startToken, options);\n }, debounceMs);\n return;\n }\n\n void self.startAutocompleteRequest(startToken, options);\n}\n\nexport async function do_startAutocompleteRequest(\n self: Editor,\n startToken: number,\n options: { force: boolean; explicitTab: boolean },\n): Promise<void> {\n const previousTask = self.autocompleteRequestTask;\n self.autocompleteRequestTask = (async () => {\n await previousTask;\n if (startToken !== self.autocompleteStartToken || !self.autocompleteProvider) {\n return;\n }\n\n const controller = new AbortController();\n self.autocompleteAbort = controller;\n const requestId = ++self.autocompleteRequestId;\n const snapshotText = self.getText();\n const snapshotLine = self.state.cursorLine;\n const snapshotCol = self.state.cursorCol;\n\n await self.runAutocompleteRequest(requestId, controller, snapshotText, snapshotLine, snapshotCol, options);\n })();\n await self.autocompleteRequestTask;\n}\n\nexport function do_setAutocompleteTriggerCharacters(self: Editor, triggerCharacters: string[]): void {\n const next = [...DEFAULT_AUTOCOMPLETE_TRIGGER_CHARACTERS];\n for (const character of triggerCharacters) {\n if (character.length !== 1 || character === \"/\" || isWhitespaceChar(character) || next.includes(character)) {\n continue;\n }\n next.push(character);\n }\n self.autocompleteTriggerCharacters = next;\n self.autocompleteTriggerPattern = buildTriggerPattern(next);\n self.autocompleteDebouncePattern = buildDebouncePattern(next);\n}\n\nexport function do_getAutocompleteDebounceMs(self: Editor, options: { force: boolean; explicitTab: boolean }): number {\n if (options.explicitTab || options.force) {\n return 0;\n }\n\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n const textBeforeCursor = currentLine.slice(0, self.state.cursorCol);\n return self.autocompleteDebouncePattern.test(textBeforeCursor) ? ATTACHMENT_AUTOCOMPLETE_DEBOUNCE_MS : 0;\n}\n"]}
@@ -0,0 +1,14 @@
1
+ import type { AutocompleteSuggestions } from "../../../autocomplete.ts";
2
+ import type { Editor } from "../editor.ts";
3
+ export declare function do_runAutocompleteRequest(self: Editor, requestId: number, controller: AbortController, snapshotText: string, snapshotLine: number, snapshotCol: number, options: {
4
+ force: boolean;
5
+ explicitTab: boolean;
6
+ }): Promise<void>;
7
+ export declare function do_isAutocompleteRequestCurrent(self: Editor, requestId: number, controller: AbortController, snapshotText: string, snapshotLine: number, snapshotCol: number): boolean;
8
+ export declare function do_applyAutocompleteSuggestions(self: Editor, suggestions: AutocompleteSuggestions, state: "regular" | "force"): void;
9
+ export declare function do_cancelAutocompleteRequest(self: Editor): void;
10
+ export declare function do_clearAutocompleteUi(self: Editor): void;
11
+ export declare function do_cancelAutocomplete(self: Editor): void;
12
+ export declare function do_isShowingAutocomplete(self: Editor): boolean;
13
+ export declare function do_updateAutocomplete(self: Editor): void;
14
+ //# sourceMappingURL=autocomplete-request.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autocomplete-request.d.ts","sourceRoot":"","sources":["../../../../src/components/editor/editor-methods/autocomplete-request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,eAAe,EAC3B,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,GAChD,OAAO,CAAC,IAAI,CAAC,CA2Cf;AAED,wBAAgB,+BAA+B,CAC7C,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,eAAe,EAC3B,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,GAClB,OAAO,CAQT;AAED,wBAAgB,+BAA+B,CAC7C,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,uBAAuB,EACpC,KAAK,EAAE,SAAS,GAAG,OAAO,GACzB,IAAI,CAUN;AAED,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAQ/D;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAIzD;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAGxD;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAGxD","sourcesContent":["import type { AutocompleteSuggestions } from \"../../../autocomplete.ts\";\nimport type { Editor } from \"../editor.ts\";\n\nexport async function do_runAutocompleteRequest(\n self: Editor,\n requestId: number,\n controller: AbortController,\n snapshotText: string,\n snapshotLine: number,\n snapshotCol: number,\n options: { force: boolean; explicitTab: boolean },\n): Promise<void> {\n if (!self.autocompleteProvider) return;\n\n const suggestions = await self.autocompleteProvider.getSuggestions(\n self.state.lines,\n self.state.cursorLine,\n self.state.cursorCol,\n { signal: controller.signal, force: options.force },\n );\n\n if (!self.isAutocompleteRequestCurrent(requestId, controller, snapshotText, snapshotLine, snapshotCol)) {\n return;\n }\n\n self.autocompleteAbort = undefined;\n\n if (!suggestions || !Array.isArray(suggestions.items) || suggestions.items.length === 0) {\n self.cancelAutocomplete();\n self.tui.requestRender();\n return;\n }\n\n if (options.force && options.explicitTab && suggestions.items.length === 1) {\n const item = suggestions.items[0]!;\n self.pushUndoSnapshot();\n self.lastAction = null;\n const result = self.autocompleteProvider.applyCompletion(\n self.state.lines,\n self.state.cursorLine,\n self.state.cursorCol,\n item,\n suggestions.prefix,\n );\n self.state.lines = result.lines;\n self.state.cursorLine = result.cursorLine;\n self.setCursorCol(result.cursorCol);\n if (self.onChange) self.onChange(self.getText());\n self.tui.requestRender();\n return;\n }\n\n self.applyAutocompleteSuggestions(suggestions, options.force ? \"force\" : \"regular\");\n self.tui.requestRender();\n}\n\nexport function do_isAutocompleteRequestCurrent(\n self: Editor,\n requestId: number,\n controller: AbortController,\n snapshotText: string,\n snapshotLine: number,\n snapshotCol: number,\n): boolean {\n return (\n !controller.signal.aborted &&\n requestId === self.autocompleteRequestId &&\n self.getText() === snapshotText &&\n self.state.cursorLine === snapshotLine &&\n self.state.cursorCol === snapshotCol\n );\n}\n\nexport function do_applyAutocompleteSuggestions(\n self: Editor,\n suggestions: AutocompleteSuggestions,\n state: \"regular\" | \"force\",\n): void {\n self.autocompletePrefix = suggestions.prefix;\n self.autocompleteList = self.createAutocompleteList(suggestions.prefix, suggestions.items);\n\n const bestMatchIndex = self.getBestAutocompleteMatchIndex(suggestions.items, suggestions.prefix);\n if (bestMatchIndex >= 0) {\n self.autocompleteList.setSelectedIndex(bestMatchIndex);\n }\n\n self.autocompleteState = state;\n}\n\nexport function do_cancelAutocompleteRequest(self: Editor): void {\n self.autocompleteStartToken += 1;\n if (self.autocompleteDebounceTimer) {\n clearTimeout(self.autocompleteDebounceTimer);\n self.autocompleteDebounceTimer = undefined;\n }\n self.autocompleteAbort?.abort();\n self.autocompleteAbort = undefined;\n}\n\nexport function do_clearAutocompleteUi(self: Editor): void {\n self.autocompleteState = null;\n self.autocompleteList = undefined;\n self.autocompletePrefix = \"\";\n}\n\nexport function do_cancelAutocomplete(self: Editor): void {\n self.cancelAutocompleteRequest();\n self.clearAutocompleteUi();\n}\n\nexport function do_isShowingAutocomplete(self: Editor): boolean {\n return self.autocompleteState !== null;\n}\n\nexport function do_updateAutocomplete(self: Editor): void {\n if (!self.autocompleteState || !self.autocompleteProvider) return;\n self.requestAutocomplete({ force: self.autocompleteState === \"force\", explicitTab: false });\n}\n"]}
@@ -0,0 +1,72 @@
1
+ export async function do_runAutocompleteRequest(self, requestId, controller, snapshotText, snapshotLine, snapshotCol, options) {
2
+ if (!self.autocompleteProvider)
3
+ return;
4
+ const suggestions = await self.autocompleteProvider.getSuggestions(self.state.lines, self.state.cursorLine, self.state.cursorCol, { signal: controller.signal, force: options.force });
5
+ if (!self.isAutocompleteRequestCurrent(requestId, controller, snapshotText, snapshotLine, snapshotCol)) {
6
+ return;
7
+ }
8
+ self.autocompleteAbort = undefined;
9
+ if (!suggestions || !Array.isArray(suggestions.items) || suggestions.items.length === 0) {
10
+ self.cancelAutocomplete();
11
+ self.tui.requestRender();
12
+ return;
13
+ }
14
+ if (options.force && options.explicitTab && suggestions.items.length === 1) {
15
+ const item = suggestions.items[0];
16
+ self.pushUndoSnapshot();
17
+ self.lastAction = null;
18
+ const result = self.autocompleteProvider.applyCompletion(self.state.lines, self.state.cursorLine, self.state.cursorCol, item, suggestions.prefix);
19
+ self.state.lines = result.lines;
20
+ self.state.cursorLine = result.cursorLine;
21
+ self.setCursorCol(result.cursorCol);
22
+ if (self.onChange)
23
+ self.onChange(self.getText());
24
+ self.tui.requestRender();
25
+ return;
26
+ }
27
+ self.applyAutocompleteSuggestions(suggestions, options.force ? "force" : "regular");
28
+ self.tui.requestRender();
29
+ }
30
+ export function do_isAutocompleteRequestCurrent(self, requestId, controller, snapshotText, snapshotLine, snapshotCol) {
31
+ return (!controller.signal.aborted &&
32
+ requestId === self.autocompleteRequestId &&
33
+ self.getText() === snapshotText &&
34
+ self.state.cursorLine === snapshotLine &&
35
+ self.state.cursorCol === snapshotCol);
36
+ }
37
+ export function do_applyAutocompleteSuggestions(self, suggestions, state) {
38
+ self.autocompletePrefix = suggestions.prefix;
39
+ self.autocompleteList = self.createAutocompleteList(suggestions.prefix, suggestions.items);
40
+ const bestMatchIndex = self.getBestAutocompleteMatchIndex(suggestions.items, suggestions.prefix);
41
+ if (bestMatchIndex >= 0) {
42
+ self.autocompleteList.setSelectedIndex(bestMatchIndex);
43
+ }
44
+ self.autocompleteState = state;
45
+ }
46
+ export function do_cancelAutocompleteRequest(self) {
47
+ self.autocompleteStartToken += 1;
48
+ if (self.autocompleteDebounceTimer) {
49
+ clearTimeout(self.autocompleteDebounceTimer);
50
+ self.autocompleteDebounceTimer = undefined;
51
+ }
52
+ self.autocompleteAbort?.abort();
53
+ self.autocompleteAbort = undefined;
54
+ }
55
+ export function do_clearAutocompleteUi(self) {
56
+ self.autocompleteState = null;
57
+ self.autocompleteList = undefined;
58
+ self.autocompletePrefix = "";
59
+ }
60
+ export function do_cancelAutocomplete(self) {
61
+ self.cancelAutocompleteRequest();
62
+ self.clearAutocompleteUi();
63
+ }
64
+ export function do_isShowingAutocomplete(self) {
65
+ return self.autocompleteState !== null;
66
+ }
67
+ export function do_updateAutocomplete(self) {
68
+ if (!self.autocompleteState || !self.autocompleteProvider)
69
+ return;
70
+ self.requestAutocomplete({ force: self.autocompleteState === "force", explicitTab: false });
71
+ }
72
+ //# sourceMappingURL=autocomplete-request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autocomplete-request.js","sourceRoot":"","sources":["../../../../src/components/editor/editor-methods/autocomplete-request.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AutocompleteSuggestions } from \"../../../autocomplete.ts\";\nimport type { Editor } from \"../editor.ts\";\n\nexport async function do_runAutocompleteRequest(\n self: Editor,\n requestId: number,\n controller: AbortController,\n snapshotText: string,\n snapshotLine: number,\n snapshotCol: number,\n options: { force: boolean; explicitTab: boolean },\n): Promise<void> {\n if (!self.autocompleteProvider) return;\n\n const suggestions = await self.autocompleteProvider.getSuggestions(\n self.state.lines,\n self.state.cursorLine,\n self.state.cursorCol,\n { signal: controller.signal, force: options.force },\n );\n\n if (!self.isAutocompleteRequestCurrent(requestId, controller, snapshotText, snapshotLine, snapshotCol)) {\n return;\n }\n\n self.autocompleteAbort = undefined;\n\n if (!suggestions || !Array.isArray(suggestions.items) || suggestions.items.length === 0) {\n self.cancelAutocomplete();\n self.tui.requestRender();\n return;\n }\n\n if (options.force && options.explicitTab && suggestions.items.length === 1) {\n const item = suggestions.items[0]!;\n self.pushUndoSnapshot();\n self.lastAction = null;\n const result = self.autocompleteProvider.applyCompletion(\n self.state.lines,\n self.state.cursorLine,\n self.state.cursorCol,\n item,\n suggestions.prefix,\n );\n self.state.lines = result.lines;\n self.state.cursorLine = result.cursorLine;\n self.setCursorCol(result.cursorCol);\n if (self.onChange) self.onChange(self.getText());\n self.tui.requestRender();\n return;\n }\n\n self.applyAutocompleteSuggestions(suggestions, options.force ? \"force\" : \"regular\");\n self.tui.requestRender();\n}\n\nexport function do_isAutocompleteRequestCurrent(\n self: Editor,\n requestId: number,\n controller: AbortController,\n snapshotText: string,\n snapshotLine: number,\n snapshotCol: number,\n): boolean {\n return (\n !controller.signal.aborted &&\n requestId === self.autocompleteRequestId &&\n self.getText() === snapshotText &&\n self.state.cursorLine === snapshotLine &&\n self.state.cursorCol === snapshotCol\n );\n}\n\nexport function do_applyAutocompleteSuggestions(\n self: Editor,\n suggestions: AutocompleteSuggestions,\n state: \"regular\" | \"force\",\n): void {\n self.autocompletePrefix = suggestions.prefix;\n self.autocompleteList = self.createAutocompleteList(suggestions.prefix, suggestions.items);\n\n const bestMatchIndex = self.getBestAutocompleteMatchIndex(suggestions.items, suggestions.prefix);\n if (bestMatchIndex >= 0) {\n self.autocompleteList.setSelectedIndex(bestMatchIndex);\n }\n\n self.autocompleteState = state;\n}\n\nexport function do_cancelAutocompleteRequest(self: Editor): void {\n self.autocompleteStartToken += 1;\n if (self.autocompleteDebounceTimer) {\n clearTimeout(self.autocompleteDebounceTimer);\n self.autocompleteDebounceTimer = undefined;\n }\n self.autocompleteAbort?.abort();\n self.autocompleteAbort = undefined;\n}\n\nexport function do_clearAutocompleteUi(self: Editor): void {\n self.autocompleteState = null;\n self.autocompleteList = undefined;\n self.autocompletePrefix = \"\";\n}\n\nexport function do_cancelAutocomplete(self: Editor): void {\n self.cancelAutocompleteRequest();\n self.clearAutocompleteUi();\n}\n\nexport function do_isShowingAutocomplete(self: Editor): boolean {\n return self.autocompleteState !== null;\n}\n\nexport function do_updateAutocomplete(self: Editor): void {\n if (!self.autocompleteState || !self.autocompleteProvider) return;\n self.requestAutocomplete({ force: self.autocompleteState === \"force\", explicitTab: false });\n}\n"]}
@@ -0,0 +1,9 @@
1
+ import type { Editor } from "../editor.ts";
2
+ export declare function do_handleBackspace(self: Editor): void;
3
+ export declare function do_setCursorCol(self: Editor, col: number): void;
4
+ export declare function do_moveToVisualLine(self: Editor, visualLines: Array<{
5
+ logicalLine: number;
6
+ startCol: number;
7
+ length: number;
8
+ }>, currentVisualLine: number, targetVisualLine: number): void;
9
+ //# sourceMappingURL=backspace-cursor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backspace-cursor.d.ts","sourceRoot":"","sources":["../../../../src/components/editor/editor-methods/backspace-cursor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAuDrD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAI/D;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,KAAK,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,EAC7E,iBAAiB,EAAE,MAAM,EACzB,gBAAgB,EAAE,MAAM,GACvB,IAAI,CA4EN","sourcesContent":["import type { Editor } from \"../editor.ts\";\n\nexport function do_handleBackspace(self: Editor): void {\n self.exitHistoryBrowsing();\n self.lastAction = null;\n\n if (self.state.cursorCol > 0) {\n self.pushUndoSnapshot();\n\n // Delete grapheme before cursor (handles emojis, combining characters, etc.)\n const line = self.state.lines[self.state.cursorLine] || \"\";\n const beforeCursor = line.slice(0, self.state.cursorCol);\n\n // Find the last grapheme in the text before cursor\n const graphemes = [...self.segment(beforeCursor, \"grapheme\")];\n const lastGrapheme = graphemes[graphemes.length - 1];\n const graphemeLength = lastGrapheme ? lastGrapheme.segment.length : 1;\n\n const before = line.slice(0, self.state.cursorCol - graphemeLength);\n const after = line.slice(self.state.cursorCol);\n\n self.state.lines[self.state.cursorLine] = before + after;\n self.setCursorCol(self.state.cursorCol - graphemeLength);\n } else if (self.state.cursorLine > 0) {\n self.pushUndoSnapshot();\n\n // Merge with previous line\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n const previousLine = self.state.lines[self.state.cursorLine - 1] || \"\";\n\n self.state.lines[self.state.cursorLine - 1] = previousLine + currentLine;\n self.state.lines.splice(self.state.cursorLine, 1);\n\n self.state.cursorLine--;\n self.setCursorCol(previousLine.length);\n }\n\n if (self.onChange) {\n self.onChange(self.getText());\n }\n\n // Update or re-trigger autocomplete after backspace\n if (self.autocompleteState) {\n self.updateAutocomplete();\n } else {\n // If autocomplete was cancelled (no matches), re-trigger if we're in a completable context\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n const textBeforeCursor = currentLine.slice(0, self.state.cursorCol);\n // Slash command context\n if (self.isInSlashCommandContext(textBeforeCursor)) {\n self.tryTriggerAutocomplete();\n }\n // Symbol-based completion context like @, #, or provider triggers\n else if (self.autocompleteTriggerPattern.test(textBeforeCursor)) {\n self.tryTriggerAutocomplete();\n }\n }\n}\n\nexport function do_setCursorCol(self: Editor, col: number): void {\n self.state.cursorCol = col;\n self.preferredVisualCol = null;\n self.snappedFromCursorCol = null;\n}\n\nexport function do_moveToVisualLine(\n self: Editor,\n visualLines: Array<{ logicalLine: number; startCol: number; length: number }>,\n currentVisualLine: number,\n targetVisualLine: number,\n): void {\n const currentVL = visualLines[currentVisualLine];\n const targetVL = visualLines[targetVisualLine];\n if (!(currentVL && targetVL)) return;\n\n // When the cursor was snapped to a segment start, resolve the pre-snap\n // position against the VL it belongs to. This gives the correct visual\n // column even after a resize reshuffles VLs.\n let currentVisualCol: number;\n if (self.snappedFromCursorCol !== null) {\n const vlIndex = self.findVisualLineAt(visualLines, currentVL.logicalLine, self.snappedFromCursorCol);\n currentVisualCol = self.snappedFromCursorCol - visualLines[vlIndex].startCol;\n } else {\n currentVisualCol = self.state.cursorCol - currentVL.startCol;\n }\n\n // For non-last segments, clamp to length-1 to stay within the segment\n const isLastSourceSegment =\n currentVisualLine === visualLines.length - 1 ||\n visualLines[currentVisualLine + 1]?.logicalLine !== currentVL.logicalLine;\n const sourceMaxVisualCol = isLastSourceSegment ? currentVL.length : Math.max(0, currentVL.length - 1);\n\n const isLastTargetSegment =\n targetVisualLine === visualLines.length - 1 ||\n visualLines[targetVisualLine + 1]?.logicalLine !== targetVL.logicalLine;\n const targetMaxVisualCol = isLastTargetSegment ? targetVL.length : Math.max(0, targetVL.length - 1);\n\n const moveToVisualCol = self.computeVerticalMoveColumn(currentVisualCol, sourceMaxVisualCol, targetMaxVisualCol);\n\n // Set cursor position\n self.state.cursorLine = targetVL.logicalLine;\n const targetCol = targetVL.startCol + moveToVisualCol;\n const logicalLine = self.state.lines[targetVL.logicalLine] || \"\";\n self.state.cursorCol = Math.min(targetCol, logicalLine.length);\n\n // Snap cursor to atomic segment boundary (e.g. paste markers)\n // so the cursor never lands in the middle of a multi-grapheme unit.\n // Single-grapheme segments don't need snapping.\n const segments = [...self.segment(logicalLine, \"grapheme\")];\n for (const seg of segments) {\n if (seg.index > self.state.cursorCol) break;\n if (seg.segment.length <= 1) continue;\n if (self.state.cursorCol < seg.index + seg.segment.length) {\n const isContinuation = seg.index < targetVL.startCol;\n const isMovingDown = targetVisualLine > currentVisualLine;\n\n if (isContinuation && isMovingDown) {\n // The segment started on a previous visual line, and we\n // already visited it on the way down. Skip all remaining\n // continuation VLs and land on the first VL past it.\n const segEnd = seg.index + seg.segment.length;\n let next = targetVisualLine + 1;\n while (\n next < visualLines.length &&\n visualLines[next].logicalLine === targetVL.logicalLine &&\n visualLines[next].startCol < segEnd\n ) {\n next++;\n }\n if (next < visualLines.length) {\n self.moveToVisualLine(visualLines, currentVisualLine, next);\n return;\n }\n }\n\n // Snap to the start of the segment so it gets highlighted.\n // Store the pre-snap position so the next vertical move can\n // resolve it to the correct visual column.\n self.snappedFromCursorCol = self.state.cursorCol;\n self.state.cursorCol = seg.index;\n return;\n }\n }\n\n // No snap occurred – we moved out of the atomic segment.\n self.snappedFromCursorCol = null;\n}\n"]}
@@ -0,0 +1,122 @@
1
+ export function do_handleBackspace(self) {
2
+ self.exitHistoryBrowsing();
3
+ self.lastAction = null;
4
+ if (self.state.cursorCol > 0) {
5
+ self.pushUndoSnapshot();
6
+ // Delete grapheme before cursor (handles emojis, combining characters, etc.)
7
+ const line = self.state.lines[self.state.cursorLine] || "";
8
+ const beforeCursor = line.slice(0, self.state.cursorCol);
9
+ // Find the last grapheme in the text before cursor
10
+ const graphemes = [...self.segment(beforeCursor, "grapheme")];
11
+ const lastGrapheme = graphemes[graphemes.length - 1];
12
+ const graphemeLength = lastGrapheme ? lastGrapheme.segment.length : 1;
13
+ const before = line.slice(0, self.state.cursorCol - graphemeLength);
14
+ const after = line.slice(self.state.cursorCol);
15
+ self.state.lines[self.state.cursorLine] = before + after;
16
+ self.setCursorCol(self.state.cursorCol - graphemeLength);
17
+ }
18
+ else if (self.state.cursorLine > 0) {
19
+ self.pushUndoSnapshot();
20
+ // Merge with previous line
21
+ const currentLine = self.state.lines[self.state.cursorLine] || "";
22
+ const previousLine = self.state.lines[self.state.cursorLine - 1] || "";
23
+ self.state.lines[self.state.cursorLine - 1] = previousLine + currentLine;
24
+ self.state.lines.splice(self.state.cursorLine, 1);
25
+ self.state.cursorLine--;
26
+ self.setCursorCol(previousLine.length);
27
+ }
28
+ if (self.onChange) {
29
+ self.onChange(self.getText());
30
+ }
31
+ // Update or re-trigger autocomplete after backspace
32
+ if (self.autocompleteState) {
33
+ self.updateAutocomplete();
34
+ }
35
+ else {
36
+ // If autocomplete was cancelled (no matches), re-trigger if we're in a completable context
37
+ const currentLine = self.state.lines[self.state.cursorLine] || "";
38
+ const textBeforeCursor = currentLine.slice(0, self.state.cursorCol);
39
+ // Slash command context
40
+ if (self.isInSlashCommandContext(textBeforeCursor)) {
41
+ self.tryTriggerAutocomplete();
42
+ }
43
+ // Symbol-based completion context like @, #, or provider triggers
44
+ else if (self.autocompleteTriggerPattern.test(textBeforeCursor)) {
45
+ self.tryTriggerAutocomplete();
46
+ }
47
+ }
48
+ }
49
+ export function do_setCursorCol(self, col) {
50
+ self.state.cursorCol = col;
51
+ self.preferredVisualCol = null;
52
+ self.snappedFromCursorCol = null;
53
+ }
54
+ export function do_moveToVisualLine(self, visualLines, currentVisualLine, targetVisualLine) {
55
+ const currentVL = visualLines[currentVisualLine];
56
+ const targetVL = visualLines[targetVisualLine];
57
+ if (!(currentVL && targetVL))
58
+ return;
59
+ // When the cursor was snapped to a segment start, resolve the pre-snap
60
+ // position against the VL it belongs to. This gives the correct visual
61
+ // column even after a resize reshuffles VLs.
62
+ let currentVisualCol;
63
+ if (self.snappedFromCursorCol !== null) {
64
+ const vlIndex = self.findVisualLineAt(visualLines, currentVL.logicalLine, self.snappedFromCursorCol);
65
+ currentVisualCol = self.snappedFromCursorCol - visualLines[vlIndex].startCol;
66
+ }
67
+ else {
68
+ currentVisualCol = self.state.cursorCol - currentVL.startCol;
69
+ }
70
+ // For non-last segments, clamp to length-1 to stay within the segment
71
+ const isLastSourceSegment = currentVisualLine === visualLines.length - 1 ||
72
+ visualLines[currentVisualLine + 1]?.logicalLine !== currentVL.logicalLine;
73
+ const sourceMaxVisualCol = isLastSourceSegment ? currentVL.length : Math.max(0, currentVL.length - 1);
74
+ const isLastTargetSegment = targetVisualLine === visualLines.length - 1 ||
75
+ visualLines[targetVisualLine + 1]?.logicalLine !== targetVL.logicalLine;
76
+ const targetMaxVisualCol = isLastTargetSegment ? targetVL.length : Math.max(0, targetVL.length - 1);
77
+ const moveToVisualCol = self.computeVerticalMoveColumn(currentVisualCol, sourceMaxVisualCol, targetMaxVisualCol);
78
+ // Set cursor position
79
+ self.state.cursorLine = targetVL.logicalLine;
80
+ const targetCol = targetVL.startCol + moveToVisualCol;
81
+ const logicalLine = self.state.lines[targetVL.logicalLine] || "";
82
+ self.state.cursorCol = Math.min(targetCol, logicalLine.length);
83
+ // Snap cursor to atomic segment boundary (e.g. paste markers)
84
+ // so the cursor never lands in the middle of a multi-grapheme unit.
85
+ // Single-grapheme segments don't need snapping.
86
+ const segments = [...self.segment(logicalLine, "grapheme")];
87
+ for (const seg of segments) {
88
+ if (seg.index > self.state.cursorCol)
89
+ break;
90
+ if (seg.segment.length <= 1)
91
+ continue;
92
+ if (self.state.cursorCol < seg.index + seg.segment.length) {
93
+ const isContinuation = seg.index < targetVL.startCol;
94
+ const isMovingDown = targetVisualLine > currentVisualLine;
95
+ if (isContinuation && isMovingDown) {
96
+ // The segment started on a previous visual line, and we
97
+ // already visited it on the way down. Skip all remaining
98
+ // continuation VLs and land on the first VL past it.
99
+ const segEnd = seg.index + seg.segment.length;
100
+ let next = targetVisualLine + 1;
101
+ while (next < visualLines.length &&
102
+ visualLines[next].logicalLine === targetVL.logicalLine &&
103
+ visualLines[next].startCol < segEnd) {
104
+ next++;
105
+ }
106
+ if (next < visualLines.length) {
107
+ self.moveToVisualLine(visualLines, currentVisualLine, next);
108
+ return;
109
+ }
110
+ }
111
+ // Snap to the start of the segment so it gets highlighted.
112
+ // Store the pre-snap position so the next vertical move can
113
+ // resolve it to the correct visual column.
114
+ self.snappedFromCursorCol = self.state.cursorCol;
115
+ self.state.cursorCol = seg.index;
116
+ return;
117
+ }
118
+ }
119
+ // No snap occurred – we moved out of the atomic segment.
120
+ self.snappedFromCursorCol = null;
121
+ }
122
+ //# sourceMappingURL=backspace-cursor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backspace-cursor.js","sourceRoot":"","sources":["../../../../src/components/editor/editor-methods/backspace-cursor.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Editor } from \"../editor.ts\";\n\nexport function do_handleBackspace(self: Editor): void {\n self.exitHistoryBrowsing();\n self.lastAction = null;\n\n if (self.state.cursorCol > 0) {\n self.pushUndoSnapshot();\n\n // Delete grapheme before cursor (handles emojis, combining characters, etc.)\n const line = self.state.lines[self.state.cursorLine] || \"\";\n const beforeCursor = line.slice(0, self.state.cursorCol);\n\n // Find the last grapheme in the text before cursor\n const graphemes = [...self.segment(beforeCursor, \"grapheme\")];\n const lastGrapheme = graphemes[graphemes.length - 1];\n const graphemeLength = lastGrapheme ? lastGrapheme.segment.length : 1;\n\n const before = line.slice(0, self.state.cursorCol - graphemeLength);\n const after = line.slice(self.state.cursorCol);\n\n self.state.lines[self.state.cursorLine] = before + after;\n self.setCursorCol(self.state.cursorCol - graphemeLength);\n } else if (self.state.cursorLine > 0) {\n self.pushUndoSnapshot();\n\n // Merge with previous line\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n const previousLine = self.state.lines[self.state.cursorLine - 1] || \"\";\n\n self.state.lines[self.state.cursorLine - 1] = previousLine + currentLine;\n self.state.lines.splice(self.state.cursorLine, 1);\n\n self.state.cursorLine--;\n self.setCursorCol(previousLine.length);\n }\n\n if (self.onChange) {\n self.onChange(self.getText());\n }\n\n // Update or re-trigger autocomplete after backspace\n if (self.autocompleteState) {\n self.updateAutocomplete();\n } else {\n // If autocomplete was cancelled (no matches), re-trigger if we're in a completable context\n const currentLine = self.state.lines[self.state.cursorLine] || \"\";\n const textBeforeCursor = currentLine.slice(0, self.state.cursorCol);\n // Slash command context\n if (self.isInSlashCommandContext(textBeforeCursor)) {\n self.tryTriggerAutocomplete();\n }\n // Symbol-based completion context like @, #, or provider triggers\n else if (self.autocompleteTriggerPattern.test(textBeforeCursor)) {\n self.tryTriggerAutocomplete();\n }\n }\n}\n\nexport function do_setCursorCol(self: Editor, col: number): void {\n self.state.cursorCol = col;\n self.preferredVisualCol = null;\n self.snappedFromCursorCol = null;\n}\n\nexport function do_moveToVisualLine(\n self: Editor,\n visualLines: Array<{ logicalLine: number; startCol: number; length: number }>,\n currentVisualLine: number,\n targetVisualLine: number,\n): void {\n const currentVL = visualLines[currentVisualLine];\n const targetVL = visualLines[targetVisualLine];\n if (!(currentVL && targetVL)) return;\n\n // When the cursor was snapped to a segment start, resolve the pre-snap\n // position against the VL it belongs to. This gives the correct visual\n // column even after a resize reshuffles VLs.\n let currentVisualCol: number;\n if (self.snappedFromCursorCol !== null) {\n const vlIndex = self.findVisualLineAt(visualLines, currentVL.logicalLine, self.snappedFromCursorCol);\n currentVisualCol = self.snappedFromCursorCol - visualLines[vlIndex].startCol;\n } else {\n currentVisualCol = self.state.cursorCol - currentVL.startCol;\n }\n\n // For non-last segments, clamp to length-1 to stay within the segment\n const isLastSourceSegment =\n currentVisualLine === visualLines.length - 1 ||\n visualLines[currentVisualLine + 1]?.logicalLine !== currentVL.logicalLine;\n const sourceMaxVisualCol = isLastSourceSegment ? currentVL.length : Math.max(0, currentVL.length - 1);\n\n const isLastTargetSegment =\n targetVisualLine === visualLines.length - 1 ||\n visualLines[targetVisualLine + 1]?.logicalLine !== targetVL.logicalLine;\n const targetMaxVisualCol = isLastTargetSegment ? targetVL.length : Math.max(0, targetVL.length - 1);\n\n const moveToVisualCol = self.computeVerticalMoveColumn(currentVisualCol, sourceMaxVisualCol, targetMaxVisualCol);\n\n // Set cursor position\n self.state.cursorLine = targetVL.logicalLine;\n const targetCol = targetVL.startCol + moveToVisualCol;\n const logicalLine = self.state.lines[targetVL.logicalLine] || \"\";\n self.state.cursorCol = Math.min(targetCol, logicalLine.length);\n\n // Snap cursor to atomic segment boundary (e.g. paste markers)\n // so the cursor never lands in the middle of a multi-grapheme unit.\n // Single-grapheme segments don't need snapping.\n const segments = [...self.segment(logicalLine, \"grapheme\")];\n for (const seg of segments) {\n if (seg.index > self.state.cursorCol) break;\n if (seg.segment.length <= 1) continue;\n if (self.state.cursorCol < seg.index + seg.segment.length) {\n const isContinuation = seg.index < targetVL.startCol;\n const isMovingDown = targetVisualLine > currentVisualLine;\n\n if (isContinuation && isMovingDown) {\n // The segment started on a previous visual line, and we\n // already visited it on the way down. Skip all remaining\n // continuation VLs and land on the first VL past it.\n const segEnd = seg.index + seg.segment.length;\n let next = targetVisualLine + 1;\n while (\n next < visualLines.length &&\n visualLines[next].logicalLine === targetVL.logicalLine &&\n visualLines[next].startCol < segEnd\n ) {\n next++;\n }\n if (next < visualLines.length) {\n self.moveToVisualLine(visualLines, currentVisualLine, next);\n return;\n }\n }\n\n // Snap to the start of the segment so it gets highlighted.\n // Store the pre-snap position so the next vertical move can\n // resolve it to the correct visual column.\n self.snappedFromCursorCol = self.state.cursorCol;\n self.state.cursorCol = seg.index;\n return;\n }\n }\n\n // No snap occurred – we moved out of the atomic segment.\n self.snappedFromCursorCol = null;\n}\n"]}
@@ -0,0 +1,17 @@
1
+ import type { AutocompleteProvider } from "../../../autocomplete.ts";
2
+ import type { Editor } from "../editor.ts";
3
+ export declare function do_validPasteIds(self: Editor): Set<number>;
4
+ export declare function do_segment(self: Editor, text: string, mode: "word" | "grapheme"): Iterable<Intl.SegmentData>;
5
+ export declare function do_getPaddingX(self: Editor): number;
6
+ export declare function do_setPaddingX(self: Editor, padding: number): void;
7
+ export declare function do_getAutocompleteMaxVisible(self: Editor): number;
8
+ export declare function do_setAutocompleteMaxVisible(self: Editor, maxVisible: number): void;
9
+ export declare function do_setAutocompleteProvider(self: Editor, provider: AutocompleteProvider): void;
10
+ export declare function do_addToHistory(self: Editor, text: string): void;
11
+ export declare function do_isOnFirstVisualLine(self: Editor): boolean;
12
+ export declare function do_isOnLastVisualLine(self: Editor): boolean;
13
+ export declare function do_navigateHistory(self: Editor, direction: 1 | -1): void;
14
+ export declare function do_exitHistoryBrowsing(self: Editor): void;
15
+ export declare function do_setTextInternal(self: Editor, text: string, cursorPlacement?: "start" | "end"): void;
16
+ export declare function do_invalidate(_self: Editor): void;
17
+ //# sourceMappingURL=configuration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configuration.d.ts","sourceRoot":"","sources":["../../../../src/components/editor/editor-methods/configuration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAErE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAG3C,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAE1D;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAE5G;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAMlE;AAED,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjE;AAED,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAMnF;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAI7F;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAUhE;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAI5D;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAI3D;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CA8BxE;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAGzD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,eAAe,GAAE,OAAO,GAAG,KAAa,GAAG,IAAI,CAW7G;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAEjD","sourcesContent":["import type { AutocompleteProvider } from \"../../../autocomplete.ts\";\nimport { graphemeSegmenter, wordSegmenter } from \"../constants.ts\";\nimport type { Editor } from \"../editor.ts\";\nimport { segmentWithMarkers } from \"../paste-marker.ts\";\n\nexport function do_validPasteIds(self: Editor): Set<number> {\n return new Set(self.pastes.keys());\n}\n\nexport function do_segment(self: Editor, text: string, mode: \"word\" | \"grapheme\"): Iterable<Intl.SegmentData> {\n return segmentWithMarkers(text, mode === \"word\" ? wordSegmenter : graphemeSegmenter, self.validPasteIds());\n}\n\nexport function do_getPaddingX(self: Editor): number {\n return self.paddingX;\n}\n\nexport function do_setPaddingX(self: Editor, padding: number): void {\n const newPadding = Number.isFinite(padding) ? Math.max(0, Math.floor(padding)) : 0;\n if (self.paddingX !== newPadding) {\n self.paddingX = newPadding;\n self.tui.requestRender();\n }\n}\n\nexport function do_getAutocompleteMaxVisible(self: Editor): number {\n return self.autocompleteMaxVisible;\n}\n\nexport function do_setAutocompleteMaxVisible(self: Editor, maxVisible: number): void {\n const newMaxVisible = Number.isFinite(maxVisible) ? Math.max(3, Math.min(20, Math.floor(maxVisible))) : 5;\n if (self.autocompleteMaxVisible !== newMaxVisible) {\n self.autocompleteMaxVisible = newMaxVisible;\n self.tui.requestRender();\n }\n}\n\nexport function do_setAutocompleteProvider(self: Editor, provider: AutocompleteProvider): void {\n self.cancelAutocomplete();\n self.autocompleteProvider = provider;\n self.setAutocompleteTriggerCharacters(provider.triggerCharacters ?? []);\n}\n\nexport function do_addToHistory(self: Editor, text: string): void {\n const trimmed = text.trim();\n if (!trimmed) return;\n // Don't add consecutive duplicates\n if (self.history.length > 0 && self.history[0] === trimmed) return;\n self.history.unshift(trimmed);\n // Limit history size\n if (self.history.length > 100) {\n self.history.pop();\n }\n}\n\nexport function do_isOnFirstVisualLine(self: Editor): boolean {\n const visualLines = self.buildVisualLineMap(self.lastWidth);\n const currentVisualLine = self.findCurrentVisualLine(visualLines);\n return currentVisualLine === 0;\n}\n\nexport function do_isOnLastVisualLine(self: Editor): boolean {\n const visualLines = self.buildVisualLineMap(self.lastWidth);\n const currentVisualLine = self.findCurrentVisualLine(visualLines);\n return currentVisualLine === visualLines.length - 1;\n}\n\nexport function do_navigateHistory(self: Editor, direction: 1 | -1): void {\n self.lastAction = null;\n if (self.history.length === 0) return;\n\n const newIndex = self.historyIndex - direction; // Up(-1) increases index, Down(1) decreases\n if (newIndex < -1 || newIndex >= self.history.length) return;\n\n // Capture state when first entering history browsing mode\n if (self.historyIndex === -1 && newIndex >= 0) {\n self.pushUndoSnapshot();\n self.historyDraft = structuredClone(self.state);\n }\n\n self.historyIndex = newIndex;\n\n if (self.historyIndex === -1) {\n const draft = self.historyDraft;\n self.historyDraft = null;\n if (draft) {\n self.state = draft;\n self.preferredVisualCol = null;\n self.snappedFromCursorCol = null;\n self.scrollOffset = 0;\n if (self.onChange) self.onChange(self.getText());\n } else {\n self.setTextInternal(\"\");\n }\n } else {\n self.setTextInternal(self.history[self.historyIndex] || \"\", direction === -1 ? \"start\" : \"end\");\n }\n}\n\nexport function do_exitHistoryBrowsing(self: Editor): void {\n self.historyIndex = -1;\n self.historyDraft = null;\n}\n\nexport function do_setTextInternal(self: Editor, text: string, cursorPlacement: \"start\" | \"end\" = \"end\"): void {\n const lines = text.split(\"\\n\");\n self.state.lines = lines.length === 0 ? [\"\"] : lines;\n self.state.cursorLine = cursorPlacement === \"start\" ? 0 : self.state.lines.length - 1;\n self.setCursorCol(cursorPlacement === \"start\" ? 0 : self.state.lines[self.state.cursorLine]?.length || 0);\n // Reset scroll - render() will adjust to show cursor\n self.scrollOffset = 0;\n\n if (self.onChange) {\n self.onChange(self.getText());\n }\n}\n\nexport function do_invalidate(_self: Editor): void {\n // No cached state to invalidate currently\n}\n"]}