@machina.ai/cell-cli 1.0.13-rc9 → 1.0.21-rc1

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 (579) hide show
  1. package/dist/package.json +11 -7
  2. package/dist/src/commands/mcp/add.d.ts +7 -0
  3. package/dist/src/commands/mcp/add.js +166 -0
  4. package/dist/src/commands/mcp/add.js.map +1 -0
  5. package/dist/src/commands/mcp/list.d.ts +8 -0
  6. package/dist/src/commands/mcp/list.js +110 -0
  7. package/dist/src/commands/mcp/list.js.map +1 -0
  8. package/dist/src/commands/mcp/remove.d.ts +7 -0
  9. package/dist/src/commands/mcp/remove.js +44 -0
  10. package/dist/src/commands/mcp/remove.js.map +1 -0
  11. package/dist/src/commands/mcp.d.ts +7 -0
  12. package/dist/src/commands/mcp.js +23 -0
  13. package/dist/src/commands/mcp.js.map +1 -0
  14. package/dist/src/config/auth.test.d.ts +6 -0
  15. package/dist/src/config/auth.test.js +28 -0
  16. package/dist/src/config/auth.test.js.map +1 -0
  17. package/dist/src/config/config.d.ts +6 -3
  18. package/dist/src/config/config.js +177 -90
  19. package/dist/src/config/config.js.map +1 -1
  20. package/dist/src/config/extension.d.ts +1 -0
  21. package/dist/src/config/extension.js +4 -0
  22. package/dist/src/config/extension.js.map +1 -1
  23. package/dist/src/config/keyBindings.d.ts +66 -0
  24. package/dist/src/config/keyBindings.js +141 -0
  25. package/dist/src/config/keyBindings.js.map +1 -0
  26. package/dist/src/config/keyBindings.test.d.ts +6 -0
  27. package/dist/src/config/keyBindings.test.js +51 -0
  28. package/dist/src/config/keyBindings.test.js.map +1 -0
  29. package/dist/src/config/sandboxConfig.js +3 -3
  30. package/dist/src/config/sandboxConfig.js.map +1 -1
  31. package/dist/src/config/settings.d.ts +6 -41
  32. package/dist/src/config/settings.js +137 -52
  33. package/dist/src/config/settings.js.map +1 -1
  34. package/dist/src/config/settingsSchema.d.ts +533 -0
  35. package/dist/src/config/settingsSchema.js +507 -0
  36. package/dist/src/config/settingsSchema.js.map +1 -0
  37. package/dist/src/config/settingsSchema.test.d.ts +6 -0
  38. package/dist/src/config/settingsSchema.test.js +195 -0
  39. package/dist/src/config/settingsSchema.test.js.map +1 -0
  40. package/dist/src/config/trustedFolders.d.ts +37 -0
  41. package/dist/src/config/trustedFolders.js +118 -0
  42. package/dist/src/config/trustedFolders.js.map +1 -0
  43. package/dist/src/config/trustedFolders.test.d.ts +6 -0
  44. package/dist/src/config/trustedFolders.test.js +160 -0
  45. package/dist/src/config/trustedFolders.test.js.map +1 -0
  46. package/dist/src/gemini.d.ts +3 -0
  47. package/dist/src/gemini.js +106 -68
  48. package/dist/src/gemini.js.map +1 -1
  49. package/dist/src/gemini.test.d.ts +6 -0
  50. package/dist/src/gemini.test.js +193 -0
  51. package/dist/src/gemini.test.js.map +1 -0
  52. package/dist/src/generated/git-commit.d.ts +2 -1
  53. package/dist/src/generated/git-commit.js +3 -2
  54. package/dist/src/generated/git-commit.js.map +1 -1
  55. package/dist/src/nonInteractiveCli.js +35 -55
  56. package/dist/src/nonInteractiveCli.js.map +1 -1
  57. package/dist/src/patches/is-in-ci.d.ts +7 -0
  58. package/dist/src/patches/is-in-ci.js +15 -0
  59. package/dist/src/patches/is-in-ci.js.map +1 -0
  60. package/dist/src/services/BuiltinCommandLoader.js +12 -0
  61. package/dist/src/services/BuiltinCommandLoader.js.map +1 -1
  62. package/dist/src/services/BuiltinCommandLoader.test.d.ts +6 -0
  63. package/dist/src/services/BuiltinCommandLoader.test.js +108 -0
  64. package/dist/src/services/BuiltinCommandLoader.test.js.map +1 -0
  65. package/dist/src/services/CommandService.d.ts +8 -4
  66. package/dist/src/services/CommandService.js +24 -8
  67. package/dist/src/services/CommandService.js.map +1 -1
  68. package/dist/src/services/CommandService.test.d.ts +6 -0
  69. package/dist/src/services/CommandService.test.js +232 -0
  70. package/dist/src/services/CommandService.test.js.map +1 -0
  71. package/dist/src/services/FileCommandLoader.d.ts +15 -3
  72. package/dist/src/services/FileCommandLoader.js +115 -38
  73. package/dist/src/services/FileCommandLoader.js.map +1 -1
  74. package/dist/src/services/McpPromptLoader.d.ts +25 -0
  75. package/dist/src/services/McpPromptLoader.js +192 -0
  76. package/dist/src/services/McpPromptLoader.js.map +1 -0
  77. package/dist/src/services/prompt-processors/argumentProcessor.d.ts +16 -0
  78. package/dist/src/services/prompt-processors/argumentProcessor.js +20 -0
  79. package/dist/src/services/prompt-processors/argumentProcessor.js.map +1 -0
  80. package/dist/src/services/prompt-processors/shellProcessor.d.ts +35 -0
  81. package/dist/src/services/prompt-processors/shellProcessor.js +170 -0
  82. package/dist/src/services/prompt-processors/shellProcessor.js.map +1 -0
  83. package/dist/src/services/prompt-processors/types.d.ts +40 -0
  84. package/dist/src/services/prompt-processors/types.js +16 -0
  85. package/dist/src/services/prompt-processors/types.js.map +1 -0
  86. package/dist/src/test-utils/customMatchers.d.ts +14 -0
  87. package/dist/src/test-utils/customMatchers.js +46 -0
  88. package/dist/src/test-utils/customMatchers.js.map +1 -0
  89. package/dist/src/test-utils/mockCommandContext.d.ts +18 -0
  90. package/dist/src/test-utils/mockCommandContext.js +86 -0
  91. package/dist/src/test-utils/mockCommandContext.js.map +1 -0
  92. package/dist/src/test-utils/mockCommandContext.test.d.ts +6 -0
  93. package/dist/src/test-utils/mockCommandContext.test.js +51 -0
  94. package/dist/src/test-utils/mockCommandContext.test.js.map +1 -0
  95. package/dist/src/test-utils/render.d.ts +8 -0
  96. package/dist/src/test-utils/render.js +10 -0
  97. package/dist/src/test-utils/render.js.map +1 -0
  98. package/dist/src/ui/App.js +229 -67
  99. package/dist/src/ui/App.js.map +1 -1
  100. package/dist/src/ui/IdeIntegrationNudge.d.ts +16 -0
  101. package/dist/src/ui/IdeIntegrationNudge.js +52 -0
  102. package/dist/src/ui/IdeIntegrationNudge.js.map +1 -0
  103. package/dist/src/ui/colors.js +6 -0
  104. package/dist/src/ui/colors.js.map +1 -1
  105. package/dist/src/ui/commands/aboutCommand.js +9 -5
  106. package/dist/src/ui/commands/aboutCommand.js.map +1 -1
  107. package/dist/src/ui/commands/bugCommand.js +13 -5
  108. package/dist/src/ui/commands/bugCommand.js.map +1 -1
  109. package/dist/src/ui/commands/chatCommand.js +66 -6
  110. package/dist/src/ui/commands/chatCommand.js.map +1 -1
  111. package/dist/src/ui/commands/directoryCommand.d.ts +8 -0
  112. package/dist/src/ui/commands/directoryCommand.js +134 -0
  113. package/dist/src/ui/commands/directoryCommand.js.map +1 -0
  114. package/dist/src/ui/commands/docsCommand.js +1 -1
  115. package/dist/src/ui/commands/docsCommand.js.map +1 -1
  116. package/dist/src/ui/commands/helpCommand.js +7 -6
  117. package/dist/src/ui/commands/helpCommand.js.map +1 -1
  118. package/dist/src/ui/commands/ideCommand.js +179 -109
  119. package/dist/src/ui/commands/ideCommand.js.map +1 -1
  120. package/dist/src/ui/commands/initCommand.d.ts +7 -0
  121. package/dist/src/ui/commands/initCommand.js +76 -0
  122. package/dist/src/ui/commands/initCommand.js.map +1 -0
  123. package/dist/src/ui/commands/mcpCommand.js +244 -26
  124. package/dist/src/ui/commands/mcpCommand.js.map +1 -1
  125. package/dist/src/ui/commands/memoryCommand.js +9 -4
  126. package/dist/src/ui/commands/memoryCommand.js.map +1 -1
  127. package/dist/src/ui/commands/settingsCommand.d.ts +7 -0
  128. package/dist/src/ui/commands/settingsCommand.js +16 -0
  129. package/dist/src/ui/commands/settingsCommand.js.map +1 -0
  130. package/dist/src/ui/commands/setupGithubCommand.d.ts +7 -0
  131. package/dist/src/ui/commands/setupGithubCommand.js +115 -0
  132. package/dist/src/ui/commands/setupGithubCommand.js.map +1 -0
  133. package/dist/src/ui/commands/setupGithubCommand.test.d.ts +6 -0
  134. package/dist/src/ui/commands/setupGithubCommand.test.js +74 -0
  135. package/dist/src/ui/commands/setupGithubCommand.test.js.map +1 -0
  136. package/dist/src/ui/commands/terminalSetupCommand.d.ts +13 -0
  137. package/dist/src/ui/commands/terminalSetupCommand.js +41 -0
  138. package/dist/src/ui/commands/terminalSetupCommand.js.map +1 -0
  139. package/dist/src/ui/commands/types.d.ts +42 -3
  140. package/dist/src/ui/commands/types.js +1 -0
  141. package/dist/src/ui/commands/types.js.map +1 -1
  142. package/dist/src/ui/commands/vimCommand.d.ts +7 -0
  143. package/dist/src/ui/commands/vimCommand.js +23 -0
  144. package/dist/src/ui/commands/vimCommand.js.map +1 -0
  145. package/dist/src/ui/components/AboutBox.d.ts +1 -0
  146. package/dist/src/ui/components/AboutBox.js +1 -1
  147. package/dist/src/ui/components/AboutBox.js.map +1 -1
  148. package/dist/src/ui/components/AsciiArt.d.ts +3 -2
  149. package/dist/src/ui/components/AsciiArt.js +23 -12
  150. package/dist/src/ui/components/AsciiArt.js.map +1 -1
  151. package/dist/src/ui/components/AuthDialog.js +12 -6
  152. package/dist/src/ui/components/AuthDialog.js.map +1 -1
  153. package/dist/src/ui/components/AuthDialog.test.d.ts +6 -0
  154. package/dist/src/ui/components/AuthDialog.test.js +114 -0
  155. package/dist/src/ui/components/AuthDialog.test.js.map +1 -0
  156. package/dist/src/ui/components/AuthInProgress.js +5 -4
  157. package/dist/src/ui/components/AuthInProgress.js.map +1 -1
  158. package/dist/src/ui/components/ContextSummaryDisplay.d.ts +2 -2
  159. package/dist/src/ui/components/ContextSummaryDisplay.js +31 -34
  160. package/dist/src/ui/components/ContextSummaryDisplay.js.map +1 -1
  161. package/dist/src/ui/components/ContextUsageDisplay.d.ts +9 -0
  162. package/dist/src/ui/components/ContextUsageDisplay.js +14 -0
  163. package/dist/src/ui/components/ContextUsageDisplay.js.map +1 -0
  164. package/dist/src/ui/components/DebugProfiler.d.ts +6 -0
  165. package/dist/src/ui/components/DebugProfiler.js +27 -0
  166. package/dist/src/ui/components/DebugProfiler.js.map +1 -0
  167. package/dist/src/ui/components/EditorSettingsDialog.js +6 -5
  168. package/dist/src/ui/components/EditorSettingsDialog.js.map +1 -1
  169. package/dist/src/ui/components/FolderTrustDialog.d.ts +16 -0
  170. package/dist/src/ui/components/FolderTrustDialog.js +39 -0
  171. package/dist/src/ui/components/FolderTrustDialog.js.map +1 -0
  172. package/dist/src/ui/components/FolderTrustDialog.test.d.ts +6 -0
  173. package/dist/src/ui/components/FolderTrustDialog.test.js +26 -0
  174. package/dist/src/ui/components/FolderTrustDialog.test.js.map +1 -0
  175. package/dist/src/ui/components/Footer.d.ts +2 -0
  176. package/dist/src/ui/components/Footer.js +18 -7
  177. package/dist/src/ui/components/Footer.js.map +1 -1
  178. package/dist/src/ui/components/Header.d.ts +0 -1
  179. package/dist/src/ui/components/Header.js +13 -5
  180. package/dist/src/ui/components/Header.js.map +1 -1
  181. package/dist/src/ui/components/Header.test.d.ts +6 -0
  182. package/dist/src/ui/components/Header.test.js +44 -0
  183. package/dist/src/ui/components/Header.test.js.map +1 -0
  184. package/dist/src/ui/components/Help.js +2 -2
  185. package/dist/src/ui/components/Help.js.map +1 -1
  186. package/dist/src/ui/components/HistoryItemDisplay.d.ts +2 -0
  187. package/dist/src/ui/components/HistoryItemDisplay.js +2 -1
  188. package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
  189. package/dist/src/ui/components/HistoryItemDisplay.test.d.ts +6 -0
  190. package/dist/src/ui/components/HistoryItemDisplay.test.js +91 -0
  191. package/dist/src/ui/components/HistoryItemDisplay.test.js.map +1 -0
  192. package/dist/src/ui/components/InputPrompt.d.ts +3 -0
  193. package/dist/src/ui/components/InputPrompt.js +179 -126
  194. package/dist/src/ui/components/InputPrompt.js.map +1 -1
  195. package/dist/src/ui/components/LoadingIndicator.js +10 -5
  196. package/dist/src/ui/components/LoadingIndicator.js.map +1 -1
  197. package/dist/src/ui/components/LoadingIndicator.test.d.ts +6 -0
  198. package/dist/src/ui/components/LoadingIndicator.test.js +190 -0
  199. package/dist/src/ui/components/LoadingIndicator.test.js.map +1 -0
  200. package/dist/src/ui/components/PrepareLabel.d.ts +15 -0
  201. package/dist/src/ui/components/PrepareLabel.js +16 -0
  202. package/dist/src/ui/components/PrepareLabel.js.map +1 -0
  203. package/dist/src/ui/components/SettingsDialog.d.ts +14 -0
  204. package/dist/src/ui/components/SettingsDialog.js +519 -0
  205. package/dist/src/ui/components/SettingsDialog.js.map +1 -0
  206. package/dist/src/ui/components/SettingsDialog.test.d.ts +6 -0
  207. package/dist/src/ui/components/SettingsDialog.test.js +568 -0
  208. package/dist/src/ui/components/SettingsDialog.test.js.map +1 -0
  209. package/dist/src/ui/components/ShellConfirmationDialog.d.ts +15 -0
  210. package/dist/src/ui/components/ShellConfirmationDialog.js +46 -0
  211. package/dist/src/ui/components/ShellConfirmationDialog.js.map +1 -0
  212. package/dist/src/ui/components/ShellConfirmationDialog.test.d.ts +6 -0
  213. package/dist/src/ui/components/ShellConfirmationDialog.test.js +40 -0
  214. package/dist/src/ui/components/ShellConfirmationDialog.test.js.map +1 -0
  215. package/dist/src/ui/components/StatsDisplay.js +8 -7
  216. package/dist/src/ui/components/StatsDisplay.js.map +1 -1
  217. package/dist/src/ui/components/SuggestionsDisplay.d.ts +1 -0
  218. package/dist/src/ui/components/SuggestionsDisplay.js +3 -3
  219. package/dist/src/ui/components/SuggestionsDisplay.js.map +1 -1
  220. package/dist/src/ui/components/ThemeDialog.js +20 -25
  221. package/dist/src/ui/components/ThemeDialog.js.map +1 -1
  222. package/dist/src/ui/components/Tips.js +1 -1
  223. package/dist/src/ui/components/Tips.js.map +1 -1
  224. package/dist/src/ui/components/messages/DiffRenderer.js +21 -11
  225. package/dist/src/ui/components/messages/DiffRenderer.js.map +1 -1
  226. package/dist/src/ui/components/messages/DiffRenderer.test.d.ts +6 -0
  227. package/dist/src/ui/components/messages/DiffRenderer.test.js +239 -0
  228. package/dist/src/ui/components/messages/DiffRenderer.test.js.map +1 -0
  229. package/dist/src/ui/components/messages/InfoMessage.js +2 -1
  230. package/dist/src/ui/components/messages/InfoMessage.js.map +1 -1
  231. package/dist/src/ui/components/messages/ToolConfirmationMessage.js +52 -18
  232. package/dist/src/ui/components/messages/ToolConfirmationMessage.js.map +1 -1
  233. package/dist/src/ui/components/messages/ToolConfirmationMessage.test.d.ts +6 -0
  234. package/dist/src/ui/components/messages/ToolConfirmationMessage.test.js +37 -0
  235. package/dist/src/ui/components/messages/ToolConfirmationMessage.test.js.map +1 -0
  236. package/dist/src/ui/components/messages/ToolMessage.test.d.ts +6 -0
  237. package/dist/src/ui/components/messages/ToolMessage.test.js +118 -0
  238. package/dist/src/ui/components/messages/ToolMessage.test.js.map +1 -0
  239. package/dist/src/ui/components/messages/UserMessage.js +4 -1
  240. package/dist/src/ui/components/messages/UserMessage.js.map +1 -1
  241. package/dist/src/ui/components/shared/MaxSizedBox.js +1 -1
  242. package/dist/src/ui/components/shared/MaxSizedBox.js.map +1 -1
  243. package/dist/src/ui/components/shared/MaxSizedBox.test.d.ts +6 -0
  244. package/dist/src/ui/components/shared/MaxSizedBox.test.js +154 -0
  245. package/dist/src/ui/components/shared/MaxSizedBox.test.js.map +1 -0
  246. package/dist/src/ui/components/shared/RadioButtonSelect.js +11 -9
  247. package/dist/src/ui/components/shared/RadioButtonSelect.js.map +1 -1
  248. package/dist/src/ui/components/shared/RadioButtonSelect.test.d.ts +6 -0
  249. package/dist/src/ui/components/shared/RadioButtonSelect.test.js +111 -0
  250. package/dist/src/ui/components/shared/RadioButtonSelect.test.js.map +1 -0
  251. package/dist/src/ui/components/shared/text-buffer.d.ts +286 -3
  252. package/dist/src/ui/components/shared/text-buffer.js +612 -89
  253. package/dist/src/ui/components/shared/text-buffer.js.map +1 -1
  254. package/dist/src/ui/components/shared/vim-buffer-actions.d.ts +72 -0
  255. package/dist/src/ui/components/shared/vim-buffer-actions.js +552 -0
  256. package/dist/src/ui/components/shared/vim-buffer-actions.js.map +1 -0
  257. package/dist/src/ui/contexts/KeypressContext.d.ts +30 -0
  258. package/dist/src/ui/contexts/KeypressContext.js +309 -0
  259. package/dist/src/ui/contexts/KeypressContext.js.map +1 -0
  260. package/dist/src/ui/contexts/KeypressContext.test.d.ts +6 -0
  261. package/dist/src/ui/contexts/KeypressContext.test.js +219 -0
  262. package/dist/src/ui/contexts/KeypressContext.test.js.map +1 -0
  263. package/dist/src/ui/contexts/SessionContext.d.ts +3 -0
  264. package/dist/src/ui/contexts/SessionContext.js +2 -1
  265. package/dist/src/ui/contexts/SessionContext.js.map +1 -1
  266. package/dist/src/ui/contexts/SettingsContext.d.ts +9 -0
  267. package/dist/src/ui/contexts/SettingsContext.js +15 -0
  268. package/dist/src/ui/contexts/SettingsContext.js.map +1 -0
  269. package/dist/src/ui/contexts/VimModeContext.d.ts +19 -0
  270. package/dist/src/ui/contexts/VimModeContext.js +48 -0
  271. package/dist/src/ui/contexts/VimModeContext.js.map +1 -0
  272. package/dist/src/ui/editors/editorSettingsManager.js +6 -13
  273. package/dist/src/ui/editors/editorSettingsManager.js.map +1 -1
  274. package/dist/src/ui/hooks/atCommandProcessor.js +82 -62
  275. package/dist/src/ui/hooks/atCommandProcessor.js.map +1 -1
  276. package/dist/src/ui/hooks/atCommandProcessor.test.d.ts +6 -0
  277. package/dist/src/ui/hooks/atCommandProcessor.test.js +809 -0
  278. package/dist/src/ui/hooks/atCommandProcessor.test.js.map +1 -0
  279. package/dist/src/ui/hooks/shellCommandProcessor.d.ts +1 -0
  280. package/dist/src/ui/hooks/shellCommandProcessor.js +139 -196
  281. package/dist/src/ui/hooks/shellCommandProcessor.js.map +1 -1
  282. package/dist/src/ui/hooks/shellCommandProcessor.test.d.ts +6 -0
  283. package/dist/src/ui/hooks/shellCommandProcessor.test.js +328 -0
  284. package/dist/src/ui/hooks/shellCommandProcessor.test.js.map +1 -0
  285. package/dist/src/ui/hooks/slashCommandProcessor.d.ts +11 -3
  286. package/dist/src/ui/hooks/slashCommandProcessor.js +237 -90
  287. package/dist/src/ui/hooks/slashCommandProcessor.js.map +1 -1
  288. package/dist/src/ui/hooks/useAtCompletion.d.ts +23 -0
  289. package/dist/src/ui/hooks/useAtCompletion.js +178 -0
  290. package/dist/src/ui/hooks/useAtCompletion.js.map +1 -0
  291. package/dist/src/ui/hooks/useAutoAcceptIndicator.js +5 -5
  292. package/dist/src/ui/hooks/useAutoAcceptIndicator.js.map +1 -1
  293. package/dist/src/ui/hooks/useAutoAcceptIndicator.test.d.ts +6 -0
  294. package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js +191 -0
  295. package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js.map +1 -0
  296. package/dist/src/ui/hooks/useCommandCompletion.d.ts +29 -0
  297. package/dist/src/ui/hooks/useCommandCompletion.js +165 -0
  298. package/dist/src/ui/hooks/useCommandCompletion.js.map +1 -0
  299. package/dist/src/ui/hooks/useCompletion.d.ts +5 -3
  300. package/dist/src/ui/hooks/useCompletion.js +7 -312
  301. package/dist/src/ui/hooks/useCompletion.js.map +1 -1
  302. package/dist/src/ui/hooks/useConsoleMessages.js +53 -37
  303. package/dist/src/ui/hooks/useConsoleMessages.js.map +1 -1
  304. package/dist/src/ui/hooks/useEditorSettings.test.d.ts +6 -0
  305. package/dist/src/ui/hooks/useEditorSettings.test.js +164 -0
  306. package/dist/src/ui/hooks/useEditorSettings.test.js.map +1 -0
  307. package/dist/src/ui/hooks/useFocus.d.ts +4 -0
  308. package/dist/src/ui/hooks/useFocus.js +4 -4
  309. package/dist/src/ui/hooks/useFocus.js.map +1 -1
  310. package/dist/src/ui/hooks/useFolderTrust.d.ts +12 -0
  311. package/dist/src/ui/hooks/useFolderTrust.js +55 -0
  312. package/dist/src/ui/hooks/useFolderTrust.js.map +1 -0
  313. package/dist/src/ui/hooks/useGeminiStream.d.ts +2 -1
  314. package/dist/src/ui/hooks/useGeminiStream.js +40 -26
  315. package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
  316. package/dist/src/ui/hooks/useGitBranchName.test.d.ts +6 -0
  317. package/dist/src/ui/hooks/useGitBranchName.test.js +175 -0
  318. package/dist/src/ui/hooks/useGitBranchName.test.js.map +1 -0
  319. package/dist/src/ui/hooks/useHistoryManager.test.d.ts +6 -0
  320. package/dist/src/ui/hooks/useHistoryManager.test.js +171 -0
  321. package/dist/src/ui/hooks/useHistoryManager.test.js.map +1 -0
  322. package/dist/src/ui/hooks/useInputHistory.d.ts +1 -1
  323. package/dist/src/ui/hooks/useInputHistory.test.d.ts +6 -0
  324. package/dist/src/ui/hooks/useInputHistory.test.js +207 -0
  325. package/dist/src/ui/hooks/useInputHistory.test.js.map +1 -0
  326. package/dist/src/ui/hooks/useKeypress.d.ts +4 -16
  327. package/dist/src/ui/hooks/useKeypress.js +8 -137
  328. package/dist/src/ui/hooks/useKeypress.js.map +1 -1
  329. package/dist/src/ui/hooks/useKittyKeyboardProtocol.d.ts +15 -0
  330. package/dist/src/ui/hooks/useKittyKeyboardProtocol.js +20 -0
  331. package/dist/src/ui/hooks/useKittyKeyboardProtocol.js.map +1 -0
  332. package/dist/src/ui/hooks/useLoadingIndicator.test.d.ts +6 -0
  333. package/dist/src/ui/hooks/useLoadingIndicator.test.js +91 -0
  334. package/dist/src/ui/hooks/useLoadingIndicator.test.js.map +1 -0
  335. package/dist/src/ui/hooks/useMessageQueue.d.ts +22 -0
  336. package/dist/src/ui/hooks/useMessageQueue.js +49 -0
  337. package/dist/src/ui/hooks/useMessageQueue.js.map +1 -0
  338. package/dist/src/ui/hooks/useMessageQueue.test.d.ts +6 -0
  339. package/dist/src/ui/hooks/useMessageQueue.test.js +158 -0
  340. package/dist/src/ui/hooks/useMessageQueue.test.js.map +1 -0
  341. package/dist/src/ui/hooks/usePhraseCycler.js +3 -5
  342. package/dist/src/ui/hooks/usePhraseCycler.js.map +1 -1
  343. package/dist/src/ui/hooks/usePrivacySettings.js +6 -2
  344. package/dist/src/ui/hooks/usePrivacySettings.js.map +1 -1
  345. package/dist/src/ui/hooks/usePrivacySettings.test.d.ts +6 -0
  346. package/dist/src/ui/hooks/usePrivacySettings.test.js +154 -0
  347. package/dist/src/ui/hooks/usePrivacySettings.test.js.map +1 -0
  348. package/dist/src/ui/hooks/useReactToolScheduler.d.ts +1 -1
  349. package/dist/src/ui/hooks/useReactToolScheduler.js +18 -17
  350. package/dist/src/ui/hooks/useReactToolScheduler.js.map +1 -1
  351. package/dist/src/ui/hooks/useReverseSearchCompletion.d.ts +19 -0
  352. package/dist/src/ui/hooks/useReverseSearchCompletion.js +56 -0
  353. package/dist/src/ui/hooks/useReverseSearchCompletion.js.map +1 -0
  354. package/dist/src/ui/hooks/useReverseSearchCompletion.test.d.ts +6 -0
  355. package/dist/src/ui/hooks/useReverseSearchCompletion.test.js +163 -0
  356. package/dist/src/ui/hooks/useReverseSearchCompletion.test.js.map +1 -0
  357. package/dist/src/ui/hooks/useSettingsCommand.d.ts +10 -0
  358. package/dist/src/ui/hooks/useSettingsCommand.js +21 -0
  359. package/dist/src/ui/hooks/useSettingsCommand.js.map +1 -0
  360. package/dist/src/ui/hooks/useShellHistory.d.ts +4 -2
  361. package/dist/src/ui/hooks/useShellHistory.js +30 -7
  362. package/dist/src/ui/hooks/useShellHistory.js.map +1 -1
  363. package/dist/src/ui/hooks/useShellHistory.test.d.ts +6 -0
  364. package/dist/src/ui/hooks/useShellHistory.test.js +159 -0
  365. package/dist/src/ui/hooks/useShellHistory.test.js.map +1 -0
  366. package/dist/src/ui/hooks/useSlashCompletion.d.ts +20 -0
  367. package/dist/src/ui/hooks/useSlashCompletion.js +135 -0
  368. package/dist/src/ui/hooks/useSlashCompletion.js.map +1 -0
  369. package/dist/src/ui/hooks/useSlashCompletion.test.d.ts +6 -0
  370. package/dist/src/ui/hooks/useSlashCompletion.test.js +272 -0
  371. package/dist/src/ui/hooks/useSlashCompletion.test.js.map +1 -0
  372. package/dist/src/ui/hooks/useThemeCommand.js +1 -1
  373. package/dist/src/ui/hooks/useThemeCommand.js.map +1 -1
  374. package/dist/src/ui/hooks/useTimer.test.d.ts +6 -0
  375. package/dist/src/ui/hooks/useTimer.test.js +90 -0
  376. package/dist/src/ui/hooks/useTimer.test.js.map +1 -0
  377. package/dist/src/ui/hooks/useToolScheduler.test.d.ts +6 -0
  378. package/dist/src/ui/hooks/useToolScheduler.test.js +846 -0
  379. package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -0
  380. package/dist/src/ui/hooks/vim.d.ts +28 -0
  381. package/dist/src/ui/hooks/vim.js +639 -0
  382. package/dist/src/ui/hooks/vim.js.map +1 -0
  383. package/dist/src/ui/keyMatchers.d.ts +26 -0
  384. package/dist/src/ui/keyMatchers.js +68 -0
  385. package/dist/src/ui/keyMatchers.js.map +1 -0
  386. package/dist/src/ui/keyMatchers.test.d.ts +6 -0
  387. package/dist/src/ui/keyMatchers.test.js +276 -0
  388. package/dist/src/ui/keyMatchers.test.js.map +1 -0
  389. package/dist/src/ui/privacy/CloudFreePrivacyNotice.js +5 -4
  390. package/dist/src/ui/privacy/CloudFreePrivacyNotice.js.map +1 -1
  391. package/dist/src/ui/privacy/CloudPaidPrivacyNotice.js +5 -4
  392. package/dist/src/ui/privacy/CloudPaidPrivacyNotice.js.map +1 -1
  393. package/dist/src/ui/privacy/GeminiPrivacyNotice.js +5 -4
  394. package/dist/src/ui/privacy/GeminiPrivacyNotice.js.map +1 -1
  395. package/dist/src/ui/semantic-colors.d.ts +7 -0
  396. package/dist/src/ui/semantic-colors.js +24 -0
  397. package/dist/src/ui/semantic-colors.js.map +1 -0
  398. package/dist/src/ui/themes/ansi-light.js +4 -1
  399. package/dist/src/ui/themes/ansi-light.js.map +1 -1
  400. package/dist/src/ui/themes/ansi.js +4 -1
  401. package/dist/src/ui/themes/ansi.js.map +1 -1
  402. package/dist/src/ui/themes/atom-one-dark.js +4 -1
  403. package/dist/src/ui/themes/atom-one-dark.js.map +1 -1
  404. package/dist/src/ui/themes/ayu-light.js +5 -2
  405. package/dist/src/ui/themes/ayu-light.js.map +1 -1
  406. package/dist/src/ui/themes/ayu.js +5 -2
  407. package/dist/src/ui/themes/ayu.js.map +1 -1
  408. package/dist/src/ui/themes/color-utils.test.d.ts +6 -0
  409. package/dist/src/ui/themes/color-utils.test.js +197 -0
  410. package/dist/src/ui/themes/color-utils.test.js.map +1 -0
  411. package/dist/src/ui/themes/default-light.js +2 -1
  412. package/dist/src/ui/themes/default-light.js.map +1 -1
  413. package/dist/src/ui/themes/default.js +2 -1
  414. package/dist/src/ui/themes/default.js.map +1 -1
  415. package/dist/src/ui/themes/dracula.js +4 -1
  416. package/dist/src/ui/themes/dracula.js.map +1 -1
  417. package/dist/src/ui/themes/github-dark.js +4 -1
  418. package/dist/src/ui/themes/github-dark.js.map +1 -1
  419. package/dist/src/ui/themes/github-light.js +4 -1
  420. package/dist/src/ui/themes/github-light.js.map +1 -1
  421. package/dist/src/ui/themes/googlecode.js +4 -1
  422. package/dist/src/ui/themes/googlecode.js.map +1 -1
  423. package/dist/src/ui/themes/no-color.js +32 -1
  424. package/dist/src/ui/themes/no-color.js.map +1 -1
  425. package/dist/src/ui/themes/semantic-tokens.d.ts +37 -0
  426. package/dist/src/ui/themes/semantic-tokens.js +94 -0
  427. package/dist/src/ui/themes/semantic-tokens.js.map +1 -0
  428. package/dist/src/ui/themes/shades-of-purple.js +4 -1
  429. package/dist/src/ui/themes/shades-of-purple.js.map +1 -1
  430. package/dist/src/ui/themes/theme-manager.d.ts +6 -0
  431. package/dist/src/ui/themes/theme-manager.js +18 -2
  432. package/dist/src/ui/themes/theme-manager.js.map +1 -1
  433. package/dist/src/ui/themes/theme-manager.test.d.ts +6 -0
  434. package/dist/src/ui/themes/theme-manager.test.js +83 -0
  435. package/dist/src/ui/themes/theme-manager.test.js.map +1 -0
  436. package/dist/src/ui/themes/theme.d.ts +48 -2
  437. package/dist/src/ui/themes/theme.js +102 -92
  438. package/dist/src/ui/themes/theme.js.map +1 -1
  439. package/dist/src/ui/themes/xcode.js +4 -1
  440. package/dist/src/ui/themes/xcode.js.map +1 -1
  441. package/dist/src/ui/types.d.ts +13 -2
  442. package/dist/src/ui/types.js +1 -0
  443. package/dist/src/ui/types.js.map +1 -1
  444. package/dist/src/ui/utils/CodeColorizer.d.ts +3 -1
  445. package/dist/src/ui/utils/CodeColorizer.js +22 -9
  446. package/dist/src/ui/utils/CodeColorizer.js.map +1 -1
  447. package/dist/src/ui/utils/ConsolePatcher.d.ts +3 -1
  448. package/dist/src/ui/utils/ConsolePatcher.js +18 -8
  449. package/dist/src/ui/utils/ConsolePatcher.js.map +1 -1
  450. package/dist/src/ui/utils/InlineMarkdownRenderer.js +8 -1
  451. package/dist/src/ui/utils/InlineMarkdownRenderer.js.map +1 -1
  452. package/dist/src/ui/utils/MarkdownDisplay.js +4 -2
  453. package/dist/src/ui/utils/MarkdownDisplay.js.map +1 -1
  454. package/dist/src/ui/utils/MarkdownDisplay.test.d.ts +6 -0
  455. package/dist/src/ui/utils/MarkdownDisplay.test.js +151 -0
  456. package/dist/src/ui/utils/MarkdownDisplay.test.js.map +1 -0
  457. package/dist/src/ui/utils/clipboardUtils.test.d.ts +6 -0
  458. package/dist/src/ui/utils/clipboardUtils.test.js +65 -0
  459. package/dist/src/ui/utils/clipboardUtils.test.js.map +1 -0
  460. package/dist/src/ui/utils/commandUtils.d.ts +1 -0
  461. package/dist/src/ui/utils/commandUtils.js +22 -1
  462. package/dist/src/ui/utils/commandUtils.js.map +1 -1
  463. package/dist/src/ui/utils/commandUtils.test.d.ts +6 -0
  464. package/dist/src/ui/utils/commandUtils.test.js +294 -0
  465. package/dist/src/ui/utils/commandUtils.test.js.map +1 -0
  466. package/dist/src/ui/utils/computeStats.js +3 -1
  467. package/dist/src/ui/utils/computeStats.js.map +1 -1
  468. package/dist/src/ui/utils/displayUtils.test.d.ts +6 -0
  469. package/dist/src/ui/utils/displayUtils.test.js +42 -0
  470. package/dist/src/ui/utils/displayUtils.test.js.map +1 -0
  471. package/dist/src/ui/utils/formatters.test.d.ts +6 -0
  472. package/dist/src/ui/utils/formatters.test.js +56 -0
  473. package/dist/src/ui/utils/formatters.test.js.map +1 -0
  474. package/dist/src/ui/utils/isNarrowWidth.d.ts +6 -0
  475. package/dist/src/ui/utils/isNarrowWidth.js +9 -0
  476. package/dist/src/ui/utils/isNarrowWidth.js.map +1 -0
  477. package/dist/src/ui/utils/kittyProtocolDetector.d.ts +13 -0
  478. package/dist/src/ui/utils/kittyProtocolDetector.js +88 -0
  479. package/dist/src/ui/utils/kittyProtocolDetector.js.map +1 -0
  480. package/dist/src/ui/utils/markdownUtilities.test.d.ts +6 -0
  481. package/dist/src/ui/utils/markdownUtilities.test.js +42 -0
  482. package/dist/src/ui/utils/markdownUtilities.test.js.map +1 -0
  483. package/dist/src/ui/utils/platformConstants.d.ts +43 -0
  484. package/dist/src/ui/utils/platformConstants.js +44 -0
  485. package/dist/src/ui/utils/platformConstants.js.map +1 -0
  486. package/dist/src/ui/utils/terminalSetup.d.ts +30 -0
  487. package/dist/src/ui/utils/terminalSetup.js +281 -0
  488. package/dist/src/ui/utils/terminalSetup.js.map +1 -0
  489. package/dist/src/ui/utils/textUtils.d.ts +0 -8
  490. package/dist/src/ui/utils/textUtils.js +0 -22
  491. package/dist/src/ui/utils/textUtils.js.map +1 -1
  492. package/dist/src/ui/utils/updateCheck.d.ts +7 -1
  493. package/dist/src/ui/utils/updateCheck.js +47 -9
  494. package/dist/src/ui/utils/updateCheck.js.map +1 -1
  495. package/dist/src/ui/utils/updateCheck.test.d.ts +6 -0
  496. package/dist/src/ui/utils/updateCheck.test.js +145 -0
  497. package/dist/src/ui/utils/updateCheck.test.js.map +1 -0
  498. package/dist/src/utils/checks.d.ts +19 -0
  499. package/dist/src/utils/checks.js +24 -0
  500. package/dist/src/utils/checks.js.map +1 -0
  501. package/dist/src/utils/cleanup.d.ts +2 -2
  502. package/dist/src/utils/cleanup.js +2 -2
  503. package/dist/src/utils/cleanup.js.map +1 -1
  504. package/dist/src/utils/dialogScopeUtils.d.ts +31 -0
  505. package/dist/src/utils/dialogScopeUtils.js +48 -0
  506. package/dist/src/utils/dialogScopeUtils.js.map +1 -0
  507. package/dist/src/utils/events.d.ts +11 -0
  508. package/dist/src/utils/events.js +13 -0
  509. package/dist/src/utils/events.js.map +1 -0
  510. package/dist/src/utils/gitUtils.d.ts +30 -0
  511. package/dist/src/utils/gitUtils.js +89 -0
  512. package/dist/src/utils/gitUtils.js.map +1 -0
  513. package/dist/src/utils/gitUtils.test.d.ts +6 -0
  514. package/dist/src/utils/gitUtils.test.js +113 -0
  515. package/dist/src/utils/gitUtils.test.js.map +1 -0
  516. package/dist/src/utils/handleAutoUpdate.d.ts +11 -0
  517. package/dist/src/utils/handleAutoUpdate.js +101 -0
  518. package/dist/src/utils/handleAutoUpdate.js.map +1 -0
  519. package/dist/src/utils/installationInfo.d.ts +23 -0
  520. package/dist/src/utils/installationInfo.js +154 -0
  521. package/dist/src/utils/installationInfo.js.map +1 -0
  522. package/dist/src/utils/installationInfo.test.d.ts +6 -0
  523. package/dist/src/utils/installationInfo.test.js +242 -0
  524. package/dist/src/utils/installationInfo.test.js.map +1 -0
  525. package/dist/src/utils/readStdin.js +10 -0
  526. package/dist/src/utils/readStdin.js.map +1 -1
  527. package/dist/src/utils/resolvePath.d.ts +6 -0
  528. package/dist/src/utils/resolvePath.js +21 -0
  529. package/dist/src/utils/resolvePath.js.map +1 -0
  530. package/dist/src/utils/sandbox-macos-permissive-closed.sb +6 -0
  531. package/dist/src/utils/sandbox-macos-permissive-open.sb +6 -0
  532. package/dist/src/utils/sandbox-macos-permissive-proxied.sb +6 -0
  533. package/dist/src/utils/sandbox-macos-restrictive-closed.sb +6 -0
  534. package/dist/src/utils/sandbox-macos-restrictive-open.sb +6 -0
  535. package/dist/src/utils/sandbox-macos-restrictive-proxied.sb +6 -0
  536. package/dist/src/utils/sandbox.d.ts +2 -2
  537. package/dist/src/utils/sandbox.js +448 -397
  538. package/dist/src/utils/sandbox.js.map +1 -1
  539. package/dist/src/utils/settingsUtils.d.ts +134 -0
  540. package/dist/src/utils/settingsUtils.js +336 -0
  541. package/dist/src/utils/settingsUtils.js.map +1 -0
  542. package/dist/src/utils/settingsUtils.test.d.ts +6 -0
  543. package/dist/src/utils/settingsUtils.test.js +514 -0
  544. package/dist/src/utils/settingsUtils.test.js.map +1 -0
  545. package/dist/src/utils/spawnWrapper.d.ts +7 -0
  546. package/dist/src/utils/spawnWrapper.js +8 -0
  547. package/dist/src/utils/spawnWrapper.js.map +1 -0
  548. package/dist/src/utils/updateEventEmitter.d.ts +11 -0
  549. package/dist/src/utils/updateEventEmitter.js +12 -0
  550. package/dist/src/utils/updateEventEmitter.js.map +1 -0
  551. package/dist/src/utils/userStartupWarnings.test.d.ts +6 -0
  552. package/dist/src/utils/userStartupWarnings.test.js +67 -0
  553. package/dist/src/utils/userStartupWarnings.test.js.map +1 -0
  554. package/dist/src/utils/version.js +1 -1
  555. package/dist/src/utils/version.js.map +1 -1
  556. package/dist/src/validateNonInterActiveAuth.d.ts +7 -0
  557. package/dist/src/validateNonInterActiveAuth.js +37 -0
  558. package/dist/src/validateNonInterActiveAuth.js.map +1 -0
  559. package/dist/src/zed-integration/acp.d.ts +63 -0
  560. package/dist/src/{acp → zed-integration}/acp.js +76 -44
  561. package/dist/src/zed-integration/acp.js.map +1 -0
  562. package/dist/src/zed-integration/fileSystemService.d.ts +19 -0
  563. package/dist/src/zed-integration/fileSystemService.js +43 -0
  564. package/dist/src/zed-integration/fileSystemService.js.map +1 -0
  565. package/dist/src/zed-integration/schema.d.ts +11679 -0
  566. package/dist/src/zed-integration/schema.js +305 -0
  567. package/dist/src/zed-integration/schema.js.map +1 -0
  568. package/dist/src/zed-integration/zedIntegration.d.ts +10 -0
  569. package/dist/src/{acp/acpPeer.js → zed-integration/zedIntegration.js} +336 -169
  570. package/dist/src/zed-integration/zedIntegration.js.map +1 -0
  571. package/dist/tsconfig.tsbuildinfo +1 -1
  572. package/package.json +13 -8
  573. package/dist/src/acp/acp.d.ts +0 -208
  574. package/dist/src/acp/acp.js.map +0 -1
  575. package/dist/src/acp/acpPeer.d.ts +0 -8
  576. package/dist/src/acp/acpPeer.js.map +0 -1
  577. package/dist/src/ui/utils/errorParsing.d.ts +0 -7
  578. package/dist/src/ui/utils/errorParsing.js +0 -90
  579. package/dist/src/ui/utils/errorParsing.js.map +0 -1
@@ -4,6 +4,7 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  import stripAnsi from 'strip-ansi';
7
+ import { stripVTControlCharacters } from 'util';
7
8
  import { spawnSync } from 'child_process';
8
9
  import fs from 'fs';
9
10
  import os from 'os';
@@ -12,6 +13,7 @@ import { useState, useCallback, useEffect, useMemo, useReducer } from 'react';
12
13
  import stringWidth from 'string-width';
13
14
  import { unescapePath } from '@machina.ai/cell-cli-core';
14
15
  import { toCodePoints, cpLen, cpSlice } from '../../utils/textUtils.js';
16
+ import { handleVimAction } from './vim-buffer-actions.js';
15
17
  // Simple helper for word‑wise ops.
16
18
  function isWordChar(ch) {
17
19
  if (ch === undefined) {
@@ -19,24 +21,397 @@ function isWordChar(ch) {
19
21
  }
20
22
  return !/[\s,.;!?]/.test(ch);
21
23
  }
24
+ // Helper functions for line-based word navigation
25
+ export const isWordCharStrict = (char) => /[\w\p{L}\p{N}]/u.test(char); // Matches a single character that is any Unicode letter, any Unicode number, or an underscore
26
+ export const isWhitespace = (char) => /\s/.test(char);
27
+ // Check if a character is a combining mark (only diacritics for now)
28
+ export const isCombiningMark = (char) => /\p{M}/u.test(char);
29
+ // Check if a character should be considered part of a word (including combining marks)
30
+ export const isWordCharWithCombining = (char) => isWordCharStrict(char) || isCombiningMark(char);
31
+ // Get the script of a character (simplified for common scripts)
32
+ export const getCharScript = (char) => {
33
+ if (/[\p{Script=Latin}]/u.test(char))
34
+ return 'latin'; // All Latin script chars including diacritics
35
+ if (/[\p{Script=Han}]/u.test(char))
36
+ return 'han'; // Chinese
37
+ if (/[\p{Script=Arabic}]/u.test(char))
38
+ return 'arabic';
39
+ if (/[\p{Script=Hiragana}]/u.test(char))
40
+ return 'hiragana';
41
+ if (/[\p{Script=Katakana}]/u.test(char))
42
+ return 'katakana';
43
+ if (/[\p{Script=Cyrillic}]/u.test(char))
44
+ return 'cyrillic';
45
+ return 'other';
46
+ };
47
+ // Check if two characters are from different scripts (indicating word boundary)
48
+ export const isDifferentScript = (char1, char2) => {
49
+ if (!isWordCharStrict(char1) || !isWordCharStrict(char2))
50
+ return false;
51
+ return getCharScript(char1) !== getCharScript(char2);
52
+ };
53
+ // Find next word start within a line, starting from col
54
+ export const findNextWordStartInLine = (line, col) => {
55
+ const chars = toCodePoints(line);
56
+ let i = col;
57
+ if (i >= chars.length)
58
+ return null;
59
+ const currentChar = chars[i];
60
+ // Skip current word/sequence based on character type
61
+ if (isWordCharStrict(currentChar)) {
62
+ while (i < chars.length && isWordCharWithCombining(chars[i])) {
63
+ // Check for script boundary - if next character is from different script, stop here
64
+ if (i + 1 < chars.length &&
65
+ isWordCharStrict(chars[i + 1]) &&
66
+ isDifferentScript(chars[i], chars[i + 1])) {
67
+ i++; // Include current character
68
+ break; // Stop at script boundary
69
+ }
70
+ i++;
71
+ }
72
+ }
73
+ else if (!isWhitespace(currentChar)) {
74
+ while (i < chars.length &&
75
+ !isWordCharStrict(chars[i]) &&
76
+ !isWhitespace(chars[i])) {
77
+ i++;
78
+ }
79
+ }
80
+ // Skip whitespace
81
+ while (i < chars.length && isWhitespace(chars[i])) {
82
+ i++;
83
+ }
84
+ return i < chars.length ? i : null;
85
+ };
86
+ // Find previous word start within a line
87
+ export const findPrevWordStartInLine = (line, col) => {
88
+ const chars = toCodePoints(line);
89
+ let i = col;
90
+ if (i <= 0)
91
+ return null;
92
+ i--;
93
+ // Skip whitespace moving backwards
94
+ while (i >= 0 && isWhitespace(chars[i])) {
95
+ i--;
96
+ }
97
+ if (i < 0)
98
+ return null;
99
+ if (isWordCharStrict(chars[i])) {
100
+ // We're in a word, move to its beginning
101
+ while (i >= 0 && isWordCharStrict(chars[i])) {
102
+ // Check for script boundary - if previous character is from different script, stop here
103
+ if (i - 1 >= 0 &&
104
+ isWordCharStrict(chars[i - 1]) &&
105
+ isDifferentScript(chars[i], chars[i - 1])) {
106
+ return i; // Return current position at script boundary
107
+ }
108
+ i--;
109
+ }
110
+ return i + 1;
111
+ }
112
+ else {
113
+ // We're in punctuation, move to its beginning
114
+ while (i >= 0 && !isWordCharStrict(chars[i]) && !isWhitespace(chars[i])) {
115
+ i--;
116
+ }
117
+ return i + 1;
118
+ }
119
+ };
120
+ // Find word end within a line
121
+ export const findWordEndInLine = (line, col) => {
122
+ const chars = toCodePoints(line);
123
+ let i = col;
124
+ // If we're already at the end of a word (including punctuation sequences), advance to next word
125
+ // This includes both regular word endings and script boundaries
126
+ const atEndOfWordChar = i < chars.length &&
127
+ isWordCharWithCombining(chars[i]) &&
128
+ (i + 1 >= chars.length ||
129
+ !isWordCharWithCombining(chars[i + 1]) ||
130
+ (isWordCharStrict(chars[i]) &&
131
+ i + 1 < chars.length &&
132
+ isWordCharStrict(chars[i + 1]) &&
133
+ isDifferentScript(chars[i], chars[i + 1])));
134
+ const atEndOfPunctuation = i < chars.length &&
135
+ !isWordCharWithCombining(chars[i]) &&
136
+ !isWhitespace(chars[i]) &&
137
+ (i + 1 >= chars.length ||
138
+ isWhitespace(chars[i + 1]) ||
139
+ isWordCharWithCombining(chars[i + 1]));
140
+ if (atEndOfWordChar || atEndOfPunctuation) {
141
+ // We're at the end of a word or punctuation sequence, move forward to find next word
142
+ i++;
143
+ // Skip whitespace to find next word or punctuation
144
+ while (i < chars.length && isWhitespace(chars[i])) {
145
+ i++;
146
+ }
147
+ }
148
+ // If we're not on a word character, find the next word or punctuation sequence
149
+ if (i < chars.length && !isWordCharWithCombining(chars[i])) {
150
+ // Skip whitespace to find next word or punctuation
151
+ while (i < chars.length && isWhitespace(chars[i])) {
152
+ i++;
153
+ }
154
+ }
155
+ // Move to end of current word (including combining marks, but stop at script boundaries)
156
+ let foundWord = false;
157
+ let lastBaseCharPos = -1;
158
+ if (i < chars.length && isWordCharWithCombining(chars[i])) {
159
+ // Handle word characters
160
+ while (i < chars.length && isWordCharWithCombining(chars[i])) {
161
+ foundWord = true;
162
+ // Track the position of the last base character (not combining mark)
163
+ if (isWordCharStrict(chars[i])) {
164
+ lastBaseCharPos = i;
165
+ }
166
+ // Check if next character is from a different script (word boundary)
167
+ if (i + 1 < chars.length &&
168
+ isWordCharStrict(chars[i + 1]) &&
169
+ isDifferentScript(chars[i], chars[i + 1])) {
170
+ i++; // Include current character
171
+ if (isWordCharStrict(chars[i - 1])) {
172
+ lastBaseCharPos = i - 1;
173
+ }
174
+ break; // Stop at script boundary
175
+ }
176
+ i++;
177
+ }
178
+ }
179
+ else if (i < chars.length && !isWhitespace(chars[i])) {
180
+ // Handle punctuation sequences (like ████)
181
+ while (i < chars.length &&
182
+ !isWordCharStrict(chars[i]) &&
183
+ !isWhitespace(chars[i])) {
184
+ foundWord = true;
185
+ lastBaseCharPos = i;
186
+ i++;
187
+ }
188
+ }
189
+ // Only return a position if we actually found a word
190
+ // Return the position of the last base character, not combining marks
191
+ if (foundWord && lastBaseCharPos >= col) {
192
+ return lastBaseCharPos;
193
+ }
194
+ return null;
195
+ };
196
+ // Find next word across lines
197
+ export const findNextWordAcrossLines = (lines, cursorRow, cursorCol, searchForWordStart) => {
198
+ // First try current line
199
+ const currentLine = lines[cursorRow] || '';
200
+ const colInCurrentLine = searchForWordStart
201
+ ? findNextWordStartInLine(currentLine, cursorCol)
202
+ : findWordEndInLine(currentLine, cursorCol);
203
+ if (colInCurrentLine !== null) {
204
+ return { row: cursorRow, col: colInCurrentLine };
205
+ }
206
+ // Search subsequent lines
207
+ for (let row = cursorRow + 1; row < lines.length; row++) {
208
+ const line = lines[row] || '';
209
+ const chars = toCodePoints(line);
210
+ // For empty lines, if we haven't found any words yet, return the empty line
211
+ if (chars.length === 0) {
212
+ // Check if there are any words in remaining lines
213
+ let hasWordsInLaterLines = false;
214
+ for (let laterRow = row + 1; laterRow < lines.length; laterRow++) {
215
+ const laterLine = lines[laterRow] || '';
216
+ const laterChars = toCodePoints(laterLine);
217
+ let firstNonWhitespace = 0;
218
+ while (firstNonWhitespace < laterChars.length &&
219
+ isWhitespace(laterChars[firstNonWhitespace])) {
220
+ firstNonWhitespace++;
221
+ }
222
+ if (firstNonWhitespace < laterChars.length) {
223
+ hasWordsInLaterLines = true;
224
+ break;
225
+ }
226
+ }
227
+ // If no words in later lines, return the empty line
228
+ if (!hasWordsInLaterLines) {
229
+ return { row, col: 0 };
230
+ }
231
+ continue;
232
+ }
233
+ // Find first non-whitespace
234
+ let firstNonWhitespace = 0;
235
+ while (firstNonWhitespace < chars.length &&
236
+ isWhitespace(chars[firstNonWhitespace])) {
237
+ firstNonWhitespace++;
238
+ }
239
+ if (firstNonWhitespace < chars.length) {
240
+ if (searchForWordStart) {
241
+ return { row, col: firstNonWhitespace };
242
+ }
243
+ else {
244
+ // For word end, find the end of the first word
245
+ const endCol = findWordEndInLine(line, firstNonWhitespace);
246
+ if (endCol !== null) {
247
+ return { row, col: endCol };
248
+ }
249
+ }
250
+ }
251
+ }
252
+ return null;
253
+ };
254
+ // Find previous word across lines
255
+ export const findPrevWordAcrossLines = (lines, cursorRow, cursorCol) => {
256
+ // First try current line
257
+ const currentLine = lines[cursorRow] || '';
258
+ const colInCurrentLine = findPrevWordStartInLine(currentLine, cursorCol);
259
+ if (colInCurrentLine !== null) {
260
+ return { row: cursorRow, col: colInCurrentLine };
261
+ }
262
+ // Search previous lines
263
+ for (let row = cursorRow - 1; row >= 0; row--) {
264
+ const line = lines[row] || '';
265
+ const chars = toCodePoints(line);
266
+ if (chars.length === 0)
267
+ continue;
268
+ // Find last word start
269
+ let lastWordStart = chars.length;
270
+ while (lastWordStart > 0 && isWhitespace(chars[lastWordStart - 1])) {
271
+ lastWordStart--;
272
+ }
273
+ if (lastWordStart > 0) {
274
+ // Find start of this word
275
+ const wordStart = findPrevWordStartInLine(line, lastWordStart);
276
+ if (wordStart !== null) {
277
+ return { row, col: wordStart };
278
+ }
279
+ }
280
+ }
281
+ return null;
282
+ };
283
+ // Helper functions for vim line operations
284
+ export const getPositionFromOffsets = (startOffset, endOffset, lines) => {
285
+ let offset = 0;
286
+ let startRow = 0;
287
+ let startCol = 0;
288
+ let endRow = 0;
289
+ let endCol = 0;
290
+ // Find start position
291
+ for (let i = 0; i < lines.length; i++) {
292
+ const lineLength = lines[i].length + 1; // +1 for newline
293
+ if (offset + lineLength > startOffset) {
294
+ startRow = i;
295
+ startCol = startOffset - offset;
296
+ break;
297
+ }
298
+ offset += lineLength;
299
+ }
300
+ // Find end position
301
+ offset = 0;
302
+ for (let i = 0; i < lines.length; i++) {
303
+ const lineLength = lines[i].length + (i < lines.length - 1 ? 1 : 0); // +1 for newline except last line
304
+ if (offset + lineLength >= endOffset) {
305
+ endRow = i;
306
+ endCol = endOffset - offset;
307
+ break;
308
+ }
309
+ offset += lineLength;
310
+ }
311
+ return { startRow, startCol, endRow, endCol };
312
+ };
313
+ export const getLineRangeOffsets = (startRow, lineCount, lines) => {
314
+ let startOffset = 0;
315
+ // Calculate start offset
316
+ for (let i = 0; i < startRow; i++) {
317
+ startOffset += lines[i].length + 1; // +1 for newline
318
+ }
319
+ // Calculate end offset
320
+ let endOffset = startOffset;
321
+ for (let i = 0; i < lineCount; i++) {
322
+ const lineIndex = startRow + i;
323
+ if (lineIndex < lines.length) {
324
+ endOffset += lines[lineIndex].length;
325
+ if (lineIndex < lines.length - 1) {
326
+ endOffset += 1; // +1 for newline
327
+ }
328
+ }
329
+ }
330
+ return { startOffset, endOffset };
331
+ };
332
+ export const replaceRangeInternal = (state, startRow, startCol, endRow, endCol, text) => {
333
+ const currentLine = (row) => state.lines[row] || '';
334
+ const currentLineLen = (row) => cpLen(currentLine(row));
335
+ const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
336
+ if (startRow > endRow ||
337
+ (startRow === endRow && startCol > endCol) ||
338
+ startRow < 0 ||
339
+ startCol < 0 ||
340
+ endRow >= state.lines.length ||
341
+ (endRow < state.lines.length && endCol > currentLineLen(endRow))) {
342
+ return state; // Invalid range
343
+ }
344
+ const newLines = [...state.lines];
345
+ const sCol = clamp(startCol, 0, currentLineLen(startRow));
346
+ const eCol = clamp(endCol, 0, currentLineLen(endRow));
347
+ const prefix = cpSlice(currentLine(startRow), 0, sCol);
348
+ const suffix = cpSlice(currentLine(endRow), eCol);
349
+ const normalisedReplacement = text
350
+ .replace(/\r\n/g, '\n')
351
+ .replace(/\r/g, '\n');
352
+ const replacementParts = normalisedReplacement.split('\n');
353
+ // The combined first line of the new text
354
+ const firstLine = prefix + replacementParts[0];
355
+ if (replacementParts.length === 1) {
356
+ // No newlines in replacement: combine prefix, replacement, and suffix on one line.
357
+ newLines.splice(startRow, endRow - startRow + 1, firstLine + suffix);
358
+ }
359
+ else {
360
+ // Newlines in replacement: create new lines.
361
+ const lastLine = replacementParts[replacementParts.length - 1] + suffix;
362
+ const middleLines = replacementParts.slice(1, -1);
363
+ newLines.splice(startRow, endRow - startRow + 1, firstLine, ...middleLines, lastLine);
364
+ }
365
+ const finalCursorRow = startRow + replacementParts.length - 1;
366
+ const finalCursorCol = (replacementParts.length > 1 ? 0 : sCol) +
367
+ cpLen(replacementParts[replacementParts.length - 1]);
368
+ return {
369
+ ...state,
370
+ lines: newLines,
371
+ cursorRow: Math.min(Math.max(finalCursorRow, 0), newLines.length - 1),
372
+ cursorCol: Math.max(0, Math.min(finalCursorCol, cpLen(newLines[finalCursorRow] || ''))),
373
+ preferredCol: null,
374
+ };
375
+ };
22
376
  /**
23
377
  * Strip characters that can break terminal rendering.
24
378
  *
25
- * Strip ANSI escape codes and control characters except for line breaks.
26
- * Control characters such as delete break terminal UI rendering.
379
+ * Uses Node.js built-in stripVTControlCharacters to handle VT sequences,
380
+ * then filters remaining control characters that can disrupt display.
381
+ *
382
+ * Characters stripped:
383
+ * - ANSI escape sequences (via strip-ansi)
384
+ * - VT control sequences (via Node.js util.stripVTControlCharacters)
385
+ * - C0 control chars (0x00-0x1F) except CR/LF which are handled elsewhere
386
+ * - C1 control chars (0x80-0x9F) that can cause display issues
387
+ *
388
+ * Characters preserved:
389
+ * - All printable Unicode including emojis
390
+ * - DEL (0x7F) - handled functionally by applyOperations, not a display issue
391
+ * - CR/LF (0x0D/0x0A) - needed for line breaks
27
392
  */
28
393
  function stripUnsafeCharacters(str) {
29
- const stripped = stripAnsi(str);
30
- return toCodePoints(stripped)
394
+ const strippedAnsi = stripAnsi(str);
395
+ const strippedVT = stripVTControlCharacters(strippedAnsi);
396
+ return toCodePoints(strippedVT)
31
397
  .filter((char) => {
32
- if (char.length > 1)
33
- return false;
34
398
  const code = char.codePointAt(0);
35
- if (code === undefined) {
399
+ if (code === undefined)
36
400
  return false;
37
- }
38
- const isUnsafe = code === 127 || (code <= 31 && code !== 13 && code !== 10);
39
- return !isUnsafe;
401
+ // Preserve CR/LF for line handling
402
+ if (code === 0x0a || code === 0x0d)
403
+ return true;
404
+ // Remove C0 control chars (except CR/LF) that can break display
405
+ // Examples: BELL(0x07) makes noise, BS(0x08) moves cursor, VT(0x0B), FF(0x0C)
406
+ if (code >= 0x00 && code <= 0x1f)
407
+ return false;
408
+ // Remove C1 control chars (0x80-0x9F) - legacy 8-bit control codes
409
+ if (code >= 0x80 && code <= 0x9f)
410
+ return false;
411
+ // Preserve DEL (0x7F) - it's handled functionally by applyOperations as backspace
412
+ // and doesn't cause rendering issues when displayed
413
+ // Preserve all other characters including Unicode/emojis
414
+ return true;
40
415
  })
41
416
  .join('');
42
417
  }
@@ -106,6 +481,24 @@ export function offsetToLogicalPos(text, offset) {
106
481
  }
107
482
  return [row, col];
108
483
  }
484
+ /**
485
+ * Converts logical row/col position to absolute text offset
486
+ * Inverse operation of offsetToLogicalPos
487
+ */
488
+ export function logicalPosToOffset(lines, row, col) {
489
+ let offset = 0;
490
+ // Clamp row to valid range
491
+ const actualRow = Math.min(row, lines.length - 1);
492
+ // Add lengths of all lines before the target row
493
+ for (let i = 0; i < actualRow; i++) {
494
+ offset += cpLen(lines[i]) + 1; // +1 for newline
495
+ }
496
+ // Add column offset within the target row
497
+ if (actualRow >= 0 && actualRow < lines.length) {
498
+ offset += Math.min(col, cpLen(lines[actualRow]));
499
+ }
500
+ return offset;
501
+ }
109
502
  // Helper to calculate visual lines and map cursor positions
110
503
  function calculateVisualLayout(logicalLines, logicalCursor, viewportWidth) {
111
504
  const visualLines = [];
@@ -279,26 +672,27 @@ function calculateVisualLayout(logicalLines, logicalCursor, viewportWidth) {
279
672
  };
280
673
  }
281
674
  const historyLimit = 100;
282
- export function textBufferReducer(state, action) {
283
- const pushUndo = (currentState) => {
284
- const snapshot = {
285
- lines: [...currentState.lines],
286
- cursorRow: currentState.cursorRow,
287
- cursorCol: currentState.cursorCol,
288
- };
289
- const newStack = [...currentState.undoStack, snapshot];
290
- if (newStack.length > historyLimit) {
291
- newStack.shift();
292
- }
293
- return { ...currentState, undoStack: newStack, redoStack: [] };
675
+ export const pushUndo = (currentState) => {
676
+ const snapshot = {
677
+ lines: [...currentState.lines],
678
+ cursorRow: currentState.cursorRow,
679
+ cursorCol: currentState.cursorCol,
294
680
  };
681
+ const newStack = [...currentState.undoStack, snapshot];
682
+ if (newStack.length > historyLimit) {
683
+ newStack.shift();
684
+ }
685
+ return { ...currentState, undoStack: newStack, redoStack: [] };
686
+ };
687
+ export function textBufferReducer(state, action) {
688
+ const pushUndoLocal = pushUndo;
295
689
  const currentLine = (r) => state.lines[r] ?? '';
296
690
  const currentLineLen = (r) => cpLen(currentLine(r));
297
691
  switch (action.type) {
298
692
  case 'set_text': {
299
693
  let nextState = state;
300
694
  if (action.pushToUndo !== false) {
301
- nextState = pushUndo(state);
695
+ nextState = pushUndoLocal(state);
302
696
  }
303
697
  const newContentLines = action.payload
304
698
  .replace(/\r\n?/g, '\n')
@@ -314,7 +708,7 @@ export function textBufferReducer(state, action) {
314
708
  };
315
709
  }
316
710
  case 'insert': {
317
- const nextState = pushUndo(state);
711
+ const nextState = pushUndoLocal(state);
318
712
  const newLines = [...nextState.lines];
319
713
  let newCursorRow = nextState.cursorRow;
320
714
  let newCursorCol = nextState.cursorCol;
@@ -346,7 +740,7 @@ export function textBufferReducer(state, action) {
346
740
  };
347
741
  }
348
742
  case 'backspace': {
349
- const nextState = pushUndo(state);
743
+ const nextState = pushUndoLocal(state);
350
744
  const newLines = [...nextState.lines];
351
745
  let newCursorRow = nextState.cursorRow;
352
746
  let newCursorCol = nextState.cursorCol;
@@ -523,7 +917,7 @@ export function textBufferReducer(state, action) {
523
917
  const { cursorRow, cursorCol, lines } = state;
524
918
  const lineContent = currentLine(cursorRow);
525
919
  if (cursorCol < currentLineLen(cursorRow)) {
526
- const nextState = pushUndo(state);
920
+ const nextState = pushUndoLocal(state);
527
921
  const newLines = [...nextState.lines];
528
922
  newLines[cursorRow] =
529
923
  cpSlice(lineContent, 0, cursorCol) +
@@ -531,7 +925,7 @@ export function textBufferReducer(state, action) {
531
925
  return { ...nextState, lines: newLines, preferredCol: null };
532
926
  }
533
927
  else if (cursorRow < lines.length - 1) {
534
- const nextState = pushUndo(state);
928
+ const nextState = pushUndoLocal(state);
535
929
  const nextLineContent = currentLine(cursorRow + 1);
536
930
  const newLines = [...nextState.lines];
537
931
  newLines[cursorRow] = lineContent + nextLineContent;
@@ -546,7 +940,7 @@ export function textBufferReducer(state, action) {
546
940
  return state;
547
941
  if (cursorCol === 0) {
548
942
  // Act as a backspace
549
- const nextState = pushUndo(state);
943
+ const nextState = pushUndoLocal(state);
550
944
  const prevLineContent = currentLine(cursorRow - 1);
551
945
  const currentLineContentVal = currentLine(cursorRow);
552
946
  const newCol = cpLen(prevLineContent);
@@ -561,7 +955,7 @@ export function textBufferReducer(state, action) {
561
955
  preferredCol: null,
562
956
  };
563
957
  }
564
- const nextState = pushUndo(state);
958
+ const nextState = pushUndoLocal(state);
565
959
  const lineContent = currentLine(cursorRow);
566
960
  const arr = toCodePoints(lineContent);
567
961
  let start = cursorCol;
@@ -599,14 +993,14 @@ export function textBufferReducer(state, action) {
599
993
  return state;
600
994
  if (cursorCol >= arr.length) {
601
995
  // Act as a delete
602
- const nextState = pushUndo(state);
996
+ const nextState = pushUndoLocal(state);
603
997
  const nextLineContent = currentLine(cursorRow + 1);
604
998
  const newLines = [...nextState.lines];
605
999
  newLines[cursorRow] = lineContent + nextLineContent;
606
1000
  newLines.splice(cursorRow + 1, 1);
607
1001
  return { ...nextState, lines: newLines, preferredCol: null };
608
1002
  }
609
- const nextState = pushUndo(state);
1003
+ const nextState = pushUndoLocal(state);
610
1004
  let end = cursorCol;
611
1005
  while (end < arr.length && !isWordChar(arr[end]))
612
1006
  end++;
@@ -621,14 +1015,14 @@ export function textBufferReducer(state, action) {
621
1015
  const { cursorRow, cursorCol, lines } = state;
622
1016
  const lineContent = currentLine(cursorRow);
623
1017
  if (cursorCol < currentLineLen(cursorRow)) {
624
- const nextState = pushUndo(state);
1018
+ const nextState = pushUndoLocal(state);
625
1019
  const newLines = [...nextState.lines];
626
1020
  newLines[cursorRow] = cpSlice(lineContent, 0, cursorCol);
627
1021
  return { ...nextState, lines: newLines };
628
1022
  }
629
1023
  else if (cursorRow < lines.length - 1) {
630
1024
  // Act as a delete
631
- const nextState = pushUndo(state);
1025
+ const nextState = pushUndoLocal(state);
632
1026
  const nextLineContent = currentLine(cursorRow + 1);
633
1027
  const newLines = [...nextState.lines];
634
1028
  newLines[cursorRow] = lineContent + nextLineContent;
@@ -640,7 +1034,7 @@ export function textBufferReducer(state, action) {
640
1034
  case 'kill_line_left': {
641
1035
  const { cursorRow, cursorCol } = state;
642
1036
  if (cursorCol > 0) {
643
- const nextState = pushUndo(state);
1037
+ const nextState = pushUndoLocal(state);
644
1038
  const lineContent = currentLine(cursorRow);
645
1039
  const newLines = [...nextState.lines];
646
1040
  newLines[cursorRow] = cpSlice(lineContent, cursorCol);
@@ -687,51 +1081,8 @@ export function textBufferReducer(state, action) {
687
1081
  }
688
1082
  case 'replace_range': {
689
1083
  const { startRow, startCol, endRow, endCol, text } = action.payload;
690
- if (startRow > endRow ||
691
- (startRow === endRow && startCol > endCol) ||
692
- startRow < 0 ||
693
- startCol < 0 ||
694
- endRow >= state.lines.length ||
695
- (endRow < state.lines.length && endCol > currentLineLen(endRow))) {
696
- return state; // Invalid range
697
- }
698
- const nextState = pushUndo(state);
699
- const newLines = [...nextState.lines];
700
- const sCol = clamp(startCol, 0, currentLineLen(startRow));
701
- const eCol = clamp(endCol, 0, currentLineLen(endRow));
702
- const prefix = cpSlice(currentLine(startRow), 0, sCol);
703
- const suffix = cpSlice(currentLine(endRow), eCol);
704
- const normalisedReplacement = text
705
- .replace(/\r\n/g, '\n')
706
- .replace(/\r/g, '\n');
707
- const replacementParts = normalisedReplacement.split('\n');
708
- // Replace the content
709
- if (startRow === endRow) {
710
- newLines[startRow] = prefix + normalisedReplacement + suffix;
711
- }
712
- else {
713
- const firstLine = prefix + replacementParts[0];
714
- if (replacementParts.length === 1) {
715
- // Single line of replacement text, but spanning multiple original lines
716
- newLines.splice(startRow, endRow - startRow + 1, firstLine + suffix);
717
- }
718
- else {
719
- // Multi-line replacement text
720
- const lastLine = replacementParts[replacementParts.length - 1] + suffix;
721
- const middleLines = replacementParts.slice(1, -1);
722
- newLines.splice(startRow, endRow - startRow + 1, firstLine, ...middleLines, lastLine);
723
- }
724
- }
725
- const finalCursorRow = startRow + replacementParts.length - 1;
726
- const finalCursorCol = (replacementParts.length > 1 ? 0 : sCol) +
727
- cpLen(replacementParts[replacementParts.length - 1]);
728
- return {
729
- ...nextState,
730
- lines: newLines,
731
- cursorRow: finalCursorRow,
732
- cursorCol: finalCursorCol,
733
- preferredCol: null,
734
- };
1084
+ const nextState = pushUndoLocal(state);
1085
+ return replaceRangeInternal(nextState, startRow, startCol, endRow, endCol, text);
735
1086
  }
736
1087
  case 'move_to_offset': {
737
1088
  const { offset } = action.payload;
@@ -744,8 +1095,42 @@ export function textBufferReducer(state, action) {
744
1095
  };
745
1096
  }
746
1097
  case 'create_undo_snapshot': {
747
- return pushUndo(state);
1098
+ return pushUndoLocal(state);
748
1099
  }
1100
+ // Vim-specific operations
1101
+ case 'vim_delete_word_forward':
1102
+ case 'vim_delete_word_backward':
1103
+ case 'vim_delete_word_end':
1104
+ case 'vim_change_word_forward':
1105
+ case 'vim_change_word_backward':
1106
+ case 'vim_change_word_end':
1107
+ case 'vim_delete_line':
1108
+ case 'vim_change_line':
1109
+ case 'vim_delete_to_end_of_line':
1110
+ case 'vim_change_to_end_of_line':
1111
+ case 'vim_change_movement':
1112
+ case 'vim_move_left':
1113
+ case 'vim_move_right':
1114
+ case 'vim_move_up':
1115
+ case 'vim_move_down':
1116
+ case 'vim_move_word_forward':
1117
+ case 'vim_move_word_backward':
1118
+ case 'vim_move_word_end':
1119
+ case 'vim_delete_char':
1120
+ case 'vim_insert_at_cursor':
1121
+ case 'vim_append_at_cursor':
1122
+ case 'vim_open_line_below':
1123
+ case 'vim_open_line_above':
1124
+ case 'vim_append_at_line_end':
1125
+ case 'vim_insert_at_line_start':
1126
+ case 'vim_move_to_line_start':
1127
+ case 'vim_move_to_line_end':
1128
+ case 'vim_move_to_first_nonwhitespace':
1129
+ case 'vim_move_to_first_line':
1130
+ case 'vim_move_to_last_line':
1131
+ case 'vim_move_to_line':
1132
+ case 'vim_escape_insert_mode':
1133
+ return handleVimAction(state, action);
749
1134
  default: {
750
1135
  const exhaustiveCheck = action;
751
1136
  console.error(`Unknown action encountered: ${exhaustiveCheck}`);
@@ -798,22 +1183,23 @@ export function useTextBuffer({ initialText = '', initialCursorOffset = 0, viewp
798
1183
  setVisualScrollRow(newVisualScrollRow);
799
1184
  }
800
1185
  }, [visualCursor, visualScrollRow, viewport]);
801
- const insert = useCallback((ch) => {
1186
+ const insert = useCallback((ch, { paste = false } = {}) => {
802
1187
  if (/[\n\r]/.test(ch)) {
803
1188
  dispatch({ type: 'insert', payload: ch });
804
1189
  return;
805
1190
  }
806
1191
  const minLengthToInferAsDragDrop = 3;
807
- if (ch.length >= minLengthToInferAsDragDrop && !shellModeActive) {
808
- let potentialPath = ch;
809
- if (potentialPath.length > 2 &&
810
- potentialPath.startsWith("'") &&
811
- potentialPath.endsWith("'")) {
812
- potentialPath = ch.slice(1, -1);
1192
+ if (ch.length >= minLengthToInferAsDragDrop &&
1193
+ !shellModeActive &&
1194
+ paste) {
1195
+ let potentialPath = ch.trim();
1196
+ const quoteMatch = potentialPath.match(/^'(.*)'$/);
1197
+ if (quoteMatch) {
1198
+ potentialPath = quoteMatch[1];
813
1199
  }
814
1200
  potentialPath = potentialPath.trim();
815
1201
  if (isValidPath(unescapePath(potentialPath))) {
816
- ch = `@${potentialPath}`;
1202
+ ch = `@${potentialPath} `;
817
1203
  }
818
1204
  }
819
1205
  let currentText = '';
@@ -866,6 +1252,104 @@ export function useTextBuffer({ initialText = '', initialCursorOffset = 0, viewp
866
1252
  const killLineLeft = useCallback(() => {
867
1253
  dispatch({ type: 'kill_line_left' });
868
1254
  }, []);
1255
+ // Vim-specific operations
1256
+ const vimDeleteWordForward = useCallback((count) => {
1257
+ dispatch({ type: 'vim_delete_word_forward', payload: { count } });
1258
+ }, []);
1259
+ const vimDeleteWordBackward = useCallback((count) => {
1260
+ dispatch({ type: 'vim_delete_word_backward', payload: { count } });
1261
+ }, []);
1262
+ const vimDeleteWordEnd = useCallback((count) => {
1263
+ dispatch({ type: 'vim_delete_word_end', payload: { count } });
1264
+ }, []);
1265
+ const vimChangeWordForward = useCallback((count) => {
1266
+ dispatch({ type: 'vim_change_word_forward', payload: { count } });
1267
+ }, []);
1268
+ const vimChangeWordBackward = useCallback((count) => {
1269
+ dispatch({ type: 'vim_change_word_backward', payload: { count } });
1270
+ }, []);
1271
+ const vimChangeWordEnd = useCallback((count) => {
1272
+ dispatch({ type: 'vim_change_word_end', payload: { count } });
1273
+ }, []);
1274
+ const vimDeleteLine = useCallback((count) => {
1275
+ dispatch({ type: 'vim_delete_line', payload: { count } });
1276
+ }, []);
1277
+ const vimChangeLine = useCallback((count) => {
1278
+ dispatch({ type: 'vim_change_line', payload: { count } });
1279
+ }, []);
1280
+ const vimDeleteToEndOfLine = useCallback(() => {
1281
+ dispatch({ type: 'vim_delete_to_end_of_line' });
1282
+ }, []);
1283
+ const vimChangeToEndOfLine = useCallback(() => {
1284
+ dispatch({ type: 'vim_change_to_end_of_line' });
1285
+ }, []);
1286
+ const vimChangeMovement = useCallback((movement, count) => {
1287
+ dispatch({ type: 'vim_change_movement', payload: { movement, count } });
1288
+ }, []);
1289
+ // New vim navigation and operation methods
1290
+ const vimMoveLeft = useCallback((count) => {
1291
+ dispatch({ type: 'vim_move_left', payload: { count } });
1292
+ }, []);
1293
+ const vimMoveRight = useCallback((count) => {
1294
+ dispatch({ type: 'vim_move_right', payload: { count } });
1295
+ }, []);
1296
+ const vimMoveUp = useCallback((count) => {
1297
+ dispatch({ type: 'vim_move_up', payload: { count } });
1298
+ }, []);
1299
+ const vimMoveDown = useCallback((count) => {
1300
+ dispatch({ type: 'vim_move_down', payload: { count } });
1301
+ }, []);
1302
+ const vimMoveWordForward = useCallback((count) => {
1303
+ dispatch({ type: 'vim_move_word_forward', payload: { count } });
1304
+ }, []);
1305
+ const vimMoveWordBackward = useCallback((count) => {
1306
+ dispatch({ type: 'vim_move_word_backward', payload: { count } });
1307
+ }, []);
1308
+ const vimMoveWordEnd = useCallback((count) => {
1309
+ dispatch({ type: 'vim_move_word_end', payload: { count } });
1310
+ }, []);
1311
+ const vimDeleteChar = useCallback((count) => {
1312
+ dispatch({ type: 'vim_delete_char', payload: { count } });
1313
+ }, []);
1314
+ const vimInsertAtCursor = useCallback(() => {
1315
+ dispatch({ type: 'vim_insert_at_cursor' });
1316
+ }, []);
1317
+ const vimAppendAtCursor = useCallback(() => {
1318
+ dispatch({ type: 'vim_append_at_cursor' });
1319
+ }, []);
1320
+ const vimOpenLineBelow = useCallback(() => {
1321
+ dispatch({ type: 'vim_open_line_below' });
1322
+ }, []);
1323
+ const vimOpenLineAbove = useCallback(() => {
1324
+ dispatch({ type: 'vim_open_line_above' });
1325
+ }, []);
1326
+ const vimAppendAtLineEnd = useCallback(() => {
1327
+ dispatch({ type: 'vim_append_at_line_end' });
1328
+ }, []);
1329
+ const vimInsertAtLineStart = useCallback(() => {
1330
+ dispatch({ type: 'vim_insert_at_line_start' });
1331
+ }, []);
1332
+ const vimMoveToLineStart = useCallback(() => {
1333
+ dispatch({ type: 'vim_move_to_line_start' });
1334
+ }, []);
1335
+ const vimMoveToLineEnd = useCallback(() => {
1336
+ dispatch({ type: 'vim_move_to_line_end' });
1337
+ }, []);
1338
+ const vimMoveToFirstNonWhitespace = useCallback(() => {
1339
+ dispatch({ type: 'vim_move_to_first_nonwhitespace' });
1340
+ }, []);
1341
+ const vimMoveToFirstLine = useCallback(() => {
1342
+ dispatch({ type: 'vim_move_to_first_line' });
1343
+ }, []);
1344
+ const vimMoveToLastLine = useCallback(() => {
1345
+ dispatch({ type: 'vim_move_to_last_line' });
1346
+ }, []);
1347
+ const vimMoveToLine = useCallback((lineNumber) => {
1348
+ dispatch({ type: 'vim_move_to_line', payload: { lineNumber } });
1349
+ }, []);
1350
+ const vimEscapeInsertMode = useCallback(() => {
1351
+ dispatch({ type: 'vim_escape_insert_mode' });
1352
+ }, []);
869
1353
  const openInExternalEditor = useCallback(async (opts = {}) => {
870
1354
  const editor = opts.editor ??
871
1355
  process.env['VISUAL'] ??
@@ -911,6 +1395,12 @@ export function useTextBuffer({ initialText = '', initialCursorOffset = 0, viewp
911
1395
  }, [text, stdin, setRawMode]);
912
1396
  const handleInput = useCallback((key) => {
913
1397
  const { sequence: input } = key;
1398
+ if (key.paste) {
1399
+ // Do not do any other processing on pastes so ensure we handle them
1400
+ // before all other cases.
1401
+ insert(input, { paste: key.paste });
1402
+ return;
1403
+ }
914
1404
  if (key.name === 'return' ||
915
1405
  input === '\r' ||
916
1406
  input === '\n' ||
@@ -959,7 +1449,7 @@ export function useTextBuffer({ initialText = '', initialCursorOffset = 0, viewp
959
1449
  else if (key.name === 'delete' || (key.ctrl && key.name === 'd'))
960
1450
  del();
961
1451
  else if (input && !key.ctrl && !key.meta) {
962
- insert(input);
1452
+ insert(input, { paste: key.paste });
963
1453
  }
964
1454
  }, [newline, move, deleteWordLeft, deleteWordRight, backspace, del, insert]);
965
1455
  const renderedVisualLines = useMemo(() => visualLines.slice(visualScrollRow, visualScrollRow + viewport.height), [visualLines, visualScrollRow, viewport.height]);
@@ -1004,6 +1494,39 @@ export function useTextBuffer({ initialText = '', initialCursorOffset = 0, viewp
1004
1494
  killLineLeft,
1005
1495
  handleInput,
1006
1496
  openInExternalEditor,
1497
+ // Vim-specific operations
1498
+ vimDeleteWordForward,
1499
+ vimDeleteWordBackward,
1500
+ vimDeleteWordEnd,
1501
+ vimChangeWordForward,
1502
+ vimChangeWordBackward,
1503
+ vimChangeWordEnd,
1504
+ vimDeleteLine,
1505
+ vimChangeLine,
1506
+ vimDeleteToEndOfLine,
1507
+ vimChangeToEndOfLine,
1508
+ vimChangeMovement,
1509
+ vimMoveLeft,
1510
+ vimMoveRight,
1511
+ vimMoveUp,
1512
+ vimMoveDown,
1513
+ vimMoveWordForward,
1514
+ vimMoveWordBackward,
1515
+ vimMoveWordEnd,
1516
+ vimDeleteChar,
1517
+ vimInsertAtCursor,
1518
+ vimAppendAtCursor,
1519
+ vimOpenLineBelow,
1520
+ vimOpenLineAbove,
1521
+ vimAppendAtLineEnd,
1522
+ vimInsertAtLineStart,
1523
+ vimMoveToLineStart,
1524
+ vimMoveToLineEnd,
1525
+ vimMoveToFirstNonWhitespace,
1526
+ vimMoveToFirstLine,
1527
+ vimMoveToLastLine,
1528
+ vimMoveToLine,
1529
+ vimEscapeInsertMode,
1007
1530
  };
1008
1531
  return returnValue;
1009
1532
  }