@aigne/cli 1.60.0-beta → 1.74.0-beta

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 (360) hide show
  1. package/README.md +12 -12
  2. package/dist/_virtual/rolldown_runtime.cjs +29 -0
  3. package/dist/bunwrapper.cjs +22 -0
  4. package/dist/bunwrapper.d.cts +1 -0
  5. package/dist/bunwrapper.d.mts +1 -0
  6. package/dist/bunwrapper.mjs +23 -0
  7. package/dist/bunwrapper.mjs.map +1 -0
  8. package/dist/cli.cjs +42 -0
  9. package/dist/cli.d.cts +9 -0
  10. package/dist/cli.d.cts.map +1 -0
  11. package/dist/cli.d.mts +10 -0
  12. package/dist/cli.d.mts.map +1 -0
  13. package/dist/cli.mjs +41 -0
  14. package/dist/cli.mjs.map +1 -0
  15. package/dist/commands/aigne.cjs +23 -0
  16. package/dist/commands/aigne.mjs +22 -0
  17. package/dist/commands/aigne.mjs.map +1 -0
  18. package/dist/commands/app/agent.cjs +117 -0
  19. package/dist/commands/app/agent.mjs +113 -0
  20. package/dist/commands/app/agent.mjs.map +1 -0
  21. package/dist/commands/app/app.cjs +92 -0
  22. package/dist/commands/app/app.mjs +90 -0
  23. package/dist/commands/app/app.mjs.map +1 -0
  24. package/dist/commands/app/cli.cjs +6 -0
  25. package/dist/commands/app/cli.d.cts +1 -0
  26. package/dist/commands/app/cli.d.mts +1 -0
  27. package/dist/commands/app/cli.mjs +8 -0
  28. package/dist/commands/app/cli.mjs.map +1 -0
  29. package/dist/commands/app/upgrade.cjs +243 -0
  30. package/dist/commands/app/upgrade.mjs +240 -0
  31. package/dist/commands/app/upgrade.mjs.map +1 -0
  32. package/dist/commands/app.cjs +53 -0
  33. package/dist/commands/app.mjs +53 -0
  34. package/dist/commands/app.mjs.map +1 -0
  35. package/dist/commands/create.cjs +66 -0
  36. package/dist/commands/create.mjs +65 -0
  37. package/dist/commands/create.mjs.map +1 -0
  38. package/dist/commands/deploy.cjs +237 -0
  39. package/dist/commands/deploy.mjs +237 -0
  40. package/dist/commands/deploy.mjs.map +1 -0
  41. package/dist/commands/eval.cjs +88 -0
  42. package/dist/commands/eval.mjs +88 -0
  43. package/dist/commands/eval.mjs.map +1 -0
  44. package/dist/commands/hub.cjs +297 -0
  45. package/dist/commands/hub.mjs +294 -0
  46. package/dist/commands/hub.mjs.map +1 -0
  47. package/dist/commands/observe.cjs +49 -0
  48. package/dist/commands/observe.mjs +46 -0
  49. package/dist/commands/observe.mjs.map +1 -0
  50. package/dist/commands/run-skill.cjs +84 -0
  51. package/dist/commands/run-skill.mjs +81 -0
  52. package/dist/commands/run-skill.mjs.map +1 -0
  53. package/dist/commands/run.cjs +172 -0
  54. package/dist/commands/run.mjs +171 -0
  55. package/dist/commands/run.mjs.map +1 -0
  56. package/dist/commands/serve-mcp.cjs +68 -0
  57. package/dist/commands/serve-mcp.mjs +67 -0
  58. package/dist/commands/serve-mcp.mjs.map +1 -0
  59. package/dist/commands/test.cjs +40 -0
  60. package/dist/commands/test.mjs +39 -0
  61. package/dist/commands/test.mjs.map +1 -0
  62. package/dist/constants.cjs +28 -0
  63. package/dist/constants.d.cts +9 -0
  64. package/dist/constants.d.cts.map +1 -0
  65. package/dist/constants.d.mts +9 -0
  66. package/dist/constants.d.mts.map +1 -0
  67. package/dist/constants.mjs +24 -0
  68. package/dist/constants.mjs.map +1 -0
  69. package/dist/global.d.cjs +0 -0
  70. package/dist/global.d.cts +6 -0
  71. package/dist/global.d.cts.map +1 -0
  72. package/dist/global.d.mts +6 -0
  73. package/dist/global.d.mts.map +1 -0
  74. package/dist/index.cjs +0 -0
  75. package/dist/index.d.cts +2 -0
  76. package/dist/index.d.mts +2 -0
  77. package/dist/index.mjs +1 -0
  78. package/dist/tracer/terminal.cjs +336 -0
  79. package/dist/tracer/terminal.mjs +332 -0
  80. package/dist/tracer/terminal.mjs.map +1 -0
  81. package/dist/type.cjs +0 -0
  82. package/dist/type.d.cts +10 -0
  83. package/dist/type.d.cts.map +1 -0
  84. package/dist/type.d.mts +10 -0
  85. package/dist/type.d.mts.map +1 -0
  86. package/dist/type.mjs +1 -0
  87. package/dist/ui/utils/terminal-input.cjs +145 -0
  88. package/dist/ui/utils/terminal-input.mjs +144 -0
  89. package/dist/ui/utils/terminal-input.mjs.map +1 -0
  90. package/dist/ui/utils/text-buffer.cjs +865 -0
  91. package/dist/ui/utils/text-buffer.mjs +865 -0
  92. package/dist/ui/utils/text-buffer.mjs.map +1 -0
  93. package/dist/ui/utils/text-utils.cjs +85 -0
  94. package/dist/ui/utils/text-utils.mjs +78 -0
  95. package/dist/ui/utils/text-utils.mjs.map +1 -0
  96. package/dist/utils/agent-v1.cjs +180 -0
  97. package/dist/utils/agent-v1.d.cts +138 -0
  98. package/dist/utils/agent-v1.d.cts.map +1 -0
  99. package/dist/utils/agent-v1.d.mts +138 -0
  100. package/dist/utils/agent-v1.d.mts.map +1 -0
  101. package/dist/utils/agent-v1.mjs +179 -0
  102. package/dist/utils/agent-v1.mjs.map +1 -0
  103. package/dist/utils/aigne-hub/constants.cjs +22 -0
  104. package/dist/utils/aigne-hub/constants.mjs +18 -0
  105. package/dist/utils/aigne-hub/constants.mjs.map +1 -0
  106. package/dist/utils/aigne-hub/credential.cjs +179 -0
  107. package/dist/utils/aigne-hub/credential.mjs +175 -0
  108. package/dist/utils/aigne-hub/credential.mjs.map +1 -0
  109. package/dist/utils/aigne-hub/crypto.cjs +41 -0
  110. package/dist/utils/aigne-hub/crypto.mjs +33 -0
  111. package/dist/utils/aigne-hub/crypto.mjs.map +1 -0
  112. package/dist/utils/aigne-hub/model.cjs +112 -0
  113. package/dist/utils/aigne-hub/model.d.cts +19 -0
  114. package/dist/utils/aigne-hub/model.d.cts.map +1 -0
  115. package/dist/utils/aigne-hub/model.d.mts +19 -0
  116. package/dist/utils/aigne-hub/model.d.mts.map +1 -0
  117. package/dist/utils/aigne-hub/model.mjs +106 -0
  118. package/dist/utils/aigne-hub/model.mjs.map +1 -0
  119. package/dist/utils/aigne-hub/store/file.cjs +64 -0
  120. package/dist/utils/aigne-hub/store/file.mjs +64 -0
  121. package/dist/utils/aigne-hub/store/file.mjs.map +1 -0
  122. package/dist/utils/aigne-hub/store/index.cjs +37 -0
  123. package/dist/utils/aigne-hub/store/index.mjs +37 -0
  124. package/dist/utils/aigne-hub/store/index.mjs.map +1 -0
  125. package/dist/utils/aigne-hub/store/keytar.cjs +61 -0
  126. package/dist/utils/aigne-hub/store/keytar.mjs +61 -0
  127. package/dist/utils/aigne-hub/store/keytar.mjs.map +1 -0
  128. package/dist/utils/aigne-hub/store/migrate.cjs +46 -0
  129. package/dist/utils/aigne-hub/store/migrate.mjs +45 -0
  130. package/dist/utils/aigne-hub/store/migrate.mjs.map +1 -0
  131. package/dist/utils/aigne-hub/type.d.cts +18 -0
  132. package/dist/utils/aigne-hub/type.d.cts.map +1 -0
  133. package/dist/utils/aigne-hub/type.d.mts +18 -0
  134. package/dist/utils/aigne-hub/type.d.mts.map +1 -0
  135. package/dist/utils/aigne-hub-user.cjs +11 -0
  136. package/dist/utils/aigne-hub-user.d.cts +23 -0
  137. package/dist/utils/aigne-hub-user.d.cts.map +1 -0
  138. package/dist/utils/aigne-hub-user.d.mts +23 -0
  139. package/dist/utils/aigne-hub-user.d.mts.map +1 -0
  140. package/dist/utils/aigne-hub-user.mjs +11 -0
  141. package/dist/utils/aigne-hub-user.mjs.map +1 -0
  142. package/dist/utils/ascii-logo.cjs +30 -0
  143. package/dist/utils/ascii-logo.d.cts +5 -0
  144. package/dist/utils/ascii-logo.d.cts.map +1 -0
  145. package/dist/utils/ascii-logo.d.mts +5 -0
  146. package/dist/utils/ascii-logo.d.mts.map +1 -0
  147. package/dist/utils/{ascii-logo.js → ascii-logo.mjs} +13 -3
  148. package/dist/utils/ascii-logo.mjs.map +1 -0
  149. package/dist/utils/download.cjs +25 -0
  150. package/dist/utils/download.d.cts +7 -0
  151. package/dist/utils/download.d.cts.map +1 -0
  152. package/dist/utils/download.d.mts +7 -0
  153. package/dist/utils/download.d.mts.map +1 -0
  154. package/dist/utils/download.mjs +25 -0
  155. package/dist/utils/download.mjs.map +1 -0
  156. package/dist/utils/evaluation/core.cjs +84 -0
  157. package/dist/utils/evaluation/core.mjs +84 -0
  158. package/dist/utils/evaluation/core.mjs.map +1 -0
  159. package/dist/utils/evaluation/dataset.cjs +47 -0
  160. package/dist/utils/evaluation/dataset.mjs +46 -0
  161. package/dist/utils/evaluation/dataset.mjs.map +1 -0
  162. package/dist/utils/evaluation/evaluator.cjs +109 -0
  163. package/dist/utils/evaluation/{evaluator.js → evaluator.mjs} +48 -45
  164. package/dist/utils/evaluation/evaluator.mjs.map +1 -0
  165. package/dist/utils/evaluation/reporter.cjs +225 -0
  166. package/dist/utils/evaluation/reporter.mjs +220 -0
  167. package/dist/utils/evaluation/reporter.mjs.map +1 -0
  168. package/dist/utils/evaluation/runner.cjs +85 -0
  169. package/dist/utils/evaluation/runner.mjs +85 -0
  170. package/dist/utils/evaluation/runner.mjs.map +1 -0
  171. package/dist/utils/get-url-origin.cjs +12 -0
  172. package/dist/utils/get-url-origin.d.cts +5 -0
  173. package/dist/utils/get-url-origin.d.cts.map +1 -0
  174. package/dist/utils/get-url-origin.d.mts +5 -0
  175. package/dist/utils/get-url-origin.d.mts.map +1 -0
  176. package/dist/utils/get-url-origin.mjs +12 -0
  177. package/dist/utils/get-url-origin.mjs.map +1 -0
  178. package/dist/utils/inquirer/checkbox.cjs +265 -0
  179. package/dist/utils/inquirer/checkbox.mjs +262 -0
  180. package/dist/utils/inquirer/checkbox.mjs.map +1 -0
  181. package/dist/utils/listr.cjs +226 -0
  182. package/dist/utils/listr.d.cts +71 -0
  183. package/dist/utils/listr.d.cts.map +1 -0
  184. package/dist/utils/listr.d.mts +71 -0
  185. package/dist/utils/listr.d.mts.map +1 -0
  186. package/dist/utils/listr.mjs +222 -0
  187. package/dist/utils/listr.mjs.map +1 -0
  188. package/dist/utils/load-aigne.cjs +77 -0
  189. package/dist/utils/load-aigne.d.cts +29 -0
  190. package/dist/utils/load-aigne.d.cts.map +1 -0
  191. package/dist/utils/load-aigne.d.mts +29 -0
  192. package/dist/utils/load-aigne.d.mts.map +1 -0
  193. package/dist/utils/load-aigne.mjs +74 -0
  194. package/dist/utils/load-aigne.mjs.map +1 -0
  195. package/dist/utils/run-chat-loop.cjs +90 -0
  196. package/dist/utils/run-chat-loop.d.cts +20 -0
  197. package/dist/utils/run-chat-loop.d.cts.map +1 -0
  198. package/dist/utils/run-chat-loop.d.mts +20 -0
  199. package/dist/utils/run-chat-loop.d.mts.map +1 -0
  200. package/dist/utils/run-chat-loop.mjs +89 -0
  201. package/dist/utils/run-chat-loop.mjs.map +1 -0
  202. package/dist/utils/run-with-aigne.cjs +131 -0
  203. package/dist/utils/run-with-aigne.d.cts +46 -0
  204. package/dist/utils/run-with-aigne.d.cts.map +1 -0
  205. package/dist/utils/run-with-aigne.d.mts +46 -0
  206. package/dist/utils/run-with-aigne.d.mts.map +1 -0
  207. package/dist/utils/run-with-aigne.mjs +126 -0
  208. package/dist/utils/run-with-aigne.mjs.map +1 -0
  209. package/dist/utils/serve-mcp.cjs +91 -0
  210. package/dist/utils/serve-mcp.d.cts +20 -0
  211. package/dist/utils/serve-mcp.d.cts.map +1 -0
  212. package/dist/utils/serve-mcp.d.mts +20 -0
  213. package/dist/utils/serve-mcp.d.mts.map +1 -0
  214. package/dist/utils/serve-mcp.mjs +89 -0
  215. package/dist/utils/serve-mcp.mjs.map +1 -0
  216. package/dist/utils/spinner.cjs +19 -0
  217. package/dist/utils/spinner.d.cts +5 -0
  218. package/dist/utils/spinner.d.cts.map +1 -0
  219. package/dist/utils/spinner.d.mts +5 -0
  220. package/dist/utils/spinner.d.mts.map +1 -0
  221. package/dist/utils/spinner.mjs +19 -0
  222. package/dist/utils/spinner.mjs.map +1 -0
  223. package/dist/utils/string-utils.cjs +11 -0
  224. package/dist/utils/string-utils.d.cts +5 -0
  225. package/dist/utils/string-utils.d.cts.map +1 -0
  226. package/dist/utils/string-utils.d.mts +5 -0
  227. package/dist/utils/string-utils.d.mts.map +1 -0
  228. package/dist/utils/string-utils.mjs +10 -0
  229. package/dist/utils/string-utils.mjs.map +1 -0
  230. package/dist/utils/time.cjs +14 -0
  231. package/dist/utils/time.d.cts +5 -0
  232. package/dist/utils/time.d.cts.map +1 -0
  233. package/dist/utils/time.d.mts +5 -0
  234. package/dist/utils/time.d.mts.map +1 -0
  235. package/dist/utils/time.mjs +14 -0
  236. package/dist/utils/time.mjs.map +1 -0
  237. package/dist/utils/url.cjs +8 -0
  238. package/dist/utils/url.d.cts +5 -0
  239. package/dist/utils/url.d.cts.map +1 -0
  240. package/dist/utils/url.d.mts +5 -0
  241. package/dist/utils/url.d.mts.map +1 -0
  242. package/dist/utils/url.mjs +8 -0
  243. package/dist/utils/url.mjs.map +1 -0
  244. package/dist/utils/yargs.cjs +191 -0
  245. package/dist/utils/yargs.d.cts +96 -0
  246. package/dist/utils/yargs.d.cts.map +1 -0
  247. package/dist/utils/yargs.d.mts +96 -0
  248. package/dist/utils/yargs.d.mts.map +1 -0
  249. package/dist/utils/yargs.mjs +186 -0
  250. package/dist/utils/yargs.mjs.map +1 -0
  251. package/package.json +122 -45
  252. package/CHANGELOG.md +0 -5019
  253. package/dist/bunwrapper.d.ts +0 -2
  254. package/dist/bunwrapper.js +0 -18
  255. package/dist/cli.d.ts +0 -7
  256. package/dist/cli.js +0 -42
  257. package/dist/commands/aigne.d.ts +0 -4
  258. package/dist/commands/aigne.js +0 -35
  259. package/dist/commands/app/agent.d.ts +0 -26
  260. package/dist/commands/app/agent.js +0 -122
  261. package/dist/commands/app/app.d.ts +0 -7
  262. package/dist/commands/app/app.js +0 -92
  263. package/dist/commands/app/cli.d.ts +0 -1
  264. package/dist/commands/app/cli.js +0 -2
  265. package/dist/commands/app/upgrade.d.ts +0 -54
  266. package/dist/commands/app/upgrade.js +0 -236
  267. package/dist/commands/app.d.ts +0 -4
  268. package/dist/commands/app.js +0 -54
  269. package/dist/commands/create.d.ts +0 -6
  270. package/dist/commands/create.js +0 -74
  271. package/dist/commands/deploy.d.ts +0 -11
  272. package/dist/commands/deploy.js +0 -255
  273. package/dist/commands/eval.d.ts +0 -11
  274. package/dist/commands/eval.js +0 -110
  275. package/dist/commands/hub.d.ts +0 -3
  276. package/dist/commands/hub.js +0 -323
  277. package/dist/commands/observe.d.ts +0 -7
  278. package/dist/commands/observe.js +0 -41
  279. package/dist/commands/run-skill.d.ts +0 -6
  280. package/dist/commands/run-skill.js +0 -102
  281. package/dist/commands/run.d.ts +0 -9
  282. package/dist/commands/run.js +0 -187
  283. package/dist/commands/serve-mcp.d.ts +0 -20
  284. package/dist/commands/serve-mcp.js +0 -67
  285. package/dist/commands/test.d.ts +0 -9
  286. package/dist/commands/test.js +0 -33
  287. package/dist/constants.d.ts +0 -7
  288. package/dist/constants.js +0 -21
  289. package/dist/index.d.ts +0 -1
  290. package/dist/index.js +0 -1
  291. package/dist/tracer/terminal.d.ts +0 -62
  292. package/dist/tracer/terminal.js +0 -404
  293. package/dist/type.d.ts +0 -5
  294. package/dist/type.js +0 -1
  295. package/dist/ui/utils/terminal-input.d.ts +0 -19
  296. package/dist/ui/utils/terminal-input.js +0 -123
  297. package/dist/ui/utils/text-buffer.d.ts +0 -87
  298. package/dist/ui/utils/text-buffer.js +0 -1059
  299. package/dist/ui/utils/text-utils.d.ts +0 -37
  300. package/dist/ui/utils/text-utils.js +0 -185
  301. package/dist/utils/agent-v1.d.ts +0 -134
  302. package/dist/utils/agent-v1.js +0 -213
  303. package/dist/utils/aigne-hub/constants.d.ts +0 -6
  304. package/dist/utils/aigne-hub/constants.js +0 -12
  305. package/dist/utils/aigne-hub/credential.d.ts +0 -20
  306. package/dist/utils/aigne-hub/credential.js +0 -182
  307. package/dist/utils/aigne-hub/crypto.d.ts +0 -4
  308. package/dist/utils/aigne-hub/crypto.js +0 -30
  309. package/dist/utils/aigne-hub/model.d.ts +0 -13
  310. package/dist/utils/aigne-hub/model.js +0 -122
  311. package/dist/utils/aigne-hub/store/file.d.ts +0 -15
  312. package/dist/utils/aigne-hub/store/file.js +0 -69
  313. package/dist/utils/aigne-hub/store/index.d.ts +0 -5
  314. package/dist/utils/aigne-hub/store/index.js +0 -43
  315. package/dist/utils/aigne-hub/store/keytar.d.ts +0 -15
  316. package/dist/utils/aigne-hub/store/keytar.js +0 -67
  317. package/dist/utils/aigne-hub/store/migrate.d.ts +0 -2
  318. package/dist/utils/aigne-hub/store/migrate.js +0 -57
  319. package/dist/utils/aigne-hub/type.d.ts +0 -38
  320. package/dist/utils/aigne-hub/type.js +0 -1
  321. package/dist/utils/aigne-hub-user.d.ts +0 -16
  322. package/dist/utils/aigne-hub-user.js +0 -10
  323. package/dist/utils/ascii-logo.d.ts +0 -1
  324. package/dist/utils/download.d.ts +0 -3
  325. package/dist/utils/download.js +0 -19
  326. package/dist/utils/evaluation/core.d.ts +0 -8
  327. package/dist/utils/evaluation/core.js +0 -83
  328. package/dist/utils/evaluation/dataset.d.ts +0 -15
  329. package/dist/utils/evaluation/dataset.js +0 -61
  330. package/dist/utils/evaluation/evaluator.d.ts +0 -9
  331. package/dist/utils/evaluation/reporter.d.ts +0 -28
  332. package/dist/utils/evaluation/reporter.js +0 -221
  333. package/dist/utils/evaluation/runner.d.ts +0 -16
  334. package/dist/utils/evaluation/runner.js +0 -129
  335. package/dist/utils/evaluation/type.d.ts +0 -69
  336. package/dist/utils/evaluation/type.js +0 -1
  337. package/dist/utils/get-url-origin.d.ts +0 -1
  338. package/dist/utils/get-url-origin.js +0 -8
  339. package/dist/utils/inquirer/checkbox.d.ts +0 -55
  340. package/dist/utils/inquirer/checkbox.js +0 -319
  341. package/dist/utils/listr.d.ts +0 -64
  342. package/dist/utils/listr.js +0 -265
  343. package/dist/utils/load-aigne.d.ts +0 -18
  344. package/dist/utils/load-aigne.js +0 -80
  345. package/dist/utils/run-chat-loop.d.ts +0 -15
  346. package/dist/utils/run-chat-loop.js +0 -87
  347. package/dist/utils/run-with-aigne.d.ts +0 -27
  348. package/dist/utils/run-with-aigne.js +0 -157
  349. package/dist/utils/serve-mcp.d.ts +0 -9
  350. package/dist/utils/serve-mcp.js +0 -93
  351. package/dist/utils/spinner.d.ts +0 -1
  352. package/dist/utils/spinner.js +0 -14
  353. package/dist/utils/string-utils.d.ts +0 -1
  354. package/dist/utils/string-utils.js +0 -4
  355. package/dist/utils/time.d.ts +0 -1
  356. package/dist/utils/time.js +0 -12
  357. package/dist/utils/url.d.ts +0 -1
  358. package/dist/utils/url.js +0 -3
  359. package/dist/utils/yargs.d.ts +0 -94
  360. package/dist/utils/yargs.js +0 -210
@@ -0,0 +1,865 @@
1
+ import { cpLen, cpSlice, getCachedStringWidth, stripUnsafeCharacters, toCodePoints } from "./text-utils.mjs";
2
+ import { useCallback, useEffect, useMemo, useReducer, useState } from "react";
3
+
4
+ //#region src/ui/utils/text-buffer.ts
5
+ /**
6
+ * @license
7
+ * Copyright 2025 Google LLC
8
+ * SPDX-License-Identifier: Apache-2.0
9
+ */
10
+ function isWordChar(ch) {
11
+ if (ch === void 0) return false;
12
+ return !/[\s,.;!?]/.test(ch);
13
+ }
14
+ const isWordCharStrict = (char) => /[\w\p{L}\p{N}]/u.test(char);
15
+ const isWhitespace = (char) => /\s/.test(char);
16
+ const isCombiningMark = (char) => /\p{M}/u.test(char);
17
+ const isWordCharWithCombining = (char) => isWordCharStrict(char) || isCombiningMark(char);
18
+ const getCharScript = (char) => {
19
+ if (/[\p{Script=Latin}]/u.test(char)) return "latin";
20
+ if (/[\p{Script=Han}]/u.test(char)) return "han";
21
+ if (/[\p{Script=Arabic}]/u.test(char)) return "arabic";
22
+ if (/[\p{Script=Hiragana}]/u.test(char)) return "hiragana";
23
+ if (/[\p{Script=Katakana}]/u.test(char)) return "katakana";
24
+ if (/[\p{Script=Cyrillic}]/u.test(char)) return "cyrillic";
25
+ return "other";
26
+ };
27
+ const isDifferentScript = (char1, char2) => {
28
+ if (!isWordCharStrict(char1) || !isWordCharStrict(char2)) return false;
29
+ return getCharScript(char1) !== getCharScript(char2);
30
+ };
31
+ const findNextWordStartInLine = (line, col) => {
32
+ const chars = toCodePoints(line);
33
+ let i = col;
34
+ if (i >= chars.length) return null;
35
+ const currentChar = chars[i];
36
+ if (isWordCharStrict(currentChar)) while (i < chars.length && isWordCharWithCombining(chars[i])) {
37
+ if (i + 1 < chars.length && isWordCharStrict(chars[i + 1]) && isDifferentScript(chars[i], chars[i + 1])) {
38
+ i++;
39
+ break;
40
+ }
41
+ i++;
42
+ }
43
+ else if (!isWhitespace(currentChar)) while (i < chars.length && !isWordCharStrict(chars[i]) && !isWhitespace(chars[i])) i++;
44
+ while (i < chars.length && isWhitespace(chars[i])) i++;
45
+ return i < chars.length ? i : null;
46
+ };
47
+ const findPrevWordStartInLine = (line, col) => {
48
+ const chars = toCodePoints(line);
49
+ let i = col;
50
+ if (i <= 0) return null;
51
+ i--;
52
+ while (i >= 0 && isWhitespace(chars[i])) i--;
53
+ if (i < 0) return null;
54
+ if (isWordCharStrict(chars[i])) {
55
+ while (i >= 0 && isWordCharStrict(chars[i])) {
56
+ if (i - 1 >= 0 && isWordCharStrict(chars[i - 1]) && isDifferentScript(chars[i], chars[i - 1])) return i;
57
+ i--;
58
+ }
59
+ return i + 1;
60
+ } else {
61
+ while (i >= 0 && !isWordCharStrict(chars[i]) && !isWhitespace(chars[i])) i--;
62
+ return i + 1;
63
+ }
64
+ };
65
+ const replaceRangeInternal = (state, startRow, startCol, endRow, endCol, text) => {
66
+ const currentLine = (row) => state.lines[row] || "";
67
+ const currentLineLen = (row) => cpLen(currentLine(row));
68
+ const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
69
+ if (startRow > endRow || startRow === endRow && startCol > endCol || startRow < 0 || startCol < 0 || endRow >= state.lines.length || endRow < state.lines.length && endCol > currentLineLen(endRow)) return state;
70
+ const newLines = [...state.lines];
71
+ const sCol = clamp(startCol, 0, currentLineLen(startRow));
72
+ const eCol = clamp(endCol, 0, currentLineLen(endRow));
73
+ const prefix = cpSlice(currentLine(startRow), 0, sCol);
74
+ const suffix = cpSlice(currentLine(endRow), eCol);
75
+ const replacementParts = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").split("\n");
76
+ const firstLine = prefix + replacementParts[0];
77
+ if (replacementParts.length === 1) newLines.splice(startRow, endRow - startRow + 1, firstLine + suffix);
78
+ else {
79
+ const lastLine = replacementParts[replacementParts.length - 1] + suffix;
80
+ const middleLines = replacementParts.slice(1, -1);
81
+ newLines.splice(startRow, endRow - startRow + 1, firstLine, ...middleLines, lastLine);
82
+ }
83
+ const finalCursorRow = startRow + replacementParts.length - 1;
84
+ const finalCursorCol = (replacementParts.length > 1 ? 0 : sCol) + cpLen(replacementParts[replacementParts.length - 1]);
85
+ return {
86
+ ...state,
87
+ lines: newLines,
88
+ cursorRow: Math.min(Math.max(finalCursorRow, 0), newLines.length - 1),
89
+ cursorCol: Math.max(0, Math.min(finalCursorCol, cpLen(newLines[finalCursorRow] || ""))),
90
+ preferredCol: null
91
+ };
92
+ };
93
+ function clamp(v, min, max) {
94
+ return v < min ? min : v > max ? max : v;
95
+ }
96
+ function calculateInitialCursorPosition(initialLines, offset) {
97
+ let remainingChars = offset;
98
+ let row = 0;
99
+ while (row < initialLines.length) {
100
+ const lineLength = cpLen(initialLines[row]);
101
+ const totalCharsInLineAndNewline = lineLength + (row < initialLines.length - 1 ? 1 : 0);
102
+ if (remainingChars <= lineLength) return [row, remainingChars];
103
+ remainingChars -= totalCharsInLineAndNewline;
104
+ row++;
105
+ }
106
+ if (initialLines.length > 0) {
107
+ const lastRow = initialLines.length - 1;
108
+ return [lastRow, cpLen(initialLines[lastRow])];
109
+ }
110
+ return [0, 0];
111
+ }
112
+ function offsetToLogicalPos(text, offset) {
113
+ let row = 0;
114
+ let col = 0;
115
+ let currentOffset = 0;
116
+ if (offset === 0) return [0, 0];
117
+ const lines = text.split("\n");
118
+ for (let i = 0; i < lines.length; i++) {
119
+ const line = lines[i];
120
+ const lineLength = cpLen(line);
121
+ const lineLengthWithNewline = lineLength + (i < lines.length - 1 ? 1 : 0);
122
+ if (offset <= currentOffset + lineLength) {
123
+ row = i;
124
+ col = offset - currentOffset;
125
+ return [row, col];
126
+ } else if (offset <= currentOffset + lineLengthWithNewline) {
127
+ row = i;
128
+ col = lineLength;
129
+ if (offset === currentOffset + lineLengthWithNewline && i < lines.length - 1) return [i + 1, 0];
130
+ return [row, col];
131
+ }
132
+ currentOffset += lineLengthWithNewline;
133
+ }
134
+ if (lines.length > 0) {
135
+ row = lines.length - 1;
136
+ col = cpLen(lines[row]);
137
+ } else {
138
+ row = 0;
139
+ col = 0;
140
+ }
141
+ return [row, col];
142
+ }
143
+ function calculateLayout(logicalLines, viewportWidth) {
144
+ const visualLines = [];
145
+ const logicalToVisualMap = [];
146
+ const visualToLogicalMap = [];
147
+ logicalLines.forEach((logLine, logIndex) => {
148
+ logicalToVisualMap[logIndex] = [];
149
+ if (logLine.length === 0) {
150
+ logicalToVisualMap[logIndex].push([visualLines.length, 0]);
151
+ visualToLogicalMap.push([logIndex, 0]);
152
+ visualLines.push("");
153
+ } else {
154
+ let currentPosInLogLine = 0;
155
+ const codePointsInLogLine = toCodePoints(logLine);
156
+ while (currentPosInLogLine < codePointsInLogLine.length) {
157
+ let currentChunk = "";
158
+ let currentChunkVisualWidth = 0;
159
+ let numCodePointsInChunk = 0;
160
+ let lastWordBreakPoint = -1;
161
+ let numCodePointsAtLastWordBreak = 0;
162
+ for (let i = currentPosInLogLine; i < codePointsInLogLine.length; i++) {
163
+ const char = codePointsInLogLine[i];
164
+ const charVisualWidth = getCachedStringWidth(char);
165
+ if (currentChunkVisualWidth + charVisualWidth > viewportWidth) {
166
+ if (lastWordBreakPoint !== -1 && numCodePointsAtLastWordBreak > 0 && currentPosInLogLine + numCodePointsAtLastWordBreak < i) {
167
+ currentChunk = codePointsInLogLine.slice(currentPosInLogLine, currentPosInLogLine + numCodePointsAtLastWordBreak).join("");
168
+ numCodePointsInChunk = numCodePointsAtLastWordBreak;
169
+ } else if (numCodePointsInChunk === 0 && charVisualWidth > viewportWidth) {
170
+ currentChunk = char;
171
+ numCodePointsInChunk = 1;
172
+ } else if (numCodePointsInChunk === 0 && charVisualWidth <= viewportWidth) {}
173
+ break;
174
+ }
175
+ currentChunk += char;
176
+ currentChunkVisualWidth += charVisualWidth;
177
+ numCodePointsInChunk++;
178
+ if (char === " ") {
179
+ lastWordBreakPoint = i;
180
+ numCodePointsAtLastWordBreak = numCodePointsInChunk - 1;
181
+ }
182
+ }
183
+ if (numCodePointsInChunk === 0 && currentPosInLogLine < codePointsInLogLine.length) {
184
+ currentChunk = codePointsInLogLine[currentPosInLogLine];
185
+ numCodePointsInChunk = 1;
186
+ }
187
+ if (numCodePointsInChunk === 0 && currentPosInLogLine < codePointsInLogLine.length) {
188
+ currentChunk = codePointsInLogLine[currentPosInLogLine];
189
+ numCodePointsInChunk = 1;
190
+ }
191
+ logicalToVisualMap[logIndex].push([visualLines.length, currentPosInLogLine]);
192
+ visualToLogicalMap.push([logIndex, currentPosInLogLine]);
193
+ visualLines.push(currentChunk);
194
+ const logicalStartOfThisChunk = currentPosInLogLine;
195
+ currentPosInLogLine += numCodePointsInChunk;
196
+ if (logicalStartOfThisChunk + numCodePointsInChunk < codePointsInLogLine.length && currentPosInLogLine < codePointsInLogLine.length && codePointsInLogLine[currentPosInLogLine] === " ") currentPosInLogLine++;
197
+ }
198
+ }
199
+ });
200
+ if (logicalLines.length === 0 || logicalLines.length === 1 && logicalLines[0] === "") {
201
+ if (visualLines.length === 0) {
202
+ visualLines.push("");
203
+ if (!logicalToVisualMap[0]) logicalToVisualMap[0] = [];
204
+ logicalToVisualMap[0].push([0, 0]);
205
+ visualToLogicalMap.push([0, 0]);
206
+ }
207
+ }
208
+ return {
209
+ visualLines,
210
+ logicalToVisualMap,
211
+ visualToLogicalMap
212
+ };
213
+ }
214
+ function calculateVisualCursorFromLayout(layout, logicalCursor) {
215
+ const { logicalToVisualMap, visualLines } = layout;
216
+ const [logicalRow, logicalCol] = logicalCursor;
217
+ const segmentsForLogicalLine = logicalToVisualMap[logicalRow];
218
+ if (!segmentsForLogicalLine || segmentsForLogicalLine.length === 0) return [0, 0];
219
+ let targetSegmentIndex = segmentsForLogicalLine.findIndex(([, startColInLogical$1], index) => {
220
+ const nextStartColInLogical = index + 1 < segmentsForLogicalLine.length ? segmentsForLogicalLine[index + 1][1] : Infinity;
221
+ return logicalCol >= startColInLogical$1 && logicalCol < nextStartColInLogical;
222
+ });
223
+ if (targetSegmentIndex === -1) if (logicalCol === 0) targetSegmentIndex = 0;
224
+ else targetSegmentIndex = segmentsForLogicalLine.length - 1;
225
+ const [visualRow, startColInLogical] = segmentsForLogicalLine[targetSegmentIndex];
226
+ const visualCol = logicalCol - startColInLogical;
227
+ return [visualRow, Math.min(visualCol, cpLen(visualLines[visualRow] ?? ""))];
228
+ }
229
+ const historyLimit = 100;
230
+ const pushUndo = (currentState) => {
231
+ const snapshot = {
232
+ lines: [...currentState.lines],
233
+ cursorRow: currentState.cursorRow,
234
+ cursorCol: currentState.cursorCol
235
+ };
236
+ const newStack = [...currentState.undoStack, snapshot];
237
+ if (newStack.length > historyLimit) newStack.shift();
238
+ return {
239
+ ...currentState,
240
+ undoStack: newStack,
241
+ redoStack: []
242
+ };
243
+ };
244
+ function textBufferReducerLogic(state, action) {
245
+ const pushUndoLocal = pushUndo;
246
+ const currentLine = (r) => state.lines[r] ?? "";
247
+ const currentLineLen = (r) => cpLen(currentLine(r));
248
+ switch (action.type) {
249
+ case "set_text": {
250
+ let nextState = state;
251
+ if (action.pushToUndo !== false) nextState = pushUndoLocal(state);
252
+ const newContentLines = action.payload.replace(/\r\n?/g, "\n").split("\n");
253
+ const lines = newContentLines.length === 0 ? [""] : newContentLines;
254
+ const lastNewLineIndex = lines.length - 1;
255
+ return {
256
+ ...nextState,
257
+ lines,
258
+ cursorRow: lastNewLineIndex,
259
+ cursorCol: cpLen(lines[lastNewLineIndex] ?? ""),
260
+ preferredCol: null
261
+ };
262
+ }
263
+ case "insert": {
264
+ const nextState = pushUndoLocal(state);
265
+ const newLines = [...nextState.lines];
266
+ let newCursorRow = nextState.cursorRow;
267
+ let newCursorCol = nextState.cursorCol;
268
+ const currentLine$1 = (r) => newLines[r] ?? "";
269
+ const parts = stripUnsafeCharacters(action.payload.replace(/\r\n/g, "\n").replace(/\r/g, "\n")).split("\n");
270
+ const lineContent = currentLine$1(newCursorRow);
271
+ const before = cpSlice(lineContent, 0, newCursorCol);
272
+ const after = cpSlice(lineContent, newCursorCol);
273
+ if (parts.length > 1) {
274
+ newLines[newCursorRow] = before + parts[0];
275
+ const remainingParts = parts.slice(1);
276
+ const lastPartOriginal = remainingParts.pop() ?? "";
277
+ newLines.splice(newCursorRow + 1, 0, ...remainingParts);
278
+ newLines.splice(newCursorRow + parts.length - 1, 0, lastPartOriginal + after);
279
+ newCursorRow = newCursorRow + parts.length - 1;
280
+ newCursorCol = cpLen(lastPartOriginal);
281
+ } else {
282
+ newLines[newCursorRow] = before + parts[0] + after;
283
+ newCursorCol = cpLen(before) + cpLen(parts[0]);
284
+ }
285
+ return {
286
+ ...nextState,
287
+ lines: newLines,
288
+ cursorRow: newCursorRow,
289
+ cursorCol: newCursorCol,
290
+ preferredCol: null
291
+ };
292
+ }
293
+ case "backspace": {
294
+ const nextState = pushUndoLocal(state);
295
+ const newLines = [...nextState.lines];
296
+ let newCursorRow = nextState.cursorRow;
297
+ let newCursorCol = nextState.cursorCol;
298
+ const currentLine$1 = (r) => newLines[r] ?? "";
299
+ if (newCursorCol === 0 && newCursorRow === 0) return state;
300
+ if (newCursorCol > 0) {
301
+ const lineContent = currentLine$1(newCursorRow);
302
+ newLines[newCursorRow] = cpSlice(lineContent, 0, newCursorCol - 1) + cpSlice(lineContent, newCursorCol);
303
+ newCursorCol--;
304
+ } else if (newCursorRow > 0) {
305
+ const prevLineContent = currentLine$1(newCursorRow - 1);
306
+ const currentLineContentVal = currentLine$1(newCursorRow);
307
+ const newCol = cpLen(prevLineContent);
308
+ newLines[newCursorRow - 1] = prevLineContent + currentLineContentVal;
309
+ newLines.splice(newCursorRow, 1);
310
+ newCursorRow--;
311
+ newCursorCol = newCol;
312
+ }
313
+ return {
314
+ ...nextState,
315
+ lines: newLines,
316
+ cursorRow: newCursorRow,
317
+ cursorCol: newCursorCol,
318
+ preferredCol: null
319
+ };
320
+ }
321
+ case "set_viewport": {
322
+ const { width, height } = action.payload;
323
+ if (width === state.viewportWidth && height === state.viewportHeight) return state;
324
+ return {
325
+ ...state,
326
+ viewportWidth: width,
327
+ viewportHeight: height
328
+ };
329
+ }
330
+ case "move": {
331
+ const { dir } = action.payload;
332
+ const { cursorRow, cursorCol, lines, visualLayout, preferredCol } = state;
333
+ if (dir === "left" || dir === "right" || dir === "up" || dir === "down" || dir === "home" || dir === "end") {
334
+ const visualCursor = calculateVisualCursorFromLayout(visualLayout, [cursorRow, cursorCol]);
335
+ const { visualLines, visualToLogicalMap } = visualLayout;
336
+ let newVisualRow = visualCursor[0];
337
+ let newVisualCol = visualCursor[1];
338
+ let newPreferredCol = preferredCol;
339
+ const currentVisLineLen = cpLen(visualLines[newVisualRow] ?? "");
340
+ switch (dir) {
341
+ case "left":
342
+ newPreferredCol = null;
343
+ if (newVisualCol > 0) newVisualCol--;
344
+ else if (newVisualRow > 0) {
345
+ newVisualRow--;
346
+ newVisualCol = cpLen(visualLines[newVisualRow] ?? "");
347
+ }
348
+ break;
349
+ case "right":
350
+ newPreferredCol = null;
351
+ if (newVisualCol < currentVisLineLen) newVisualCol++;
352
+ else if (newVisualRow < visualLines.length - 1) {
353
+ newVisualRow++;
354
+ newVisualCol = 0;
355
+ }
356
+ break;
357
+ case "up":
358
+ if (newVisualRow > 0) {
359
+ if (newPreferredCol === null) newPreferredCol = newVisualCol;
360
+ newVisualRow--;
361
+ newVisualCol = clamp(newPreferredCol, 0, cpLen(visualLines[newVisualRow] ?? ""));
362
+ }
363
+ break;
364
+ case "down":
365
+ if (newVisualRow < visualLines.length - 1) {
366
+ if (newPreferredCol === null) newPreferredCol = newVisualCol;
367
+ newVisualRow++;
368
+ newVisualCol = clamp(newPreferredCol, 0, cpLen(visualLines[newVisualRow] ?? ""));
369
+ }
370
+ break;
371
+ case "home":
372
+ newPreferredCol = null;
373
+ newVisualCol = 0;
374
+ break;
375
+ case "end":
376
+ newPreferredCol = null;
377
+ newVisualCol = currentVisLineLen;
378
+ break;
379
+ default: {
380
+ const exhaustiveCheck = dir;
381
+ console.error(`Unknown visual movement direction: ${exhaustiveCheck}`);
382
+ return state;
383
+ }
384
+ }
385
+ if (visualToLogicalMap[newVisualRow]) {
386
+ const [logRow, logStartCol] = visualToLogicalMap[newVisualRow];
387
+ return {
388
+ ...state,
389
+ cursorRow: logRow,
390
+ cursorCol: clamp(logStartCol + newVisualCol, 0, cpLen(lines[logRow] ?? "")),
391
+ preferredCol: newPreferredCol
392
+ };
393
+ }
394
+ return state;
395
+ }
396
+ switch (dir) {
397
+ case "wordLeft": {
398
+ if (cursorCol === 0 && cursorRow === 0) return state;
399
+ let newCursorRow = cursorRow;
400
+ let newCursorCol = cursorCol;
401
+ if (cursorCol === 0) {
402
+ newCursorRow--;
403
+ newCursorCol = cpLen(lines[newCursorRow] ?? "");
404
+ } else {
405
+ const lineContent = lines[cursorRow];
406
+ const arr = toCodePoints(lineContent);
407
+ let start = cursorCol;
408
+ let onlySpaces = true;
409
+ for (let i = 0; i < start; i++) if (isWordChar(arr[i])) {
410
+ onlySpaces = false;
411
+ break;
412
+ }
413
+ if (onlySpaces && start > 0) start--;
414
+ else {
415
+ while (start > 0 && !isWordChar(arr[start - 1])) start--;
416
+ while (start > 0 && isWordChar(arr[start - 1])) start--;
417
+ }
418
+ newCursorCol = start;
419
+ }
420
+ return {
421
+ ...state,
422
+ cursorRow: newCursorRow,
423
+ cursorCol: newCursorCol,
424
+ preferredCol: null
425
+ };
426
+ }
427
+ case "wordRight": {
428
+ if (cursorRow === lines.length - 1 && cursorCol === cpLen(lines[cursorRow] ?? "")) return state;
429
+ let newCursorRow = cursorRow;
430
+ let newCursorCol = cursorCol;
431
+ const arr = toCodePoints(lines[cursorRow] ?? "");
432
+ if (cursorCol >= arr.length) {
433
+ newCursorRow++;
434
+ newCursorCol = 0;
435
+ } else {
436
+ let end = cursorCol;
437
+ while (end < arr.length && !isWordChar(arr[end])) end++;
438
+ while (end < arr.length && isWordChar(arr[end])) end++;
439
+ newCursorCol = end;
440
+ }
441
+ return {
442
+ ...state,
443
+ cursorRow: newCursorRow,
444
+ cursorCol: newCursorCol,
445
+ preferredCol: null
446
+ };
447
+ }
448
+ default: return state;
449
+ }
450
+ }
451
+ case "set_cursor": return {
452
+ ...state,
453
+ ...action.payload
454
+ };
455
+ case "delete": {
456
+ const { cursorRow, cursorCol, lines } = state;
457
+ const lineContent = currentLine(cursorRow);
458
+ if (cursorCol < currentLineLen(cursorRow)) {
459
+ const nextState = pushUndoLocal(state);
460
+ const newLines = [...nextState.lines];
461
+ newLines[cursorRow] = cpSlice(lineContent, 0, cursorCol) + cpSlice(lineContent, cursorCol + 1);
462
+ return {
463
+ ...nextState,
464
+ lines: newLines,
465
+ preferredCol: null
466
+ };
467
+ } else if (cursorRow < lines.length - 1) {
468
+ const nextState = pushUndoLocal(state);
469
+ const nextLineContent = currentLine(cursorRow + 1);
470
+ const newLines = [...nextState.lines];
471
+ newLines[cursorRow] = lineContent + nextLineContent;
472
+ newLines.splice(cursorRow + 1, 1);
473
+ return {
474
+ ...nextState,
475
+ lines: newLines,
476
+ preferredCol: null
477
+ };
478
+ }
479
+ return state;
480
+ }
481
+ case "delete_word_left": {
482
+ const { cursorRow, cursorCol } = state;
483
+ if (cursorCol === 0 && cursorRow === 0) return state;
484
+ const nextState = pushUndoLocal(state);
485
+ const newLines = [...nextState.lines];
486
+ let newCursorRow = cursorRow;
487
+ let newCursorCol = cursorCol;
488
+ if (newCursorCol > 0) {
489
+ const lineContent = currentLine(newCursorRow);
490
+ const prevWordStart = findPrevWordStartInLine(lineContent, newCursorCol);
491
+ const start = prevWordStart === null ? 0 : prevWordStart;
492
+ newLines[newCursorRow] = cpSlice(lineContent, 0, start) + cpSlice(lineContent, newCursorCol);
493
+ newCursorCol = start;
494
+ } else {
495
+ const prevLineContent = currentLine(cursorRow - 1);
496
+ const currentLineContentVal = currentLine(cursorRow);
497
+ const newCol = cpLen(prevLineContent);
498
+ newLines[cursorRow - 1] = prevLineContent + currentLineContentVal;
499
+ newLines.splice(cursorRow, 1);
500
+ newCursorRow--;
501
+ newCursorCol = newCol;
502
+ }
503
+ return {
504
+ ...nextState,
505
+ lines: newLines,
506
+ cursorRow: newCursorRow,
507
+ cursorCol: newCursorCol,
508
+ preferredCol: null
509
+ };
510
+ }
511
+ case "delete_word_right": {
512
+ const { cursorRow, cursorCol, lines } = state;
513
+ const lineContent = currentLine(cursorRow);
514
+ const lineLen = cpLen(lineContent);
515
+ if (cursorCol >= lineLen && cursorRow === lines.length - 1) return state;
516
+ const nextState = pushUndoLocal(state);
517
+ const newLines = [...nextState.lines];
518
+ if (cursorCol >= lineLen) {
519
+ newLines[cursorRow] = lineContent + currentLine(cursorRow + 1);
520
+ newLines.splice(cursorRow + 1, 1);
521
+ } else {
522
+ const nextWordStart = findNextWordStartInLine(lineContent, cursorCol);
523
+ const end = nextWordStart === null ? lineLen : nextWordStart;
524
+ newLines[cursorRow] = cpSlice(lineContent, 0, cursorCol) + cpSlice(lineContent, end);
525
+ }
526
+ return {
527
+ ...nextState,
528
+ lines: newLines,
529
+ preferredCol: null
530
+ };
531
+ }
532
+ case "kill_line_right": {
533
+ const { cursorRow, cursorCol, lines } = state;
534
+ const lineContent = currentLine(cursorRow);
535
+ if (cursorCol < currentLineLen(cursorRow)) {
536
+ const nextState = pushUndoLocal(state);
537
+ const newLines = [...nextState.lines];
538
+ newLines[cursorRow] = cpSlice(lineContent, 0, cursorCol);
539
+ return {
540
+ ...nextState,
541
+ lines: newLines
542
+ };
543
+ } else if (cursorRow < lines.length - 1) {
544
+ const nextState = pushUndoLocal(state);
545
+ const nextLineContent = currentLine(cursorRow + 1);
546
+ const newLines = [...nextState.lines];
547
+ newLines[cursorRow] = lineContent + nextLineContent;
548
+ newLines.splice(cursorRow + 1, 1);
549
+ return {
550
+ ...nextState,
551
+ lines: newLines,
552
+ preferredCol: null
553
+ };
554
+ }
555
+ return state;
556
+ }
557
+ case "kill_line_left": {
558
+ const { cursorRow, cursorCol } = state;
559
+ if (cursorCol > 0) {
560
+ const nextState = pushUndoLocal(state);
561
+ const lineContent = currentLine(cursorRow);
562
+ const newLines = [...nextState.lines];
563
+ newLines[cursorRow] = cpSlice(lineContent, cursorCol);
564
+ return {
565
+ ...nextState,
566
+ lines: newLines,
567
+ cursorCol: 0,
568
+ preferredCol: null
569
+ };
570
+ }
571
+ return state;
572
+ }
573
+ case "undo": {
574
+ const stateToRestore = state.undoStack[state.undoStack.length - 1];
575
+ if (!stateToRestore) return state;
576
+ const currentSnapshot = {
577
+ lines: [...state.lines],
578
+ cursorRow: state.cursorRow,
579
+ cursorCol: state.cursorCol
580
+ };
581
+ return {
582
+ ...state,
583
+ ...stateToRestore,
584
+ undoStack: state.undoStack.slice(0, -1),
585
+ redoStack: [...state.redoStack, currentSnapshot]
586
+ };
587
+ }
588
+ case "redo": {
589
+ const stateToRestore = state.redoStack[state.redoStack.length - 1];
590
+ if (!stateToRestore) return state;
591
+ const currentSnapshot = {
592
+ lines: [...state.lines],
593
+ cursorRow: state.cursorRow,
594
+ cursorCol: state.cursorCol
595
+ };
596
+ return {
597
+ ...state,
598
+ ...stateToRestore,
599
+ redoStack: state.redoStack.slice(0, -1),
600
+ undoStack: [...state.undoStack, currentSnapshot]
601
+ };
602
+ }
603
+ case "replace_range": {
604
+ const { startRow, startCol, endRow, endCol, text } = action.payload;
605
+ return replaceRangeInternal(pushUndoLocal(state), startRow, startCol, endRow, endCol, text);
606
+ }
607
+ case "move_to_offset": {
608
+ const { offset } = action.payload;
609
+ const [newRow, newCol] = offsetToLogicalPos(state.lines.join("\n"), offset);
610
+ return {
611
+ ...state,
612
+ cursorRow: newRow,
613
+ cursorCol: newCol,
614
+ preferredCol: null
615
+ };
616
+ }
617
+ case "create_undo_snapshot": return pushUndoLocal(state);
618
+ default: {
619
+ const exhaustiveCheck = action;
620
+ console.error(`Unknown action encountered: ${exhaustiveCheck}`);
621
+ return state;
622
+ }
623
+ }
624
+ }
625
+ function textBufferReducer(state, action) {
626
+ const newState = textBufferReducerLogic(state, action);
627
+ if (newState.lines !== state.lines || newState.viewportWidth !== state.viewportWidth) return {
628
+ ...newState,
629
+ visualLayout: calculateLayout(newState.lines, newState.viewportWidth)
630
+ };
631
+ return newState;
632
+ }
633
+ function useTextBuffer({ initialText = "", initialCursorOffset = 0, viewport, onChange, isValidPath, shellModeActive = false }) {
634
+ const [state, dispatch] = useReducer(textBufferReducer, useMemo(() => {
635
+ const lines$1 = initialText.split("\n");
636
+ const [initialCursorRow, initialCursorCol] = calculateInitialCursorPosition(lines$1.length === 0 ? [""] : lines$1, initialCursorOffset);
637
+ const visualLayout$1 = calculateLayout(lines$1.length === 0 ? [""] : lines$1, viewport.width);
638
+ return {
639
+ lines: lines$1.length === 0 ? [""] : lines$1,
640
+ cursorRow: initialCursorRow,
641
+ cursorCol: initialCursorCol,
642
+ preferredCol: null,
643
+ undoStack: [],
644
+ redoStack: [],
645
+ clipboard: null,
646
+ selectionAnchor: null,
647
+ viewportWidth: viewport.width,
648
+ viewportHeight: viewport.height,
649
+ visualLayout: visualLayout$1
650
+ };
651
+ }, [
652
+ initialText,
653
+ initialCursorOffset,
654
+ viewport.width,
655
+ viewport.height
656
+ ]));
657
+ const { lines, cursorRow, cursorCol, preferredCol, selectionAnchor, visualLayout } = state;
658
+ const text = useMemo(() => lines.join("\n"), [lines]);
659
+ const visualCursor = useMemo(() => calculateVisualCursorFromLayout(visualLayout, [cursorRow, cursorCol]), [
660
+ visualLayout,
661
+ cursorRow,
662
+ cursorCol
663
+ ]);
664
+ const { visualLines, visualToLogicalMap } = visualLayout;
665
+ const [visualScrollRow, setVisualScrollRow] = useState(0);
666
+ useEffect(() => {
667
+ if (onChange) onChange(text);
668
+ }, [text, onChange]);
669
+ useEffect(() => {
670
+ dispatch({
671
+ type: "set_viewport",
672
+ payload: {
673
+ width: viewport.width,
674
+ height: viewport.height
675
+ }
676
+ });
677
+ }, [viewport.width, viewport.height]);
678
+ useEffect(() => {
679
+ const { height } = viewport;
680
+ const totalVisualLines = visualLines.length;
681
+ const maxScrollStart = Math.max(0, totalVisualLines - height);
682
+ let newVisualScrollRow = visualScrollRow;
683
+ if (visualCursor[0] < visualScrollRow) newVisualScrollRow = visualCursor[0];
684
+ else if (visualCursor[0] >= visualScrollRow + height) newVisualScrollRow = visualCursor[0] - height + 1;
685
+ newVisualScrollRow = clamp(newVisualScrollRow, 0, maxScrollStart);
686
+ if (newVisualScrollRow !== visualScrollRow) setVisualScrollRow(newVisualScrollRow);
687
+ }, [
688
+ visualCursor,
689
+ visualScrollRow,
690
+ viewport,
691
+ visualLines.length
692
+ ]);
693
+ const insert = useCallback((ch, { paste = false } = {}) => {
694
+ if (/[\n\r]/.test(ch)) {
695
+ dispatch({
696
+ type: "insert",
697
+ payload: ch
698
+ });
699
+ return;
700
+ }
701
+ if (ch.length >= 3 && !shellModeActive && paste) {
702
+ let potentialPath = ch.trim();
703
+ const quoteMatch = potentialPath.match(/^'(.*)'$/);
704
+ if (quoteMatch) potentialPath = quoteMatch[1];
705
+ potentialPath = potentialPath.trim();
706
+ if (isValidPath(potentialPath)) ch = `@${potentialPath} `;
707
+ }
708
+ let currentText = "";
709
+ for (const char of toCodePoints(ch)) if (char.codePointAt(0) === 127) {
710
+ if (currentText.length > 0) {
711
+ dispatch({
712
+ type: "insert",
713
+ payload: currentText
714
+ });
715
+ currentText = "";
716
+ }
717
+ dispatch({ type: "backspace" });
718
+ } else currentText += char;
719
+ if (currentText.length > 0) dispatch({
720
+ type: "insert",
721
+ payload: currentText
722
+ });
723
+ }, [isValidPath, shellModeActive]);
724
+ const newline = useCallback(() => {
725
+ dispatch({
726
+ type: "insert",
727
+ payload: "\n"
728
+ });
729
+ }, []);
730
+ const backspace = useCallback(() => {
731
+ dispatch({ type: "backspace" });
732
+ }, []);
733
+ const del = useCallback(() => {
734
+ dispatch({ type: "delete" });
735
+ }, []);
736
+ const move = useCallback((dir) => {
737
+ dispatch({
738
+ type: "move",
739
+ payload: { dir }
740
+ });
741
+ }, [dispatch]);
742
+ const undo = useCallback(() => {
743
+ dispatch({ type: "undo" });
744
+ }, []);
745
+ const redo = useCallback(() => {
746
+ dispatch({ type: "redo" });
747
+ }, []);
748
+ const setText = useCallback((newText) => {
749
+ dispatch({
750
+ type: "set_text",
751
+ payload: newText
752
+ });
753
+ }, []);
754
+ const deleteWordLeft = useCallback(() => {
755
+ dispatch({ type: "delete_word_left" });
756
+ }, []);
757
+ const deleteWordRight = useCallback(() => {
758
+ dispatch({ type: "delete_word_right" });
759
+ }, []);
760
+ const killLineRight = useCallback(() => {
761
+ dispatch({ type: "kill_line_right" });
762
+ }, []);
763
+ const killLineLeft = useCallback(() => {
764
+ dispatch({ type: "kill_line_left" });
765
+ }, []);
766
+ const handleInput = useCallback((key) => {
767
+ const { sequence: input } = key;
768
+ if (key.paste) {
769
+ insert(input, { paste: key.paste });
770
+ return;
771
+ }
772
+ if (key.name === "return" || input === "\r" || input === "\n" || input === "\\\r") newline();
773
+ else if (key.name === "left" && !key.meta && !key.ctrl) move("left");
774
+ else if (key.ctrl && key.name === "b") move("left");
775
+ else if (key.name === "right" && !key.meta && !key.ctrl) move("right");
776
+ else if (key.ctrl && key.name === "f") move("right");
777
+ else if (key.name === "up") move("up");
778
+ else if (key.name === "down") move("down");
779
+ else if ((key.ctrl || key.meta) && key.name === "left") move("wordLeft");
780
+ else if (key.meta && key.name === "b") move("wordLeft");
781
+ else if ((key.ctrl || key.meta) && key.name === "right") move("wordRight");
782
+ else if (key.meta && key.name === "f") move("wordRight");
783
+ else if (key.name === "home") move("home");
784
+ else if (key.ctrl && key.name === "a") move("home");
785
+ else if (key.name === "end") move("end");
786
+ else if (key.ctrl && key.name === "e") move("end");
787
+ else if (key.ctrl && key.name === "w") deleteWordLeft();
788
+ else if ((key.meta || key.ctrl) && (key.name === "backspace" || input === "")) deleteWordLeft();
789
+ else if ((key.meta || key.ctrl) && key.name === "delete") deleteWordRight();
790
+ else if (key.name === "backspace" || input === "" || key.ctrl && key.name === "h") backspace();
791
+ else if (key.name === "delete" || key.ctrl && key.name === "d") del();
792
+ else if (key.ctrl && !key.shift && key.name === "z") undo();
793
+ else if (key.ctrl && key.shift && key.name === "z") redo();
794
+ else if (input && !key.ctrl && !key.meta) insert(input, { paste: key.paste });
795
+ }, [
796
+ newline,
797
+ move,
798
+ deleteWordLeft,
799
+ deleteWordRight,
800
+ backspace,
801
+ del,
802
+ insert,
803
+ undo,
804
+ redo
805
+ ]);
806
+ const renderedVisualLines = useMemo(() => visualLines.slice(visualScrollRow, visualScrollRow + viewport.height), [
807
+ visualLines,
808
+ visualScrollRow,
809
+ viewport.height
810
+ ]);
811
+ return useMemo(() => ({
812
+ lines,
813
+ text,
814
+ cursor: [cursorRow, cursorCol],
815
+ preferredCol,
816
+ selectionAnchor,
817
+ allVisualLines: visualLines,
818
+ viewportVisualLines: renderedVisualLines,
819
+ visualCursor,
820
+ visualScrollRow,
821
+ visualToLogicalMap,
822
+ setText,
823
+ insert,
824
+ newline,
825
+ backspace,
826
+ del,
827
+ move,
828
+ undo,
829
+ redo,
830
+ deleteWordLeft,
831
+ deleteWordRight,
832
+ killLineRight,
833
+ killLineLeft,
834
+ handleInput
835
+ }), [
836
+ lines,
837
+ text,
838
+ cursorRow,
839
+ cursorCol,
840
+ preferredCol,
841
+ selectionAnchor,
842
+ visualLines,
843
+ renderedVisualLines,
844
+ visualCursor,
845
+ visualScrollRow,
846
+ setText,
847
+ insert,
848
+ newline,
849
+ backspace,
850
+ del,
851
+ move,
852
+ undo,
853
+ redo,
854
+ deleteWordLeft,
855
+ deleteWordRight,
856
+ killLineRight,
857
+ killLineLeft,
858
+ handleInput,
859
+ visualToLogicalMap
860
+ ]);
861
+ }
862
+
863
+ //#endregion
864
+ export { useTextBuffer };
865
+ //# sourceMappingURL=text-buffer.mjs.map