@machina.ai/cell-cli 1.11.0-rc1 → 1.13.0-rc2
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.
- package/dist/package.json +16 -10
- package/dist/src/commands/extensions/disable.d.ts +1 -1
- package/dist/src/commands/extensions/disable.js +15 -7
- package/dist/src/commands/extensions/disable.js.map +1 -1
- package/dist/src/commands/extensions/enable.d.ts +1 -1
- package/dist/src/commands/extensions/enable.js +15 -7
- package/dist/src/commands/extensions/enable.js.map +1 -1
- package/dist/src/commands/extensions/install.js +14 -3
- package/dist/src/commands/extensions/install.js.map +1 -1
- package/dist/src/commands/extensions/install.test.js +39 -19
- package/dist/src/commands/extensions/install.test.js.map +1 -1
- package/dist/src/commands/extensions/link.js +14 -3
- package/dist/src/commands/extensions/link.js.map +1 -1
- package/dist/src/commands/extensions/list.js +13 -4
- package/dist/src/commands/extensions/list.js.map +1 -1
- package/dist/src/commands/extensions/uninstall.js +13 -2
- package/dist/src/commands/extensions/uninstall.js.map +1 -1
- package/dist/src/commands/extensions/update.js +18 -13
- package/dist/src/commands/extensions/update.js.map +1 -1
- package/dist/src/commands/extensions/validate.d.ts +12 -0
- package/dist/src/commands/extensions/validate.js +83 -0
- package/dist/src/commands/extensions/validate.js.map +1 -0
- package/dist/src/commands/extensions/validate.test.js +93 -0
- package/dist/src/commands/extensions/validate.test.js.map +1 -0
- package/dist/src/commands/extensions.js +3 -0
- package/dist/src/commands/extensions.js.map +1 -1
- package/dist/src/commands/mcp/add.test.js +3 -0
- package/dist/src/commands/mcp/add.test.js.map +1 -1
- package/dist/src/commands/mcp/list.js +10 -3
- package/dist/src/commands/mcp/list.js.map +1 -1
- package/dist/src/commands/mcp/list.test.js +37 -27
- package/dist/src/commands/mcp/list.test.js.map +1 -1
- package/dist/src/config/auth.js +0 -5
- package/dist/src/config/auth.js.map +1 -1
- package/dist/src/config/config.d.ts +6 -3
- package/dist/src/config/config.js +65 -80
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +235 -212
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/extension-manager.d.ts +63 -0
- package/dist/src/config/extension-manager.js +450 -0
- package/dist/src/config/extension-manager.js.map +1 -0
- package/dist/src/config/extension.d.ts +4 -51
- package/dist/src/config/extension.js +1 -535
- package/dist/src/config/extension.js.map +1 -1
- package/dist/src/config/extension.test.js +525 -201
- package/dist/src/config/extension.test.js.map +1 -1
- package/dist/src/config/extensions/consent.d.ts +38 -0
- package/dist/src/config/extensions/consent.js +123 -0
- package/dist/src/config/extensions/consent.js.map +1 -0
- package/dist/src/config/extensions/extensionEnablement.d.ts +1 -1
- package/dist/src/config/extensions/extensionEnablement.js +4 -3
- package/dist/src/config/extensions/extensionEnablement.js.map +1 -1
- package/dist/src/config/extensions/extensionEnablement.test.js +10 -10
- package/dist/src/config/extensions/extensionEnablement.test.js.map +1 -1
- package/dist/src/config/extensions/extensionSettings.d.ts +15 -0
- package/dist/src/config/extensions/extensionSettings.js +113 -0
- package/dist/src/config/extensions/extensionSettings.js.map +1 -0
- package/dist/src/config/extensions/extensionSettings.test.d.ts +6 -0
- package/dist/src/config/extensions/extensionSettings.test.js +254 -0
- package/dist/src/config/extensions/extensionSettings.test.js.map +1 -0
- package/dist/src/config/extensions/github.d.ts +2 -2
- package/dist/src/config/extensions/github.js +5 -10
- package/dist/src/config/extensions/github.js.map +1 -1
- package/dist/src/config/extensions/github.test.js +153 -167
- package/dist/src/config/extensions/github.test.js.map +1 -1
- package/dist/src/config/extensions/github_fetch.d.ts +1 -1
- package/dist/src/config/extensions/github_fetch.js +13 -1
- package/dist/src/config/extensions/github_fetch.js.map +1 -1
- package/dist/src/config/extensions/github_fetch.test.d.ts +6 -0
- package/dist/src/config/extensions/github_fetch.test.js +169 -0
- package/dist/src/config/extensions/github_fetch.test.js.map +1 -0
- package/dist/src/config/extensions/storage.d.ts +14 -0
- package/dist/src/config/extensions/storage.js +32 -0
- package/dist/src/config/extensions/storage.js.map +1 -0
- package/dist/src/config/extensions/update.d.ts +4 -4
- package/dist/src/config/extensions/update.js +39 -39
- package/dist/src/config/extensions/update.js.map +1 -1
- package/dist/src/config/extensions/update.test.js +72 -74
- package/dist/src/config/extensions/update.test.js.map +1 -1
- package/dist/src/config/extensions/variableSchema.d.ts +0 -6
- package/dist/src/config/extensions/variableSchema.js.map +1 -1
- package/dist/src/config/extensions/variables.d.ts +4 -0
- package/dist/src/config/extensions/variables.js +6 -0
- package/dist/src/config/extensions/variables.js.map +1 -1
- package/dist/src/config/keyBindings.d.ts +3 -0
- package/dist/src/config/keyBindings.js +30 -8
- package/dist/src/config/keyBindings.js.map +1 -1
- package/dist/src/config/keyBindings.test.js +17 -0
- package/dist/src/config/keyBindings.test.js.map +1 -1
- package/dist/src/config/policies/read-only.toml +56 -0
- package/dist/src/config/policies/write.toml +63 -0
- package/dist/src/config/policies/yolo.toml +31 -0
- package/dist/src/config/policy-engine.integration.test.js +41 -38
- package/dist/src/config/policy-engine.integration.test.js.map +1 -1
- package/dist/src/config/policy.d.ts +2 -2
- package/dist/src/config/policy.js +10 -148
- package/dist/src/config/policy.js.map +1 -1
- package/dist/src/config/sandboxConfig.d.ts +1 -1
- package/dist/src/config/sandboxConfig.js +6 -3
- package/dist/src/config/sandboxConfig.js.map +1 -1
- package/dist/src/config/settings.d.ts +2 -1
- package/dist/src/config/settings.js +58 -18
- package/dist/src/config/settings.js.map +1 -1
- package/dist/src/config/settings.test.js +128 -69
- package/dist/src/config/settings.test.js.map +1 -1
- package/dist/src/config/settingsSchema.d.ts +170 -28
- package/dist/src/config/settingsSchema.js +418 -27
- package/dist/src/config/settingsSchema.js.map +1 -1
- package/dist/src/config/settingsSchema.test.js +42 -1
- package/dist/src/config/settingsSchema.test.js.map +1 -1
- package/dist/src/config/trustedFolders.d.ts +1 -1
- package/dist/src/config/trustedFolders.js +4 -2
- package/dist/src/config/trustedFolders.js.map +1 -1
- package/dist/src/core/initializer.js +2 -1
- package/dist/src/core/initializer.js.map +1 -1
- package/dist/src/gemini.d.ts +1 -1
- package/dist/src/gemini.js +46 -16
- package/dist/src/gemini.js.map +1 -1
- package/dist/src/gemini.test.js +88 -30
- package/dist/src/gemini.test.js.map +1 -1
- package/dist/src/generated/git-commit.d.ts +2 -2
- package/dist/src/generated/git-commit.js +2 -2
- package/dist/src/nonInteractiveCli.d.ts +9 -1
- package/dist/src/nonInteractiveCli.js +114 -7
- package/dist/src/nonInteractiveCli.js.map +1 -1
- package/dist/src/nonInteractiveCli.test.js +355 -112
- package/dist/src/nonInteractiveCli.test.js.map +1 -1
- package/dist/src/services/BuiltinCommandLoader.js +4 -0
- package/dist/src/services/BuiltinCommandLoader.js.map +1 -1
- package/dist/src/services/BuiltinCommandLoader.test.js +22 -0
- package/dist/src/services/BuiltinCommandLoader.test.js.map +1 -1
- package/dist/src/services/FeedbackService.js +2 -2
- package/dist/src/services/FeedbackService.js.map +1 -1
- package/dist/src/services/McpPromptLoader.js +2 -2
- package/dist/src/services/McpPromptLoader.js.map +1 -1
- package/dist/src/services/McpPromptLoader.test.js +4 -2
- package/dist/src/services/McpPromptLoader.test.js.map +1 -1
- package/dist/src/test-utils/async.d.ts +9 -0
- package/dist/src/test-utils/async.js +29 -0
- package/dist/src/test-utils/async.js.map +1 -0
- package/dist/src/test-utils/createExtension.d.ts +3 -1
- package/dist/src/test-utils/createExtension.js +3 -3
- package/dist/src/test-utils/createExtension.js.map +1 -1
- package/dist/src/test-utils/render.d.ts +16 -2
- package/dist/src/test-utils/render.js +66 -4
- package/dist/src/test-utils/render.js.map +1 -1
- package/dist/src/test-utils/render.test.d.ts +6 -0
- package/dist/src/test-utils/render.test.js +79 -0
- package/dist/src/test-utils/render.test.js.map +1 -0
- package/dist/src/ui/App.test.js +1 -1
- package/dist/src/ui/App.test.js.map +1 -1
- package/dist/src/ui/AppContainer.js +181 -65
- package/dist/src/ui/AppContainer.js.map +1 -1
- package/dist/src/ui/AppContainer.test.js +505 -147
- package/dist/src/ui/AppContainer.test.js.map +1 -1
- package/dist/src/ui/IdeIntegrationNudge.js +1 -1
- package/dist/src/ui/IdeIntegrationNudge.js.map +1 -1
- package/dist/src/ui/auth/ApiAuthDialog.d.ts +14 -0
- package/dist/src/ui/auth/ApiAuthDialog.js +26 -0
- package/dist/src/ui/auth/ApiAuthDialog.js.map +1 -0
- package/dist/src/ui/auth/ApiAuthDialog.test.d.ts +6 -0
- package/dist/src/ui/auth/ApiAuthDialog.test.js +91 -0
- package/dist/src/ui/auth/ApiAuthDialog.test.js.map +1 -0
- package/dist/src/ui/auth/AuthDialog.js +7 -3
- package/dist/src/ui/auth/AuthDialog.js.map +1 -1
- package/dist/src/ui/auth/useAuth.d.ts +2 -0
- package/dist/src/ui/auth/useAuth.js +31 -2
- package/dist/src/ui/auth/useAuth.js.map +1 -1
- package/dist/src/ui/colors.js +3 -0
- package/dist/src/ui/colors.js.map +1 -1
- package/dist/src/ui/commands/directoryCommand.js +1 -1
- package/dist/src/ui/commands/directoryCommand.js.map +1 -1
- package/dist/src/ui/commands/extensionsCommand.js +64 -11
- package/dist/src/ui/commands/extensionsCommand.js.map +1 -1
- package/dist/src/ui/commands/extensionsCommand.test.js +72 -1
- package/dist/src/ui/commands/extensionsCommand.test.js.map +1 -1
- package/dist/src/ui/commands/mcpCommand.js +14 -14
- package/dist/src/ui/commands/mcpCommand.js.map +1 -1
- package/dist/src/ui/commands/mcpCommand.test.js +4 -0
- package/dist/src/ui/commands/mcpCommand.test.js.map +1 -1
- package/dist/src/ui/commands/memoryCommand.js +1 -1
- package/dist/src/ui/commands/memoryCommand.js.map +1 -1
- package/dist/src/ui/commands/memoryCommand.test.js +3 -1
- package/dist/src/ui/commands/memoryCommand.test.js.map +1 -1
- package/dist/src/ui/commands/policiesCommand.d.ts +7 -0
- package/dist/src/ui/commands/policiesCommand.js +59 -0
- package/dist/src/ui/commands/policiesCommand.js.map +1 -0
- package/dist/src/ui/commands/policiesCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/policiesCommand.test.js +83 -0
- package/dist/src/ui/commands/policiesCommand.test.js.map +1 -0
- package/dist/src/ui/components/AnsiOutput.test.js +1 -1
- package/dist/src/ui/components/AnsiOutput.test.js.map +1 -1
- package/dist/src/ui/components/AsciiArt.d.ts +3 -3
- package/dist/src/ui/components/AsciiArt.js +3 -3
- package/dist/src/ui/components/Composer.js +1 -1
- package/dist/src/ui/components/Composer.js.map +1 -1
- package/dist/src/ui/components/Composer.test.js +5 -2
- package/dist/src/ui/components/Composer.test.js.map +1 -1
- package/dist/src/ui/components/ConfigInitDisplay.js +4 -6
- package/dist/src/ui/components/ConfigInitDisplay.js.map +1 -1
- package/dist/src/ui/components/ConsentPrompt.test.js +18 -8
- package/dist/src/ui/components/ConsentPrompt.test.js.map +1 -1
- package/dist/src/ui/components/ConsoleSummaryDisplay.js +1 -1
- package/dist/src/ui/components/ConsoleSummaryDisplay.js.map +1 -1
- package/dist/src/ui/components/ContextSummaryDisplay.test.js +11 -6
- package/dist/src/ui/components/ContextSummaryDisplay.test.js.map +1 -1
- package/dist/src/ui/components/DetailedMessagesDisplay.js +1 -1
- package/dist/src/ui/components/DetailedMessagesDisplay.js.map +1 -1
- package/dist/src/ui/components/DialogManager.js +4 -0
- package/dist/src/ui/components/DialogManager.js.map +1 -1
- package/dist/src/ui/components/FolderTrustDialog.test.js +2 -1
- package/dist/src/ui/components/FolderTrustDialog.test.js.map +1 -1
- package/dist/src/ui/components/Footer.js +4 -3
- package/dist/src/ui/components/Footer.js.map +1 -1
- package/dist/src/ui/components/Footer.test.js +83 -0
- package/dist/src/ui/components/Footer.test.js.map +1 -1
- package/dist/src/ui/components/Header.test.js +13 -5
- package/dist/src/ui/components/Header.test.js.map +1 -1
- package/dist/src/ui/components/Help.test.js +5 -4
- package/dist/src/ui/components/Help.test.js.map +1 -1
- package/dist/src/ui/components/HistoryItemDisplay.js +1 -1
- package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
- package/dist/src/ui/components/InputPrompt.js +27 -8
- package/dist/src/ui/components/InputPrompt.js.map +1 -1
- package/dist/src/ui/components/InputPrompt.test.js +776 -727
- package/dist/src/ui/components/InputPrompt.test.js.map +1 -1
- package/dist/src/ui/components/LoadingIndicator.js +2 -2
- package/dist/src/ui/components/LoadingIndicator.js.map +1 -1
- package/dist/src/ui/components/LoadingIndicator.test.js +28 -15
- package/dist/src/ui/components/LoadingIndicator.test.js.map +1 -1
- package/dist/src/ui/components/LoopDetectionConfirmation.js +1 -1
- package/dist/src/ui/components/LoopDetectionConfirmation.js.map +1 -1
- package/dist/src/ui/components/LoopDetectionConfirmation.test.js +2 -2
- package/dist/src/ui/components/LoopDetectionConfirmation.test.js.map +1 -1
- package/dist/src/ui/components/MainContent.js +15 -4
- package/dist/src/ui/components/MainContent.js.map +1 -1
- package/dist/src/ui/components/ModelDialog.js +1 -1
- package/dist/src/ui/components/ModelDialog.js.map +1 -1
- package/dist/src/ui/components/ModelDialog.test.js +23 -13
- package/dist/src/ui/components/ModelDialog.test.js.map +1 -1
- package/dist/src/ui/components/ModelStatsDisplay.test.js +1 -1
- package/dist/src/ui/components/ModelStatsDisplay.test.js.map +1 -1
- package/dist/src/ui/components/Notifications.js +38 -5
- package/dist/src/ui/components/Notifications.js.map +1 -1
- package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js +2 -2
- package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js.map +1 -1
- package/dist/src/ui/components/PrepareLabel.test.js +14 -8
- package/dist/src/ui/components/PrepareLabel.test.js.map +1 -1
- package/dist/src/ui/components/ProQuotaDialog.test.js +14 -6
- package/dist/src/ui/components/ProQuotaDialog.test.js.map +1 -1
- package/dist/src/ui/components/QueuedMessageDisplay.test.js +11 -6
- package/dist/src/ui/components/QueuedMessageDisplay.test.js.map +1 -1
- package/dist/src/ui/components/SessionSummaryDisplay.test.js +1 -1
- package/dist/src/ui/components/SessionSummaryDisplay.test.js.map +1 -1
- package/dist/src/ui/components/SettingsDialog.js +32 -25
- package/dist/src/ui/components/SettingsDialog.js.map +1 -1
- package/dist/src/ui/components/SettingsDialog.test.js +428 -532
- package/dist/src/ui/components/SettingsDialog.test.js.map +1 -1
- package/dist/src/ui/components/ShellConfirmationDialog.js +1 -1
- package/dist/src/ui/components/ShellConfirmationDialog.js.map +1 -1
- package/dist/src/ui/components/ShellConfirmationDialog.test.js +2 -2
- package/dist/src/ui/components/ShellConfirmationDialog.test.js.map +1 -1
- package/dist/src/ui/components/StatsDisplay.test.js +1 -1
- package/dist/src/ui/components/StatsDisplay.test.js.map +1 -1
- package/dist/src/ui/components/SuggestionsDisplay.js +1 -1
- package/dist/src/ui/components/SuggestionsDisplay.js.map +1 -1
- package/dist/src/ui/components/ThemeDialog.test.js +2 -2
- package/dist/src/ui/components/ThemeDialog.test.js.map +1 -1
- package/dist/src/ui/components/ToolStatsDisplay.test.js +1 -1
- package/dist/src/ui/components/ToolStatsDisplay.test.js.map +1 -1
- package/dist/src/ui/components/messages/CompressionMessage.test.js +25 -17
- package/dist/src/ui/components/messages/CompressionMessage.test.js.map +1 -1
- package/dist/src/ui/components/messages/DiffRenderer.test.js +1 -1
- package/dist/src/ui/components/messages/DiffRenderer.test.js.map +1 -1
- package/dist/src/ui/components/messages/InfoMessage.js +1 -1
- package/dist/src/ui/components/messages/InfoMessage.js.map +1 -1
- package/dist/src/ui/components/messages/Todo.js +27 -5
- package/dist/src/ui/components/messages/Todo.js.map +1 -1
- package/dist/src/ui/components/messages/Todo.test.js +20 -8
- package/dist/src/ui/components/messages/Todo.test.js.map +1 -1
- package/dist/src/ui/components/messages/ToolConfirmationMessage.js +1 -1
- package/dist/src/ui/components/messages/ToolConfirmationMessage.js.map +1 -1
- package/dist/src/ui/components/messages/ToolGroupMessage.test.js +29 -15
- package/dist/src/ui/components/messages/ToolGroupMessage.test.js.map +1 -1
- package/dist/src/ui/components/messages/WarningMessage.js +2 -2
- package/dist/src/ui/components/messages/WarningMessage.js.map +1 -1
- package/dist/src/ui/components/shared/BaseSelectionList.test.js +1 -1
- package/dist/src/ui/components/shared/BaseSelectionList.test.js.map +1 -1
- package/dist/src/ui/components/shared/MaxSizedBox.test.js +43 -22
- package/dist/src/ui/components/shared/MaxSizedBox.test.js.map +1 -1
- package/dist/src/ui/components/shared/TextInput.d.ts +15 -0
- package/dist/src/ui/components/shared/TextInput.js +38 -0
- package/dist/src/ui/components/shared/TextInput.js.map +1 -0
- package/dist/src/ui/components/shared/TextInput.test.d.ts +6 -0
- package/dist/src/ui/components/shared/TextInput.test.js +242 -0
- package/dist/src/ui/components/shared/TextInput.test.js.map +1 -0
- package/dist/src/ui/components/shared/text-buffer.d.ts +9 -2
- package/dist/src/ui/components/shared/text-buffer.js +51 -13
- package/dist/src/ui/components/shared/text-buffer.js.map +1 -1
- package/dist/src/ui/components/shared/text-buffer.test.js +385 -202
- package/dist/src/ui/components/shared/text-buffer.test.js.map +1 -1
- package/dist/src/ui/components/views/ChatList.test.js +7 -4
- package/dist/src/ui/components/views/ChatList.test.js.map +1 -1
- package/dist/src/ui/components/views/ExtensionsList.d.ts +7 -1
- package/dist/src/ui/components/views/ExtensionsList.js +9 -11
- package/dist/src/ui/components/views/ExtensionsList.js.map +1 -1
- package/dist/src/ui/components/views/ExtensionsList.test.js +43 -22
- package/dist/src/ui/components/views/ExtensionsList.test.js.map +1 -1
- package/dist/src/ui/components/views/McpStatus.test.js +23 -12
- package/dist/src/ui/components/views/McpStatus.test.js.map +1 -1
- package/dist/src/ui/contexts/KeypressContext.d.ts +3 -2
- package/dist/src/ui/contexts/KeypressContext.js +610 -540
- package/dist/src/ui/contexts/KeypressContext.js.map +1 -1
- package/dist/src/ui/contexts/KeypressContext.test.js +438 -718
- package/dist/src/ui/contexts/KeypressContext.test.js.map +1 -1
- package/dist/src/ui/contexts/MouseContext.d.ts +21 -0
- package/dist/src/ui/contexts/MouseContext.js +89 -0
- package/dist/src/ui/contexts/MouseContext.js.map +1 -0
- package/dist/src/ui/contexts/MouseContext.test.d.ts +6 -0
- package/dist/src/ui/contexts/MouseContext.test.js +164 -0
- package/dist/src/ui/contexts/MouseContext.test.js.map +1 -0
- package/dist/src/ui/contexts/SessionContext.test.js +35 -17
- package/dist/src/ui/contexts/SessionContext.test.js.map +1 -1
- package/dist/src/ui/contexts/UIActionsContext.d.ts +2 -0
- package/dist/src/ui/contexts/UIActionsContext.js.map +1 -1
- package/dist/src/ui/contexts/UIStateContext.d.ts +2 -0
- package/dist/src/ui/contexts/UIStateContext.js.map +1 -1
- package/dist/src/ui/hooks/atCommandProcessor.js +31 -9
- package/dist/src/ui/hooks/atCommandProcessor.js.map +1 -1
- package/dist/src/ui/hooks/atCommandProcessor.test.js +163 -64
- package/dist/src/ui/hooks/atCommandProcessor.test.js.map +1 -1
- package/dist/src/ui/hooks/shellCommandProcessor.test.js +64 -35
- package/dist/src/ui/hooks/shellCommandProcessor.test.js.map +1 -1
- package/dist/src/ui/hooks/slashCommandProcessor.test.js +193 -165
- package/dist/src/ui/hooks/slashCommandProcessor.test.js.map +1 -1
- package/dist/src/ui/hooks/useAtCompletion.test.js +16 -5
- package/dist/src/ui/hooks/useAtCompletion.test.js.map +1 -1
- package/dist/src/ui/hooks/useAutoAcceptIndicator.js +10 -0
- package/dist/src/ui/hooks/useAutoAcceptIndicator.js.map +1 -1
- package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js +32 -1
- package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js.map +1 -1
- package/dist/src/ui/hooks/useCommandCompletion.test.js +66 -64
- package/dist/src/ui/hooks/useCommandCompletion.test.js.map +1 -1
- package/dist/src/ui/hooks/useConsoleMessages.test.js +26 -9
- package/dist/src/ui/hooks/useConsoleMessages.test.js.map +1 -1
- package/dist/src/ui/hooks/useEditorSettings.test.js +40 -34
- package/dist/src/ui/hooks/useEditorSettings.test.js.map +1 -1
- package/dist/src/ui/hooks/useExtensionUpdates.d.ts +14 -5
- package/dist/src/ui/hooks/useExtensionUpdates.js +18 -13
- package/dist/src/ui/hooks/useExtensionUpdates.js.map +1 -1
- package/dist/src/ui/hooks/useExtensionUpdates.test.js +49 -44
- package/dist/src/ui/hooks/useExtensionUpdates.test.js.map +1 -1
- package/dist/src/ui/hooks/useFlickerDetector.test.js +9 -5
- package/dist/src/ui/hooks/useFlickerDetector.test.js.map +1 -1
- package/dist/src/ui/hooks/useFocus.test.js +25 -9
- package/dist/src/ui/hooks/useFocus.test.js.map +1 -1
- package/dist/src/ui/hooks/useFolderTrust.test.js +46 -22
- package/dist/src/ui/hooks/useFolderTrust.test.js.map +1 -1
- package/dist/src/ui/hooks/useGeminiStream.js +56 -19
- package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
- package/dist/src/ui/hooks/useGeminiStream.test.js +260 -411
- package/dist/src/ui/hooks/useGeminiStream.test.js.map +1 -1
- package/dist/src/ui/hooks/useGitBranchName.js +4 -0
- package/dist/src/ui/hooks/useGitBranchName.js.map +1 -1
- package/dist/src/ui/hooks/useGitBranchName.test.js +46 -34
- package/dist/src/ui/hooks/useGitBranchName.test.js.map +1 -1
- package/dist/src/ui/hooks/useHistoryManager.test.js +2 -1
- package/dist/src/ui/hooks/useHistoryManager.test.js.map +1 -1
- package/dist/src/ui/hooks/useIdeTrustListener.test.js +40 -9
- package/dist/src/ui/hooks/useIdeTrustListener.test.js.map +1 -1
- package/dist/src/ui/hooks/useInputHistory.test.js +2 -1
- package/dist/src/ui/hooks/useInputHistory.test.js.map +1 -1
- package/dist/src/ui/hooks/useInputHistoryStore.test.js +2 -1
- package/dist/src/ui/hooks/useInputHistoryStore.test.js.map +1 -1
- package/dist/src/ui/hooks/useKeypress.test.js +103 -114
- package/dist/src/ui/hooks/useKeypress.test.js.map +1 -1
- package/dist/src/ui/hooks/useLoadingIndicator.test.js +24 -6
- package/dist/src/ui/hooks/useLoadingIndicator.test.js.map +1 -1
- package/dist/src/ui/hooks/useMemoryMonitor.test.js +10 -5
- package/dist/src/ui/hooks/useMemoryMonitor.test.js.map +1 -1
- package/dist/src/ui/hooks/useMessageQueue.test.js +62 -45
- package/dist/src/ui/hooks/useMessageQueue.test.js.map +1 -1
- package/dist/src/ui/hooks/useModelCommand.test.js +21 -11
- package/dist/src/ui/hooks/useModelCommand.test.js.map +1 -1
- package/dist/src/ui/hooks/useMouse.d.ts +17 -0
- package/dist/src/ui/hooks/useMouse.js +27 -0
- package/dist/src/ui/hooks/useMouse.js.map +1 -0
- package/dist/src/ui/hooks/useMouse.test.d.ts +6 -0
- package/dist/src/ui/hooks/useMouse.test.js +57 -0
- package/dist/src/ui/hooks/useMouse.test.js.map +1 -0
- package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js +2 -2
- package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js.map +1 -1
- package/dist/src/ui/hooks/usePhraseCycler.js +1 -1
- package/dist/src/ui/hooks/usePhraseCycler.js.map +1 -1
- package/dist/src/ui/hooks/usePhraseCycler.test.js +109 -106
- package/dist/src/ui/hooks/usePhraseCycler.test.js.map +1 -1
- package/dist/src/ui/hooks/usePrivacySettings.test.js +26 -6
- package/dist/src/ui/hooks/usePrivacySettings.test.js.map +1 -1
- package/dist/src/ui/hooks/usePromptCompletion.js +2 -2
- package/dist/src/ui/hooks/usePromptCompletion.js.map +1 -1
- package/dist/src/ui/hooks/useQuotaAndFallback.js +13 -14
- package/dist/src/ui/hooks/useQuotaAndFallback.js.map +1 -1
- package/dist/src/ui/hooks/useQuotaAndFallback.test.js +55 -48
- package/dist/src/ui/hooks/useQuotaAndFallback.test.js.map +1 -1
- package/dist/src/ui/hooks/useReactToolScheduler.d.ts +8 -1
- package/dist/src/ui/hooks/useReactToolScheduler.js +59 -34
- package/dist/src/ui/hooks/useReactToolScheduler.js.map +1 -1
- package/dist/src/ui/hooks/useReactToolScheduler.test.d.ts +6 -0
- package/dist/src/ui/hooks/useReactToolScheduler.test.js +65 -0
- package/dist/src/ui/hooks/useReactToolScheduler.test.js.map +1 -0
- package/dist/src/ui/hooks/useReverseSearchCompletion.test.js +2 -2
- package/dist/src/ui/hooks/useReverseSearchCompletion.test.js.map +1 -1
- package/dist/src/ui/hooks/useSelectionList.js +5 -4
- package/dist/src/ui/hooks/useSelectionList.js.map +1 -1
- package/dist/src/ui/hooks/useSelectionList.test.js +272 -183
- package/dist/src/ui/hooks/useSelectionList.test.js.map +1 -1
- package/dist/src/ui/hooks/useShellHistory.test.js +52 -20
- package/dist/src/ui/hooks/useShellHistory.test.js.map +1 -1
- package/dist/src/ui/hooks/useSlashCompletion.js +18 -7
- package/dist/src/ui/hooks/useSlashCompletion.js.map +1 -1
- package/dist/src/ui/hooks/useSlashCompletion.test.js +275 -137
- package/dist/src/ui/hooks/useSlashCompletion.test.js.map +1 -1
- package/dist/src/ui/hooks/useTimer.test.js +43 -14
- package/dist/src/ui/hooks/useTimer.test.js.map +1 -1
- package/dist/src/ui/hooks/useToolScheduler.test.js +226 -242
- package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -1
- package/dist/src/ui/hooks/vim.test.js +235 -355
- package/dist/src/ui/hooks/vim.test.js.map +1 -1
- package/dist/src/ui/keyMatchers.test.js +30 -3
- package/dist/src/ui/keyMatchers.test.js.map +1 -1
- package/dist/src/ui/state/extensions.d.ts +1 -0
- package/dist/src/ui/state/extensions.js +1 -0
- package/dist/src/ui/state/extensions.js.map +1 -1
- package/dist/src/ui/themes/ansi-light.js +1 -0
- package/dist/src/ui/themes/ansi-light.js.map +1 -1
- package/dist/src/ui/themes/ansi.js +1 -0
- package/dist/src/ui/themes/ansi.js.map +1 -1
- package/dist/src/ui/themes/atom-one-dark.js +2 -0
- package/dist/src/ui/themes/atom-one-dark.js.map +1 -1
- package/dist/src/ui/themes/ayu-light.js +2 -0
- package/dist/src/ui/themes/ayu-light.js.map +1 -1
- package/dist/src/ui/themes/ayu.js +2 -0
- package/dist/src/ui/themes/ayu.js.map +1 -1
- package/dist/src/ui/themes/color-utils.d.ts +1 -0
- package/dist/src/ui/themes/color-utils.js +6 -0
- package/dist/src/ui/themes/color-utils.js.map +1 -1
- package/dist/src/ui/themes/color-utils.test.js +13 -1
- package/dist/src/ui/themes/color-utils.test.js.map +1 -1
- package/dist/src/ui/themes/dracula.js +2 -0
- package/dist/src/ui/themes/dracula.js.map +1 -1
- package/dist/src/ui/themes/github-dark.js +2 -0
- package/dist/src/ui/themes/github-dark.js.map +1 -1
- package/dist/src/ui/themes/github-light.js +2 -0
- package/dist/src/ui/themes/github-light.js.map +1 -1
- package/dist/src/ui/themes/googlecode.js +2 -0
- package/dist/src/ui/themes/googlecode.js.map +1 -1
- package/dist/src/ui/themes/no-color.js +3 -0
- package/dist/src/ui/themes/no-color.js.map +1 -1
- package/dist/src/ui/themes/semantic-tokens.d.ts +2 -0
- package/dist/src/ui/themes/semantic-tokens.js +6 -0
- package/dist/src/ui/themes/semantic-tokens.js.map +1 -1
- package/dist/src/ui/themes/shades-of-purple.js +2 -0
- package/dist/src/ui/themes/shades-of-purple.js.map +1 -1
- package/dist/src/ui/themes/theme.d.ts +3 -0
- package/dist/src/ui/themes/theme.js +14 -3
- package/dist/src/ui/themes/theme.js.map +1 -1
- package/dist/src/ui/themes/theme.test.js +67 -1
- package/dist/src/ui/themes/theme.test.js.map +1 -1
- package/dist/src/ui/themes/xcode.js +2 -0
- package/dist/src/ui/themes/xcode.js.map +1 -1
- package/dist/src/ui/types.d.ts +3 -1
- package/dist/src/ui/types.js +2 -0
- package/dist/src/ui/types.js.map +1 -1
- package/dist/src/ui/utils/CodeColorizer.js +2 -1
- package/dist/src/ui/utils/CodeColorizer.js.map +1 -1
- package/dist/src/ui/utils/InlineMarkdownRenderer.d.ts +1 -0
- package/dist/src/ui/utils/InlineMarkdownRenderer.js +11 -10
- package/dist/src/ui/utils/InlineMarkdownRenderer.js.map +1 -1
- package/dist/src/ui/utils/MarkdownDisplay.js +11 -9
- package/dist/src/ui/utils/MarkdownDisplay.js.map +1 -1
- package/dist/src/ui/utils/clipboardUtils.js +2 -2
- package/dist/src/ui/utils/clipboardUtils.js.map +1 -1
- package/dist/src/ui/utils/input.d.ts +17 -0
- package/dist/src/ui/utils/input.js +51 -0
- package/dist/src/ui/utils/input.js.map +1 -0
- package/dist/src/ui/utils/input.test.d.ts +6 -0
- package/dist/src/ui/utils/input.test.js +44 -0
- package/dist/src/ui/utils/input.test.js.map +1 -0
- package/dist/src/ui/utils/kittyProtocolDetector.js +13 -4
- package/dist/src/ui/utils/kittyProtocolDetector.js.map +1 -1
- package/dist/src/ui/utils/mouse.d.ts +31 -0
- package/dist/src/ui/utils/mouse.js +164 -0
- package/dist/src/ui/utils/mouse.js.map +1 -0
- package/dist/src/ui/utils/mouse.test.d.ts +6 -0
- package/dist/src/ui/utils/mouse.test.js +131 -0
- package/dist/src/ui/utils/mouse.test.js.map +1 -0
- package/dist/src/ui/utils/textOutput.d.ts +25 -0
- package/dist/src/ui/utils/textOutput.js +49 -0
- package/dist/src/ui/utils/textOutput.js.map +1 -0
- package/dist/src/ui/utils/textOutput.test.d.ts +6 -0
- package/dist/src/ui/utils/textOutput.test.js +79 -0
- package/dist/src/ui/utils/textOutput.test.js.map +1 -0
- package/dist/src/ui/utils/updateCheck.d.ts +7 -1
- package/dist/src/ui/utils/updateCheck.js +33 -29
- package/dist/src/ui/utils/updateCheck.js.map +1 -1
- package/dist/src/ui/utils/updateCheck.test.js +24 -50
- package/dist/src/ui/utils/updateCheck.test.js.map +1 -1
- package/dist/src/utils/commentJson.js +2 -2
- package/dist/src/utils/commentJson.js.map +1 -1
- package/dist/src/utils/commentJson.test.js +7 -6
- package/dist/src/utils/commentJson.test.js.map +1 -1
- package/dist/src/utils/envVarResolver.d.ts +2 -2
- package/dist/src/utils/envVarResolver.js +10 -7
- package/dist/src/utils/envVarResolver.js.map +1 -1
- package/dist/src/utils/events.d.ts +11 -2
- package/dist/src/utils/events.js +1 -0
- package/dist/src/utils/events.js.map +1 -1
- package/dist/src/utils/handleAutoUpdate.js +9 -3
- package/dist/src/utils/handleAutoUpdate.js.map +1 -1
- package/dist/src/utils/sandbox.js +16 -18
- package/dist/src/utils/sandbox.js.map +1 -1
- package/dist/src/utils/version.js +6 -2
- package/dist/src/utils/version.js.map +1 -1
- package/dist/src/zed-integration/acp.js +2 -1
- package/dist/src/zed-integration/acp.js.map +1 -1
- package/dist/src/zed-integration/schema.d.ts +4 -4
- package/dist/src/zed-integration/zedIntegration.d.ts +2 -2
- package/dist/src/zed-integration/zedIntegration.js +12 -19
- package/dist/src/zed-integration/zedIntegration.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +18 -14
- package/dist/src/config/policy.test.js +0 -360
- package/dist/src/config/policy.test.js.map +0 -1
- package/dist/src/utils/package.d.ts +0 -12
- package/dist/src/utils/package.js +0 -24
- package/dist/src/utils/package.js.map +0 -1
- /package/dist/src/{config/policy.test.d.ts → commands/extensions/validate.test.d.ts} +0 -0
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { describe, it, expect, beforeEach } from 'vitest';
|
|
7
7
|
import stripAnsi from 'strip-ansi';
|
|
8
|
-
import {
|
|
8
|
+
import { act } from 'react';
|
|
9
|
+
import { renderHook } from '../../../test-utils/render.js';
|
|
9
10
|
import { useTextBuffer, offsetToLogicalPos, logicalPosToOffset, textBufferReducer, findWordEndInLine, findNextWordStartInLine, isWordCharStrict, } from './text-buffer.js';
|
|
10
11
|
import { cpLen } from '../../utils/textUtils.js';
|
|
11
12
|
const defaultVisualLayout = {
|
|
@@ -76,6 +77,40 @@ describe('textBufferReducer', () => {
|
|
|
76
77
|
expect(state.cursorCol).toBe(0);
|
|
77
78
|
});
|
|
78
79
|
});
|
|
80
|
+
describe('insert action with options', () => {
|
|
81
|
+
it('should filter input using inputFilter option', () => {
|
|
82
|
+
const action = { type: 'insert', payload: 'a1b2c3' };
|
|
83
|
+
const options = {
|
|
84
|
+
inputFilter: (text) => text.replace(/[0-9]/g, ''),
|
|
85
|
+
};
|
|
86
|
+
const state = textBufferReducer(initialState, action, options);
|
|
87
|
+
expect(state.lines).toEqual(['abc']);
|
|
88
|
+
expect(state.cursorCol).toBe(3);
|
|
89
|
+
});
|
|
90
|
+
it('should strip newlines when singleLine option is true', () => {
|
|
91
|
+
const action = {
|
|
92
|
+
type: 'insert',
|
|
93
|
+
payload: 'hello\nworld',
|
|
94
|
+
};
|
|
95
|
+
const options = { singleLine: true };
|
|
96
|
+
const state = textBufferReducer(initialState, action, options);
|
|
97
|
+
expect(state.lines).toEqual(['helloworld']);
|
|
98
|
+
expect(state.cursorCol).toBe(10);
|
|
99
|
+
});
|
|
100
|
+
it('should apply both inputFilter and singleLine options', () => {
|
|
101
|
+
const action = {
|
|
102
|
+
type: 'insert',
|
|
103
|
+
payload: 'h\ne\nl\nl\no\n1\n2\n3',
|
|
104
|
+
};
|
|
105
|
+
const options = {
|
|
106
|
+
singleLine: true,
|
|
107
|
+
inputFilter: (text) => text.replace(/[0-9]/g, ''),
|
|
108
|
+
};
|
|
109
|
+
const state = textBufferReducer(initialState, action, options);
|
|
110
|
+
expect(state.lines).toEqual(['hello']);
|
|
111
|
+
expect(state.cursorCol).toBe(5);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
79
114
|
describe('backspace action', () => {
|
|
80
115
|
it('should remove a character', () => {
|
|
81
116
|
const stateWithText = {
|
|
@@ -153,41 +188,38 @@ describe('textBufferReducer', () => {
|
|
|
153
188
|
});
|
|
154
189
|
});
|
|
155
190
|
describe('delete_word_left action', () => {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
191
|
+
const createSingleLineState = (text, col) => ({
|
|
192
|
+
...initialState,
|
|
193
|
+
lines: [text],
|
|
194
|
+
cursorRow: 0,
|
|
195
|
+
cursorCol: col,
|
|
196
|
+
});
|
|
197
|
+
it.each([
|
|
198
|
+
{
|
|
199
|
+
input: 'hello world',
|
|
161
200
|
cursorCol: 11,
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
it('should delete a path segment', () => {
|
|
169
|
-
const stateWithText = {
|
|
170
|
-
...initialState,
|
|
171
|
-
lines: ['path/to/file'],
|
|
172
|
-
cursorRow: 0,
|
|
201
|
+
expectedLines: ['hello '],
|
|
202
|
+
expectedCol: 6,
|
|
203
|
+
desc: 'simple word',
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
input: 'path/to/file',
|
|
173
207
|
cursorCol: 12,
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
it('should delete variable_name parts', () => {
|
|
181
|
-
const stateWithText = {
|
|
182
|
-
...initialState,
|
|
183
|
-
lines: ['variable_name'],
|
|
184
|
-
cursorRow: 0,
|
|
208
|
+
expectedLines: ['path/to/'],
|
|
209
|
+
expectedCol: 8,
|
|
210
|
+
desc: 'path segment',
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
input: 'variable_name',
|
|
185
214
|
cursorCol: 13,
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
215
|
+
expectedLines: ['variable_'],
|
|
216
|
+
expectedCol: 9,
|
|
217
|
+
desc: 'variable_name parts',
|
|
218
|
+
},
|
|
219
|
+
])('should delete $desc', ({ input, cursorCol, expectedLines, expectedCol }) => {
|
|
220
|
+
const state = textBufferReducer(createSingleLineState(input, cursorCol), { type: 'delete_word_left' });
|
|
221
|
+
expect(state.lines).toEqual(expectedLines);
|
|
222
|
+
expect(state.cursorCol).toBe(expectedCol);
|
|
191
223
|
});
|
|
192
224
|
it('should act like backspace at the beginning of a line', () => {
|
|
193
225
|
const stateWithText = {
|
|
@@ -196,51 +228,55 @@ describe('textBufferReducer', () => {
|
|
|
196
228
|
cursorRow: 1,
|
|
197
229
|
cursorCol: 0,
|
|
198
230
|
};
|
|
199
|
-
const
|
|
200
|
-
|
|
231
|
+
const state = textBufferReducer(stateWithText, {
|
|
232
|
+
type: 'delete_word_left',
|
|
233
|
+
});
|
|
201
234
|
expect(state.lines).toEqual(['helloworld']);
|
|
202
235
|
expect(state.cursorRow).toBe(0);
|
|
203
236
|
expect(state.cursorCol).toBe(5);
|
|
204
237
|
});
|
|
205
238
|
});
|
|
206
239
|
describe('delete_word_right action', () => {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
240
|
+
const createSingleLineState = (text, col) => ({
|
|
241
|
+
...initialState,
|
|
242
|
+
lines: [text],
|
|
243
|
+
cursorRow: 0,
|
|
244
|
+
cursorCol: col,
|
|
245
|
+
});
|
|
246
|
+
it.each([
|
|
247
|
+
{
|
|
248
|
+
input: 'hello world',
|
|
212
249
|
cursorCol: 0,
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
250
|
+
expectedLines: ['world'],
|
|
251
|
+
expectedCol: 0,
|
|
252
|
+
desc: 'simple word',
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
input: 'variable_name',
|
|
256
|
+
cursorCol: 0,
|
|
257
|
+
expectedLines: ['_name'],
|
|
258
|
+
expectedCol: 0,
|
|
259
|
+
desc: 'variable_name parts',
|
|
260
|
+
},
|
|
261
|
+
])('should delete $desc', ({ input, cursorCol, expectedLines, expectedCol }) => {
|
|
262
|
+
const state = textBufferReducer(createSingleLineState(input, cursorCol), { type: 'delete_word_right' });
|
|
263
|
+
expect(state.lines).toEqual(expectedLines);
|
|
264
|
+
expect(state.cursorCol).toBe(expectedCol);
|
|
265
|
+
});
|
|
266
|
+
it('should delete path segments progressively', () => {
|
|
220
267
|
const stateWithText = {
|
|
221
268
|
...initialState,
|
|
222
269
|
lines: ['path/to/file'],
|
|
223
270
|
cursorRow: 0,
|
|
224
271
|
cursorCol: 0,
|
|
225
272
|
};
|
|
226
|
-
|
|
227
|
-
|
|
273
|
+
let state = textBufferReducer(stateWithText, {
|
|
274
|
+
type: 'delete_word_right',
|
|
275
|
+
});
|
|
228
276
|
expect(state.lines).toEqual(['/to/file']);
|
|
229
|
-
state = textBufferReducer(state,
|
|
277
|
+
state = textBufferReducer(state, { type: 'delete_word_right' });
|
|
230
278
|
expect(state.lines).toEqual(['to/file']);
|
|
231
279
|
});
|
|
232
|
-
it('should delete variable_name parts', () => {
|
|
233
|
-
const stateWithText = {
|
|
234
|
-
...initialState,
|
|
235
|
-
lines: ['variable_name'],
|
|
236
|
-
cursorRow: 0,
|
|
237
|
-
cursorCol: 0,
|
|
238
|
-
};
|
|
239
|
-
const action = { type: 'delete_word_right' };
|
|
240
|
-
const state = textBufferReducer(stateWithText, action);
|
|
241
|
-
expect(state.lines).toEqual(['_name']);
|
|
242
|
-
expect(state.cursorCol).toBe(0);
|
|
243
|
-
});
|
|
244
280
|
it('should act like delete at the end of a line', () => {
|
|
245
281
|
const stateWithText = {
|
|
246
282
|
...initialState,
|
|
@@ -248,15 +284,15 @@ describe('textBufferReducer', () => {
|
|
|
248
284
|
cursorRow: 0,
|
|
249
285
|
cursorCol: 5,
|
|
250
286
|
};
|
|
251
|
-
const
|
|
252
|
-
|
|
287
|
+
const state = textBufferReducer(stateWithText, {
|
|
288
|
+
type: 'delete_word_right',
|
|
289
|
+
});
|
|
253
290
|
expect(state.lines).toEqual(['helloworld']);
|
|
254
291
|
expect(state.cursorRow).toBe(0);
|
|
255
292
|
expect(state.cursorCol).toBe(5);
|
|
256
293
|
});
|
|
257
294
|
});
|
|
258
295
|
});
|
|
259
|
-
// Helper to get the state from the hook
|
|
260
296
|
const getBufferState = (result) => {
|
|
261
297
|
expect(result.current).toHaveOnlyValidCharacters();
|
|
262
298
|
return {
|
|
@@ -1094,71 +1130,46 @@ Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots
|
|
|
1094
1130
|
});
|
|
1095
1131
|
});
|
|
1096
1132
|
describe('Input Sanitization', () => {
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1133
|
+
const createInput = (sequence) => ({
|
|
1134
|
+
name: '',
|
|
1135
|
+
ctrl: false,
|
|
1136
|
+
meta: false,
|
|
1137
|
+
shift: false,
|
|
1138
|
+
paste: false,
|
|
1139
|
+
sequence,
|
|
1140
|
+
});
|
|
1141
|
+
it.each([
|
|
1142
|
+
{
|
|
1143
|
+
input: '\x1B[31mHello\x1B[0m \x1B[32mWorld\x1B[0m',
|
|
1144
|
+
expected: 'Hello World',
|
|
1145
|
+
desc: 'ANSI escape codes',
|
|
1146
|
+
},
|
|
1147
|
+
{
|
|
1148
|
+
input: 'H\x07e\x08l\x0Bl\x0Co',
|
|
1149
|
+
expected: 'Hello',
|
|
1150
|
+
desc: 'control characters',
|
|
1151
|
+
},
|
|
1152
|
+
{
|
|
1153
|
+
input: '\u001B[4mH\u001B[0mello',
|
|
1154
|
+
expected: 'Hello',
|
|
1155
|
+
desc: 'mixed ANSI and control characters',
|
|
1156
|
+
},
|
|
1157
|
+
{
|
|
1158
|
+
input: '\u001B[4mPasted\u001B[4m Text',
|
|
1159
|
+
expected: 'Pasted Text',
|
|
1160
|
+
desc: 'pasted text with ANSI',
|
|
1161
|
+
},
|
|
1162
|
+
])('should strip $desc from input', ({ input, expected }) => {
|
|
1111
1163
|
const { result } = renderHook(() => useTextBuffer({ viewport, isValidPath: () => false }));
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
name: '',
|
|
1115
|
-
ctrl: false,
|
|
1116
|
-
meta: false,
|
|
1117
|
-
shift: false,
|
|
1118
|
-
paste: false,
|
|
1119
|
-
sequence: textWithControlChars,
|
|
1120
|
-
}));
|
|
1121
|
-
expect(getBufferState(result).text).toBe('Hello');
|
|
1122
|
-
});
|
|
1123
|
-
it('should strip mixed ANSI and control characters from input', () => {
|
|
1124
|
-
const { result } = renderHook(() => useTextBuffer({ viewport, isValidPath: () => false }));
|
|
1125
|
-
const textWithMixed = '\u001B[4mH\u001B[0mello';
|
|
1126
|
-
act(() => result.current.handleInput({
|
|
1127
|
-
name: '',
|
|
1128
|
-
ctrl: false,
|
|
1129
|
-
meta: false,
|
|
1130
|
-
shift: false,
|
|
1131
|
-
paste: false,
|
|
1132
|
-
sequence: textWithMixed,
|
|
1133
|
-
}));
|
|
1134
|
-
expect(getBufferState(result).text).toBe('Hello');
|
|
1164
|
+
act(() => result.current.handleInput(createInput(input)));
|
|
1165
|
+
expect(getBufferState(result).text).toBe(expected);
|
|
1135
1166
|
});
|
|
1136
1167
|
it('should not strip standard characters or newlines', () => {
|
|
1137
1168
|
const { result } = renderHook(() => useTextBuffer({ viewport, isValidPath: () => false }));
|
|
1138
1169
|
const validText = 'Hello World\nThis is a test.';
|
|
1139
|
-
act(() => result.current.handleInput(
|
|
1140
|
-
name: '',
|
|
1141
|
-
ctrl: false,
|
|
1142
|
-
meta: false,
|
|
1143
|
-
shift: false,
|
|
1144
|
-
paste: false,
|
|
1145
|
-
sequence: validText,
|
|
1146
|
-
}));
|
|
1170
|
+
act(() => result.current.handleInput(createInput(validText)));
|
|
1147
1171
|
expect(getBufferState(result).text).toBe(validText);
|
|
1148
1172
|
});
|
|
1149
|
-
it('should sanitize pasted text via handleInput', () => {
|
|
1150
|
-
const { result } = renderHook(() => useTextBuffer({ viewport, isValidPath: () => false }));
|
|
1151
|
-
const pastedText = '\u001B[4mPasted\u001B[4m Text';
|
|
1152
|
-
act(() => result.current.handleInput({
|
|
1153
|
-
name: '',
|
|
1154
|
-
ctrl: false,
|
|
1155
|
-
meta: false,
|
|
1156
|
-
shift: false,
|
|
1157
|
-
paste: false,
|
|
1158
|
-
sequence: pastedText,
|
|
1159
|
-
}));
|
|
1160
|
-
expect(getBufferState(result).text).toBe('Pasted Text');
|
|
1161
|
-
});
|
|
1162
1173
|
it('should sanitize large text (>5000 chars) and strip unsafe characters', () => {
|
|
1163
1174
|
const { result } = renderHook(() => useTextBuffer({ viewport, isValidPath: () => false }));
|
|
1164
1175
|
const unsafeChars = '\x07\x08\x0B\x0C';
|
|
@@ -1218,6 +1229,55 @@ Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots
|
|
|
1218
1229
|
expect(getBufferState(result).text).toBe(emojis);
|
|
1219
1230
|
});
|
|
1220
1231
|
});
|
|
1232
|
+
describe('inputFilter', () => {
|
|
1233
|
+
it('should filter input based on the provided filter function', () => {
|
|
1234
|
+
const { result } = renderHook(() => useTextBuffer({
|
|
1235
|
+
viewport,
|
|
1236
|
+
isValidPath: () => false,
|
|
1237
|
+
inputFilter: (text) => text.replace(/[^0-9]/g, ''),
|
|
1238
|
+
}));
|
|
1239
|
+
act(() => result.current.insert('a1b2c3'));
|
|
1240
|
+
expect(getBufferState(result).text).toBe('123');
|
|
1241
|
+
});
|
|
1242
|
+
it('should handle empty result from filter', () => {
|
|
1243
|
+
const { result } = renderHook(() => useTextBuffer({
|
|
1244
|
+
viewport,
|
|
1245
|
+
isValidPath: () => false,
|
|
1246
|
+
inputFilter: (text) => text.replace(/[^0-9]/g, ''),
|
|
1247
|
+
}));
|
|
1248
|
+
act(() => result.current.insert('abc'));
|
|
1249
|
+
expect(getBufferState(result).text).toBe('');
|
|
1250
|
+
});
|
|
1251
|
+
it('should filter pasted text', () => {
|
|
1252
|
+
const { result } = renderHook(() => useTextBuffer({
|
|
1253
|
+
viewport,
|
|
1254
|
+
isValidPath: () => false,
|
|
1255
|
+
inputFilter: (text) => text.toUpperCase(),
|
|
1256
|
+
}));
|
|
1257
|
+
act(() => result.current.insert('hello', { paste: true }));
|
|
1258
|
+
expect(getBufferState(result).text).toBe('HELLO');
|
|
1259
|
+
});
|
|
1260
|
+
it('should not filter newlines if they are allowed by the filter', () => {
|
|
1261
|
+
const { result } = renderHook(() => useTextBuffer({
|
|
1262
|
+
viewport,
|
|
1263
|
+
isValidPath: () => false,
|
|
1264
|
+
inputFilter: (text) => text, // Allow everything including newlines
|
|
1265
|
+
}));
|
|
1266
|
+
act(() => result.current.insert('a\nb'));
|
|
1267
|
+
// The insert function splits by newline and inserts separately if it detects them.
|
|
1268
|
+
// If the filter allows them, they should be handled correctly by the subsequent logic in insert.
|
|
1269
|
+
expect(getBufferState(result).text).toBe('a\nb');
|
|
1270
|
+
});
|
|
1271
|
+
it('should filter before newline check in insert', () => {
|
|
1272
|
+
const { result } = renderHook(() => useTextBuffer({
|
|
1273
|
+
viewport,
|
|
1274
|
+
isValidPath: () => false,
|
|
1275
|
+
inputFilter: (text) => text.replace(/\n/g, ''), // Filter out newlines
|
|
1276
|
+
}));
|
|
1277
|
+
act(() => result.current.insert('a\nb'));
|
|
1278
|
+
expect(getBufferState(result).text).toBe('ab');
|
|
1279
|
+
});
|
|
1280
|
+
});
|
|
1221
1281
|
describe('stripAnsi', () => {
|
|
1222
1282
|
it('should correctly strip ANSI escape codes', () => {
|
|
1223
1283
|
const textWithAnsi = '\x1B[31mHello\x1B[0m World';
|
|
@@ -1269,88 +1329,212 @@ Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots
|
|
|
1269
1329
|
expect(getBufferState(result).text).toBe('hello world');
|
|
1270
1330
|
});
|
|
1271
1331
|
});
|
|
1332
|
+
describe('singleLine mode', () => {
|
|
1333
|
+
it('should not insert a newline character when singleLine is true', () => {
|
|
1334
|
+
const { result } = renderHook(() => useTextBuffer({
|
|
1335
|
+
viewport,
|
|
1336
|
+
isValidPath: () => false,
|
|
1337
|
+
singleLine: true,
|
|
1338
|
+
}));
|
|
1339
|
+
act(() => result.current.insert('\n'));
|
|
1340
|
+
const state = getBufferState(result);
|
|
1341
|
+
expect(state.text).toBe('');
|
|
1342
|
+
expect(state.lines).toEqual(['']);
|
|
1343
|
+
});
|
|
1344
|
+
it('should not create a new line when newline() is called and singleLine is true', () => {
|
|
1345
|
+
const { result } = renderHook(() => useTextBuffer({
|
|
1346
|
+
initialText: 'ab',
|
|
1347
|
+
viewport,
|
|
1348
|
+
isValidPath: () => false,
|
|
1349
|
+
singleLine: true,
|
|
1350
|
+
}));
|
|
1351
|
+
act(() => result.current.move('end')); // cursor at [0,2]
|
|
1352
|
+
act(() => result.current.newline());
|
|
1353
|
+
const state = getBufferState(result);
|
|
1354
|
+
expect(state.text).toBe('ab');
|
|
1355
|
+
expect(state.lines).toEqual(['ab']);
|
|
1356
|
+
expect(state.cursor).toEqual([0, 2]);
|
|
1357
|
+
});
|
|
1358
|
+
it('should not handle "Enter" key as newline when singleLine is true', () => {
|
|
1359
|
+
const { result } = renderHook(() => useTextBuffer({
|
|
1360
|
+
viewport,
|
|
1361
|
+
isValidPath: () => false,
|
|
1362
|
+
singleLine: true,
|
|
1363
|
+
}));
|
|
1364
|
+
act(() => result.current.handleInput({
|
|
1365
|
+
name: 'return',
|
|
1366
|
+
ctrl: false,
|
|
1367
|
+
meta: false,
|
|
1368
|
+
shift: false,
|
|
1369
|
+
paste: false,
|
|
1370
|
+
sequence: '\r',
|
|
1371
|
+
}));
|
|
1372
|
+
expect(getBufferState(result).lines).toEqual(['']);
|
|
1373
|
+
});
|
|
1374
|
+
it('should strip newlines from pasted text when singleLine is true', () => {
|
|
1375
|
+
const { result } = renderHook(() => useTextBuffer({
|
|
1376
|
+
viewport,
|
|
1377
|
+
isValidPath: () => false,
|
|
1378
|
+
singleLine: true,
|
|
1379
|
+
}));
|
|
1380
|
+
act(() => result.current.insert('hello\nworld', { paste: true }));
|
|
1381
|
+
const state = getBufferState(result);
|
|
1382
|
+
expect(state.text).toBe('helloworld');
|
|
1383
|
+
expect(state.lines).toEqual(['helloworld']);
|
|
1384
|
+
});
|
|
1385
|
+
});
|
|
1272
1386
|
});
|
|
1273
1387
|
describe('offsetToLogicalPos', () => {
|
|
1274
|
-
it(
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1388
|
+
it.each([
|
|
1389
|
+
{ text: 'any text', offset: 0, expected: [0, 0], desc: 'offset 0' },
|
|
1390
|
+
{ text: 'hello', offset: 0, expected: [0, 0], desc: 'single line start' },
|
|
1391
|
+
{ text: 'hello', offset: 2, expected: [0, 2], desc: 'single line middle' },
|
|
1392
|
+
{ text: 'hello', offset: 5, expected: [0, 5], desc: 'single line end' },
|
|
1393
|
+
{ text: 'hello', offset: 10, expected: [0, 5], desc: 'beyond end clamps' },
|
|
1394
|
+
{
|
|
1395
|
+
text: 'a\n\nc',
|
|
1396
|
+
offset: 0,
|
|
1397
|
+
expected: [0, 0],
|
|
1398
|
+
desc: 'empty lines - first char',
|
|
1399
|
+
},
|
|
1400
|
+
{
|
|
1401
|
+
text: 'a\n\nc',
|
|
1402
|
+
offset: 1,
|
|
1403
|
+
expected: [0, 1],
|
|
1404
|
+
desc: 'empty lines - end of first',
|
|
1405
|
+
},
|
|
1406
|
+
{
|
|
1407
|
+
text: 'a\n\nc',
|
|
1408
|
+
offset: 2,
|
|
1409
|
+
expected: [1, 0],
|
|
1410
|
+
desc: 'empty lines - empty line',
|
|
1411
|
+
},
|
|
1412
|
+
{
|
|
1413
|
+
text: 'a\n\nc',
|
|
1414
|
+
offset: 3,
|
|
1415
|
+
expected: [2, 0],
|
|
1416
|
+
desc: 'empty lines - last line start',
|
|
1417
|
+
},
|
|
1418
|
+
{
|
|
1419
|
+
text: 'a\n\nc',
|
|
1420
|
+
offset: 4,
|
|
1421
|
+
expected: [2, 1],
|
|
1422
|
+
desc: 'empty lines - last line end',
|
|
1423
|
+
},
|
|
1424
|
+
{
|
|
1425
|
+
text: 'hello\n',
|
|
1426
|
+
offset: 5,
|
|
1427
|
+
expected: [0, 5],
|
|
1428
|
+
desc: 'newline end - before newline',
|
|
1429
|
+
},
|
|
1430
|
+
{
|
|
1431
|
+
text: 'hello\n',
|
|
1432
|
+
offset: 6,
|
|
1433
|
+
expected: [1, 0],
|
|
1434
|
+
desc: 'newline end - after newline',
|
|
1435
|
+
},
|
|
1436
|
+
{
|
|
1437
|
+
text: 'hello\n',
|
|
1438
|
+
offset: 7,
|
|
1439
|
+
expected: [1, 0],
|
|
1440
|
+
desc: 'newline end - beyond',
|
|
1441
|
+
},
|
|
1442
|
+
{
|
|
1443
|
+
text: '\nhello',
|
|
1444
|
+
offset: 0,
|
|
1445
|
+
expected: [0, 0],
|
|
1446
|
+
desc: 'newline start - first line',
|
|
1447
|
+
},
|
|
1448
|
+
{
|
|
1449
|
+
text: '\nhello',
|
|
1450
|
+
offset: 1,
|
|
1451
|
+
expected: [1, 0],
|
|
1452
|
+
desc: 'newline start - second line',
|
|
1453
|
+
},
|
|
1454
|
+
{
|
|
1455
|
+
text: '\nhello',
|
|
1456
|
+
offset: 3,
|
|
1457
|
+
expected: [1, 2],
|
|
1458
|
+
desc: 'newline start - middle of second',
|
|
1459
|
+
},
|
|
1460
|
+
{ text: '', offset: 0, expected: [0, 0], desc: 'empty string at 0' },
|
|
1461
|
+
{ text: '', offset: 5, expected: [0, 0], desc: 'empty string beyond' },
|
|
1462
|
+
{
|
|
1463
|
+
text: '你好\n世界',
|
|
1464
|
+
offset: 0,
|
|
1465
|
+
expected: [0, 0],
|
|
1466
|
+
desc: 'unicode - start',
|
|
1467
|
+
},
|
|
1468
|
+
{
|
|
1469
|
+
text: '你好\n世界',
|
|
1470
|
+
offset: 1,
|
|
1471
|
+
expected: [0, 1],
|
|
1472
|
+
desc: 'unicode - after first char',
|
|
1473
|
+
},
|
|
1474
|
+
{
|
|
1475
|
+
text: '你好\n世界',
|
|
1476
|
+
offset: 2,
|
|
1477
|
+
expected: [0, 2],
|
|
1478
|
+
desc: 'unicode - end first line',
|
|
1479
|
+
},
|
|
1480
|
+
{
|
|
1481
|
+
text: '你好\n世界',
|
|
1482
|
+
offset: 3,
|
|
1483
|
+
expected: [1, 0],
|
|
1484
|
+
desc: 'unicode - second line start',
|
|
1485
|
+
},
|
|
1486
|
+
{
|
|
1487
|
+
text: '你好\n世界',
|
|
1488
|
+
offset: 4,
|
|
1489
|
+
expected: [1, 1],
|
|
1490
|
+
desc: 'unicode - second line middle',
|
|
1491
|
+
},
|
|
1492
|
+
{
|
|
1493
|
+
text: '你好\n世界',
|
|
1494
|
+
offset: 5,
|
|
1495
|
+
expected: [1, 2],
|
|
1496
|
+
desc: 'unicode - second line end',
|
|
1497
|
+
},
|
|
1498
|
+
{
|
|
1499
|
+
text: '你好\n世界',
|
|
1500
|
+
offset: 6,
|
|
1501
|
+
expected: [1, 2],
|
|
1502
|
+
desc: 'unicode - beyond',
|
|
1503
|
+
},
|
|
1504
|
+
{
|
|
1505
|
+
text: 'abc\ndef',
|
|
1506
|
+
offset: 3,
|
|
1507
|
+
expected: [0, 3],
|
|
1508
|
+
desc: 'at newline - end of line',
|
|
1509
|
+
},
|
|
1510
|
+
{
|
|
1511
|
+
text: 'abc\ndef',
|
|
1512
|
+
offset: 4,
|
|
1513
|
+
expected: [1, 0],
|
|
1514
|
+
desc: 'at newline - after newline',
|
|
1515
|
+
},
|
|
1516
|
+
{ text: '🐶🐱', offset: 0, expected: [0, 0], desc: 'emoji - start' },
|
|
1517
|
+
{ text: '🐶🐱', offset: 1, expected: [0, 1], desc: 'emoji - middle' },
|
|
1518
|
+
{ text: '🐶🐱', offset: 2, expected: [0, 2], desc: 'emoji - end' },
|
|
1519
|
+
])('should handle $desc', ({ text, offset, expected }) => {
|
|
1520
|
+
expect(offsetToLogicalPos(text, offset)).toEqual(expected);
|
|
1283
1521
|
});
|
|
1284
|
-
|
|
1522
|
+
describe('multi-line text', () => {
|
|
1285
1523
|
const text = 'hello\nworld\n123';
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
expect(offsetToLogicalPos(text, 15)).toEqual([2, 3]); // End of '123'
|
|
1301
|
-
expect(offsetToLogicalPos(text, 20)).toEqual([2, 3]); // Beyond end of text
|
|
1302
|
-
});
|
|
1303
|
-
it('should handle empty lines', () => {
|
|
1304
|
-
const text = 'a\n\nc'; // "a" (1) + \n (1) + "" (0) + \n (1) + "c" (1)
|
|
1305
|
-
expect(offsetToLogicalPos(text, 0)).toEqual([0, 0]); // 'a'
|
|
1306
|
-
expect(offsetToLogicalPos(text, 1)).toEqual([0, 1]); // End of 'a'
|
|
1307
|
-
expect(offsetToLogicalPos(text, 2)).toEqual([1, 0]); // Start of empty line
|
|
1308
|
-
expect(offsetToLogicalPos(text, 3)).toEqual([2, 0]); // Start of 'c'
|
|
1309
|
-
expect(offsetToLogicalPos(text, 4)).toEqual([2, 1]); // End of 'c'
|
|
1310
|
-
});
|
|
1311
|
-
it('should handle text ending with a newline', () => {
|
|
1312
|
-
const text = 'hello\n'; // "hello" (5) + \n (1)
|
|
1313
|
-
expect(offsetToLogicalPos(text, 5)).toEqual([0, 5]); // End of 'hello'
|
|
1314
|
-
expect(offsetToLogicalPos(text, 6)).toEqual([1, 0]); // Position on the new empty line after
|
|
1315
|
-
expect(offsetToLogicalPos(text, 7)).toEqual([1, 0]); // Still on the new empty line
|
|
1316
|
-
});
|
|
1317
|
-
it('should handle text starting with a newline', () => {
|
|
1318
|
-
const text = '\nhello'; // "" (0) + \n (1) + "hello" (5)
|
|
1319
|
-
expect(offsetToLogicalPos(text, 0)).toEqual([0, 0]); // Start of first empty line
|
|
1320
|
-
expect(offsetToLogicalPos(text, 1)).toEqual([1, 0]); // Start of 'hello'
|
|
1321
|
-
expect(offsetToLogicalPos(text, 3)).toEqual([1, 2]); // 'l' in 'hello'
|
|
1322
|
-
});
|
|
1323
|
-
it('should handle empty string input', () => {
|
|
1324
|
-
expect(offsetToLogicalPos('', 0)).toEqual([0, 0]);
|
|
1325
|
-
expect(offsetToLogicalPos('', 5)).toEqual([0, 0]);
|
|
1326
|
-
});
|
|
1327
|
-
it('should handle multi-byte unicode characters correctly', () => {
|
|
1328
|
-
const text = '你好\n世界'; // "你好" (2 chars) + \n (1) + "世界" (2 chars)
|
|
1329
|
-
// Total "code points" for offset calculation: 2 + 1 + 2 = 5
|
|
1330
|
-
expect(offsetToLogicalPos(text, 0)).toEqual([0, 0]); // Start of '你好'
|
|
1331
|
-
expect(offsetToLogicalPos(text, 1)).toEqual([0, 1]); // After '你', before '好'
|
|
1332
|
-
expect(offsetToLogicalPos(text, 2)).toEqual([0, 2]); // End of '你好'
|
|
1333
|
-
expect(offsetToLogicalPos(text, 3)).toEqual([1, 0]); // Start of '世界'
|
|
1334
|
-
expect(offsetToLogicalPos(text, 4)).toEqual([1, 1]); // After '世', before '界'
|
|
1335
|
-
expect(offsetToLogicalPos(text, 5)).toEqual([1, 2]); // End of '世界'
|
|
1336
|
-
expect(offsetToLogicalPos(text, 6)).toEqual([1, 2]); // Beyond end
|
|
1337
|
-
});
|
|
1338
|
-
it('should handle offset exactly at newline character', () => {
|
|
1339
|
-
const text = 'abc\ndef';
|
|
1340
|
-
// a b c \n d e f
|
|
1341
|
-
// 0 1 2 3 4 5 6
|
|
1342
|
-
expect(offsetToLogicalPos(text, 3)).toEqual([0, 3]); // End of 'abc'
|
|
1343
|
-
// The next character is the newline, so an offset of 4 means the start of the next line.
|
|
1344
|
-
expect(offsetToLogicalPos(text, 4)).toEqual([1, 0]); // Start of 'def'
|
|
1345
|
-
});
|
|
1346
|
-
it('should handle offset in the middle of a multi-byte character (should place at start of that char)', () => {
|
|
1347
|
-
// This scenario is tricky as "offset" is usually character-based.
|
|
1348
|
-
// Assuming cpLen and related logic handles this by treating multi-byte as one unit.
|
|
1349
|
-
// The current implementation of offsetToLogicalPos uses cpLen, so it should be code-point aware.
|
|
1350
|
-
const text = '🐶🐱'; // 2 code points
|
|
1351
|
-
expect(offsetToLogicalPos(text, 0)).toEqual([0, 0]);
|
|
1352
|
-
expect(offsetToLogicalPos(text, 1)).toEqual([0, 1]); // After 🐶
|
|
1353
|
-
expect(offsetToLogicalPos(text, 2)).toEqual([0, 2]); // After 🐱
|
|
1524
|
+
it.each([
|
|
1525
|
+
{ offset: 0, expected: [0, 0], desc: 'start of first line' },
|
|
1526
|
+
{ offset: 3, expected: [0, 3], desc: 'middle of first line' },
|
|
1527
|
+
{ offset: 5, expected: [0, 5], desc: 'end of first line' },
|
|
1528
|
+
{ offset: 6, expected: [1, 0], desc: 'start of second line' },
|
|
1529
|
+
{ offset: 8, expected: [1, 2], desc: 'middle of second line' },
|
|
1530
|
+
{ offset: 11, expected: [1, 5], desc: 'end of second line' },
|
|
1531
|
+
{ offset: 12, expected: [2, 0], desc: 'start of third line' },
|
|
1532
|
+
{ offset: 13, expected: [2, 1], desc: 'middle of third line' },
|
|
1533
|
+
{ offset: 15, expected: [2, 3], desc: 'end of third line' },
|
|
1534
|
+
{ offset: 20, expected: [2, 3], desc: 'beyond end' },
|
|
1535
|
+
])('should return $expected for $desc (offset $offset)', ({ offset, expected }) => {
|
|
1536
|
+
expect(offsetToLogicalPos(text, offset)).toEqual(expected);
|
|
1537
|
+
});
|
|
1354
1538
|
});
|
|
1355
1539
|
});
|
|
1356
1540
|
describe('logicalPosToOffset', () => {
|
|
@@ -1400,7 +1584,6 @@ describe('logicalPosToOffset', () => {
|
|
|
1400
1584
|
expect(logicalPosToOffset(lines, 5, 10)).toBe(5); // Clamps to end of last line
|
|
1401
1585
|
});
|
|
1402
1586
|
});
|
|
1403
|
-
// Helper to create state for reducer tests
|
|
1404
1587
|
const createTestState = (lines, cursorRow, cursorCol, viewportWidth = 80) => {
|
|
1405
1588
|
const text = lines.join('\n');
|
|
1406
1589
|
let state = textBufferReducer(initialState, {
|