@google/gemini-cli 0.26.0-preview.4 → 0.27.0-nightly.20260126.cb772a5b7
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/README.md +18 -1
- package/dist/google-gemini-cli-0.27.0-nightly.20260121.97aac696f.tgz +0 -0
- package/dist/package.json +3 -4
- package/dist/src/commands/extensions.js +4 -1
- package/dist/src/commands/extensions.js.map +1 -1
- package/dist/src/commands/hooks.js +4 -1
- package/dist/src/commands/hooks.js.map +1 -1
- package/dist/src/commands/mcp/enableDisable.d.ts +13 -0
- package/dist/src/commands/mcp/enableDisable.js +122 -0
- package/dist/src/commands/mcp/enableDisable.js.map +1 -0
- package/dist/src/commands/mcp/list.d.ts +2 -0
- package/dist/src/commands/mcp/list.js +1 -1
- package/dist/src/commands/mcp/list.js.map +1 -1
- package/dist/src/commands/mcp.js +7 -1
- package/dist/src/commands/mcp.js.map +1 -1
- package/dist/src/commands/mcp.test.js +3 -1
- package/dist/src/commands/mcp.test.js.map +1 -1
- package/dist/src/commands/skills.js +4 -1
- package/dist/src/commands/skills.js.map +1 -1
- package/dist/src/config/config.d.ts +4 -0
- package/dist/src/config/config.js +41 -20
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +181 -15
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/keyBindings.d.ts +8 -5
- package/dist/src/config/keyBindings.js +38 -32
- package/dist/src/config/keyBindings.js.map +1 -1
- package/dist/src/config/keyBindings.test.js +8 -5
- package/dist/src/config/keyBindings.test.js.map +1 -1
- package/dist/src/config/mcp/index.d.ts +6 -0
- package/dist/src/config/mcp/index.js +7 -0
- package/dist/src/config/mcp/index.js.map +1 -0
- package/dist/src/config/mcp/mcpServerEnablement.d.ts +145 -0
- package/dist/src/config/mcp/mcpServerEnablement.js +254 -0
- package/dist/src/config/mcp/mcpServerEnablement.js.map +1 -0
- package/dist/src/config/mcp/mcpServerEnablement.test.js +147 -0
- package/dist/src/config/mcp/mcpServerEnablement.test.js.map +1 -0
- package/dist/src/config/sandboxConfig.test.js +11 -5
- package/dist/src/config/sandboxConfig.test.js.map +1 -1
- package/dist/src/config/settings.js +76 -0
- package/dist/src/config/settings.js.map +1 -1
- package/dist/src/config/settings.test.js +44 -0
- package/dist/src/config/settings.test.js.map +1 -1
- package/dist/src/config/settingsSchema.d.ts +21 -78
- package/dist/src/config/settingsSchema.js +21 -79
- package/dist/src/config/settingsSchema.js.map +1 -1
- package/dist/src/config/settingsSchema.test.js +1 -1
- package/dist/src/config/settingsSchema.test.js.map +1 -1
- package/dist/src/config/settings_repro.test.js +6 -2
- package/dist/src/config/settings_repro.test.js.map +1 -1
- package/dist/src/gemini.js +12 -7
- package/dist/src/gemini.js.map +1 -1
- package/dist/src/gemini.test.js +140 -10
- 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/generated/git-commit.js.map +1 -1
- package/dist/src/nonInteractiveCli.js +11 -3
- package/dist/src/nonInteractiveCli.js.map +1 -1
- package/dist/src/nonInteractiveCli.test.js +193 -3
- package/dist/src/nonInteractiveCli.test.js.map +1 -1
- package/dist/src/nonInteractiveCliCommands.js +6 -1
- package/dist/src/nonInteractiveCliCommands.js.map +1 -1
- package/dist/src/services/BuiltinCommandLoader.js +2 -0
- package/dist/src/services/BuiltinCommandLoader.js.map +1 -1
- package/dist/src/services/FileCommandLoader.js +12 -4
- package/dist/src/services/FileCommandLoader.js.map +1 -1
- package/dist/src/services/FileCommandLoader.test.js +56 -0
- package/dist/src/services/FileCommandLoader.test.js.map +1 -1
- package/dist/src/test-utils/mockCommandContext.js +2 -0
- package/dist/src/test-utils/mockCommandContext.js.map +1 -1
- package/dist/src/test-utils/persistentStateFake.d.ts +26 -0
- package/dist/src/test-utils/persistentStateFake.js +39 -0
- package/dist/src/test-utils/persistentStateFake.js.map +1 -0
- package/dist/src/test-utils/render.d.ts +10 -1
- package/dist/src/test-utils/render.js +45 -16
- package/dist/src/test-utils/render.js.map +1 -1
- package/dist/src/ui/App.test.js +96 -38
- package/dist/src/ui/App.test.js.map +1 -1
- package/dist/src/ui/AppContainer.js +78 -18
- package/dist/src/ui/AppContainer.js.map +1 -1
- package/dist/src/ui/AppContainer.test.js +185 -19
- package/dist/src/ui/AppContainer.test.js.map +1 -1
- package/dist/src/ui/auth/ApiAuthDialog.test.js +5 -5
- package/dist/src/ui/auth/ApiAuthDialog.test.js.map +1 -1
- package/dist/src/ui/auth/AuthDialog.test.js +13 -9
- package/dist/src/ui/auth/AuthDialog.test.js.map +1 -1
- package/dist/src/ui/auth/LoginWithGoogleRestartDialog.test.js +6 -6
- package/dist/src/ui/auth/LoginWithGoogleRestartDialog.test.js.map +1 -1
- package/dist/src/ui/commands/aboutCommand.js +2 -0
- package/dist/src/ui/commands/aboutCommand.js.map +1 -1
- package/dist/src/ui/commands/aboutCommand.test.js +12 -0
- package/dist/src/ui/commands/aboutCommand.test.js.map +1 -1
- package/dist/src/ui/commands/agentsCommand.js +75 -4
- package/dist/src/ui/commands/agentsCommand.js.map +1 -1
- package/dist/src/ui/commands/agentsCommand.test.js +114 -0
- package/dist/src/ui/commands/agentsCommand.test.js.map +1 -1
- package/dist/src/ui/commands/directoryCommand.js +53 -49
- package/dist/src/ui/commands/directoryCommand.js.map +1 -1
- package/dist/src/ui/commands/directoryCommand.test.js +79 -23
- package/dist/src/ui/commands/directoryCommand.test.js.map +1 -1
- package/dist/src/ui/commands/initCommand.test.js +8 -4
- package/dist/src/ui/commands/initCommand.test.js.map +1 -1
- package/dist/src/ui/commands/mcpCommand.js +136 -5
- package/dist/src/ui/commands/mcpCommand.js.map +1 -1
- package/dist/src/ui/commands/policiesCommand.js +33 -20
- package/dist/src/ui/commands/policiesCommand.js.map +1 -1
- package/dist/src/ui/commands/policiesCommand.test.js +7 -4
- package/dist/src/ui/commands/policiesCommand.test.js.map +1 -1
- package/dist/src/ui/commands/rewindCommand.d.ts +7 -0
- package/dist/src/ui/commands/rewindCommand.js +132 -0
- package/dist/src/ui/commands/rewindCommand.js.map +1 -0
- package/dist/src/ui/commands/rewindCommand.test.js +242 -0
- package/dist/src/ui/commands/rewindCommand.test.js.map +1 -0
- package/dist/src/ui/commands/skillsCommand.js +6 -4
- package/dist/src/ui/commands/skillsCommand.js.map +1 -1
- package/dist/src/ui/commands/skillsCommand.test.js +17 -3
- package/dist/src/ui/commands/skillsCommand.test.js.map +1 -1
- package/dist/src/ui/commands/types.d.ts +5 -3
- package/dist/src/ui/commands/types.js.map +1 -1
- package/dist/src/ui/components/AboutBox.d.ts +1 -0
- package/dist/src/ui/components/AboutBox.js +5 -1
- package/dist/src/ui/components/AboutBox.js.map +1 -1
- package/dist/src/ui/components/AboutBox.test.js +8 -2
- package/dist/src/ui/components/AboutBox.test.js.map +1 -1
- package/dist/src/ui/components/AgentConfigDialog.d.ts +18 -0
- package/dist/src/ui/components/AgentConfigDialog.js +296 -0
- package/dist/src/ui/components/AgentConfigDialog.js.map +1 -0
- package/dist/src/ui/components/AgentConfigDialog.test.js +241 -0
- package/dist/src/ui/components/AgentConfigDialog.test.js.map +1 -0
- package/dist/src/ui/components/AlternateBufferQuittingDisplay.js +9 -2
- package/dist/src/ui/components/AlternateBufferQuittingDisplay.js.map +1 -1
- package/dist/src/ui/components/AlternateBufferQuittingDisplay.test.js +54 -25
- package/dist/src/ui/components/AlternateBufferQuittingDisplay.test.js.map +1 -1
- package/dist/src/ui/components/AppHeader.js +4 -1
- package/dist/src/ui/components/AppHeader.js.map +1 -1
- package/dist/src/ui/components/AppHeader.test.js +95 -22
- package/dist/src/ui/components/AppHeader.test.js.map +1 -1
- package/dist/src/ui/components/{AutoAcceptIndicator.d.ts → ApprovalModeIndicator.d.ts} +2 -2
- package/dist/src/ui/components/{AutoAcceptIndicator.js → ApprovalModeIndicator.js} +8 -3
- package/dist/src/ui/components/ApprovalModeIndicator.js.map +1 -0
- package/dist/src/ui/components/ApprovalModeIndicator.test.d.ts +6 -0
- package/dist/src/ui/components/{AutoAcceptIndicator.test.js → ApprovalModeIndicator.test.js} +13 -7
- package/dist/src/ui/components/ApprovalModeIndicator.test.js.map +1 -0
- package/dist/src/ui/components/AskUserDialog.d.ts +39 -0
- package/dist/src/ui/components/AskUserDialog.js +618 -0
- package/dist/src/ui/components/AskUserDialog.js.map +1 -0
- package/dist/src/ui/components/AskUserDialog.test.d.ts +6 -0
- package/dist/src/ui/components/AskUserDialog.test.js +598 -0
- package/dist/src/ui/components/AskUserDialog.test.js.map +1 -0
- package/dist/src/ui/components/Composer.d.ts +3 -1
- package/dist/src/ui/components/Composer.js +5 -5
- package/dist/src/ui/components/Composer.js.map +1 -1
- package/dist/src/ui/components/Composer.test.js +6 -6
- package/dist/src/ui/components/Composer.test.js.map +1 -1
- package/dist/src/ui/components/ConfigInitDisplay.js +3 -4
- package/dist/src/ui/components/ConfigInitDisplay.js.map +1 -1
- package/dist/src/ui/components/ConfigInitDisplay.test.js +13 -29
- package/dist/src/ui/components/ConfigInitDisplay.test.js.map +1 -1
- package/dist/src/ui/components/ContextUsageDisplay.test.js +7 -3
- package/dist/src/ui/components/ContextUsageDisplay.test.js.map +1 -1
- package/dist/src/ui/components/DialogManager.js +13 -0
- package/dist/src/ui/components/DialogManager.js.map +1 -1
- package/dist/src/ui/components/DialogManager.test.js +24 -0
- package/dist/src/ui/components/DialogManager.test.js.map +1 -1
- package/dist/src/ui/components/FolderTrustDialog.test.js +3 -1
- package/dist/src/ui/components/FolderTrustDialog.test.js.map +1 -1
- package/dist/src/ui/components/Footer.test.js +7 -0
- package/dist/src/ui/components/Footer.test.js.map +1 -1
- package/dist/src/ui/components/Help.js +5 -2
- package/dist/src/ui/components/Help.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 +32 -20
- package/dist/src/ui/components/InputPrompt.js.map +1 -1
- package/dist/src/ui/components/InputPrompt.test.js +75 -1
- package/dist/src/ui/components/InputPrompt.test.js.map +1 -1
- package/dist/src/ui/components/MultiFolderTrustDialog.js +2 -1
- package/dist/src/ui/components/MultiFolderTrustDialog.js.map +1 -1
- package/dist/src/ui/components/MultiFolderTrustDialog.test.js +12 -10
- package/dist/src/ui/components/MultiFolderTrustDialog.test.js.map +1 -1
- package/dist/src/ui/components/Notifications.js +14 -20
- package/dist/src/ui/components/Notifications.js.map +1 -1
- package/dist/src/ui/components/Notifications.test.js +45 -35
- package/dist/src/ui/components/Notifications.test.js.map +1 -1
- package/dist/src/ui/components/RewindViewer.d.ts +1 -1
- package/dist/src/ui/components/RewindViewer.js +65 -17
- package/dist/src/ui/components/RewindViewer.js.map +1 -1
- package/dist/src/ui/components/RewindViewer.test.js +5 -3
- package/dist/src/ui/components/RewindViewer.test.js.map +1 -1
- package/dist/src/ui/components/SessionBrowser.js +3 -2
- package/dist/src/ui/components/SessionBrowser.js.map +1 -1
- package/dist/src/ui/components/SessionBrowser.test.js +10 -3
- package/dist/src/ui/components/SessionBrowser.test.js.map +1 -1
- package/dist/src/ui/components/SettingsDialog.d.ts +1 -1
- package/dist/src/ui/components/SettingsDialog.js +266 -516
- package/dist/src/ui/components/SettingsDialog.js.map +1 -1
- package/dist/src/ui/components/SettingsDialog.test.js +2 -2
- package/dist/src/ui/components/SettingsDialog.test.js.map +1 -1
- package/dist/src/ui/components/ShellInputPrompt.test.js +17 -8
- package/dist/src/ui/components/ShellInputPrompt.test.js.map +1 -1
- package/dist/src/ui/components/SuggestionsDisplay.d.ts +1 -1
- package/dist/src/ui/components/SuggestionsDisplay.js +4 -3
- package/dist/src/ui/components/SuggestionsDisplay.js.map +1 -1
- package/dist/src/ui/components/ToolConfirmationQueue.d.ts +12 -0
- package/dist/src/ui/components/ToolConfirmationQueue.js +30 -0
- package/dist/src/ui/components/ToolConfirmationQueue.js.map +1 -0
- package/dist/src/ui/components/ToolConfirmationQueue.test.d.ts +6 -0
- package/dist/src/ui/components/ToolConfirmationQueue.test.js +71 -0
- package/dist/src/ui/components/ToolConfirmationQueue.test.js.map +1 -0
- package/dist/src/ui/components/messages/RedirectionConfirmation.test.js +2 -4
- package/dist/src/ui/components/messages/RedirectionConfirmation.test.js.map +1 -1
- package/dist/src/ui/components/messages/ShellToolMessage.js +6 -41
- package/dist/src/ui/components/messages/ShellToolMessage.js.map +1 -1
- package/dist/src/ui/components/messages/ToolConfirmationMessage.d.ts +3 -2
- package/dist/src/ui/components/messages/ToolConfirmationMessage.js +61 -76
- package/dist/src/ui/components/messages/ToolConfirmationMessage.js.map +1 -1
- package/dist/src/ui/components/messages/ToolConfirmationMessage.test.js +20 -7
- package/dist/src/ui/components/messages/ToolConfirmationMessage.test.js.map +1 -1
- package/dist/src/ui/components/messages/ToolGroupMessage.js +34 -18
- package/dist/src/ui/components/messages/ToolGroupMessage.js.map +1 -1
- package/dist/src/ui/components/messages/ToolGroupMessage.test.js +209 -24
- package/dist/src/ui/components/messages/ToolGroupMessage.test.js.map +1 -1
- package/dist/src/ui/components/messages/ToolMessage.d.ts +1 -1
- package/dist/src/ui/components/messages/ToolMessage.js +7 -29
- package/dist/src/ui/components/messages/ToolMessage.js.map +1 -1
- package/dist/src/ui/components/messages/ToolMessageFocusHint.test.d.ts +6 -0
- package/dist/src/ui/components/messages/ToolMessageFocusHint.test.js +89 -0
- package/dist/src/ui/components/messages/ToolMessageFocusHint.test.js.map +1 -0
- package/dist/src/ui/components/messages/ToolShared.d.ts +26 -0
- package/dist/src/ui/components/messages/ToolShared.js +59 -6
- package/dist/src/ui/components/messages/ToolShared.js.map +1 -1
- package/dist/src/ui/components/shared/BaseSelectionList.d.ts +3 -1
- package/dist/src/ui/components/shared/BaseSelectionList.js +4 -2
- package/dist/src/ui/components/shared/BaseSelectionList.js.map +1 -1
- package/dist/src/ui/components/shared/BaseSelectionList.test.js +1 -0
- package/dist/src/ui/components/shared/BaseSelectionList.test.js.map +1 -1
- package/dist/src/ui/components/shared/BaseSettingsDialog.d.ts +72 -0
- package/dist/src/ui/components/shared/BaseSettingsDialog.js +293 -0
- package/dist/src/ui/components/shared/BaseSettingsDialog.js.map +1 -0
- package/dist/src/ui/components/shared/BaseSettingsDialog.test.d.ts +6 -0
- package/dist/src/ui/components/shared/BaseSettingsDialog.test.js +434 -0
- package/dist/src/ui/components/shared/BaseSettingsDialog.test.js.map +1 -0
- package/dist/src/ui/components/shared/ExpandableText.d.ts +17 -0
- package/dist/src/ui/components/{PrepareLabel.js → shared/ExpandableText.js} +30 -15
- package/dist/src/ui/components/shared/ExpandableText.js.map +1 -0
- package/dist/src/ui/components/shared/ExpandableText.test.d.ts +6 -0
- package/dist/src/ui/components/{PrepareLabel.test.js → shared/ExpandableText.test.js} +22 -11
- package/dist/src/ui/components/shared/ExpandableText.test.js.map +1 -0
- package/dist/src/ui/components/shared/TabHeader.d.ts +51 -0
- package/dist/src/ui/components/shared/TabHeader.js +42 -0
- package/dist/src/ui/components/shared/TabHeader.js.map +1 -0
- package/dist/src/ui/components/shared/TabHeader.test.d.ts +6 -0
- package/dist/src/ui/components/shared/TabHeader.test.js +106 -0
- package/dist/src/ui/components/shared/TabHeader.test.js.map +1 -0
- package/dist/src/ui/components/shared/TextInput.test.js +32 -24
- package/dist/src/ui/components/shared/TextInput.test.js.map +1 -1
- package/dist/src/ui/components/shared/text-buffer.d.ts +13 -0
- package/dist/src/ui/components/shared/text-buffer.js +173 -14
- package/dist/src/ui/components/shared/text-buffer.js.map +1 -1
- package/dist/src/ui/components/shared/text-buffer.test.js +256 -44
- package/dist/src/ui/components/shared/text-buffer.test.js.map +1 -1
- package/dist/src/ui/components/shared/vim-buffer-actions.test.js +4 -1
- package/dist/src/ui/components/shared/vim-buffer-actions.test.js.map +1 -1
- package/dist/src/ui/components/views/McpStatus.d.ts +1 -0
- package/dist/src/ui/components/views/McpStatus.js +30 -18
- package/dist/src/ui/components/views/McpStatus.js.map +1 -1
- package/dist/src/ui/components/views/McpStatus.test.js +7 -0
- package/dist/src/ui/components/views/McpStatus.test.js.map +1 -1
- package/dist/src/ui/constants/tips.js +2 -2
- package/dist/src/ui/constants/tips.js.map +1 -1
- package/dist/src/ui/constants.d.ts +1 -0
- package/dist/src/ui/constants.js +1 -0
- package/dist/src/ui/constants.js.map +1 -1
- package/dist/src/ui/contexts/KeypressContext.d.ts +3 -2
- package/dist/src/ui/contexts/KeypressContext.js +33 -25
- package/dist/src/ui/contexts/KeypressContext.js.map +1 -1
- package/dist/src/ui/contexts/KeypressContext.test.js +151 -41
- package/dist/src/ui/contexts/KeypressContext.test.js.map +1 -1
- package/dist/src/ui/contexts/MouseContext.test.js +8 -8
- package/dist/src/ui/contexts/MouseContext.test.js.map +1 -1
- package/dist/src/ui/contexts/ToolActionsContext.d.ts +20 -0
- package/dist/src/ui/contexts/ToolActionsContext.js +74 -0
- package/dist/src/ui/contexts/ToolActionsContext.js.map +1 -0
- package/dist/src/ui/contexts/ToolActionsContext.test.d.ts +6 -0
- package/dist/src/ui/contexts/ToolActionsContext.test.js +135 -0
- package/dist/src/ui/contexts/ToolActionsContext.test.js.map +1 -0
- package/dist/src/ui/contexts/UIActionsContext.d.ts +3 -1
- package/dist/src/ui/contexts/UIActionsContext.js.map +1 -1
- package/dist/src/ui/contexts/UIStateContext.d.ts +6 -2
- package/dist/src/ui/contexts/UIStateContext.js.map +1 -1
- package/dist/src/ui/hooks/atCommandProcessor.js +19 -4
- package/dist/src/ui/hooks/atCommandProcessor.js.map +1 -1
- package/dist/src/ui/hooks/keyToAnsi.js +1 -1
- package/dist/src/ui/hooks/keyToAnsi.js.map +1 -1
- package/dist/src/ui/hooks/slashCommandProcessor.d.ts +3 -1
- package/dist/src/ui/hooks/slashCommandProcessor.js +24 -7
- package/dist/src/ui/hooks/slashCommandProcessor.js.map +1 -1
- package/dist/src/ui/hooks/slashCommandProcessor.test.js +126 -30
- package/dist/src/ui/hooks/slashCommandProcessor.test.js.map +1 -1
- package/dist/src/ui/hooks/toolMapping.js +8 -11
- package/dist/src/ui/hooks/toolMapping.js.map +1 -1
- package/dist/src/ui/hooks/toolMapping.test.js +27 -6
- package/dist/src/ui/hooks/toolMapping.test.js.map +1 -1
- package/dist/src/ui/hooks/{useAutoAcceptIndicator.d.ts → useApprovalModeIndicator.d.ts} +2 -2
- package/dist/src/ui/hooks/{useAutoAcceptIndicator.js → useApprovalModeIndicator.js} +25 -11
- package/dist/src/ui/hooks/useApprovalModeIndicator.js.map +1 -0
- package/dist/src/ui/hooks/useApprovalModeIndicator.test.d.ts +6 -0
- package/dist/src/ui/hooks/{useAutoAcceptIndicator.test.js → useApprovalModeIndicator.test.js} +56 -31
- package/dist/src/ui/hooks/useApprovalModeIndicator.test.js.map +1 -0
- package/dist/src/ui/hooks/useConfirmingTool.d.ts +16 -0
- package/dist/src/ui/hooks/useConfirmingTool.js +39 -0
- package/dist/src/ui/hooks/useConfirmingTool.js.map +1 -0
- package/dist/src/ui/hooks/useGeminiStream.d.ts +1 -1
- package/dist/src/ui/hooks/useGeminiStream.js +20 -8
- package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
- package/dist/src/ui/hooks/useGeminiStream.test.js +79 -19
- package/dist/src/ui/hooks/useGeminiStream.test.js.map +1 -1
- package/dist/src/ui/hooks/useIncludeDirsTrust.d.ts +1 -1
- package/dist/src/ui/hooks/useIncludeDirsTrust.js +9 -20
- package/dist/src/ui/hooks/useIncludeDirsTrust.js.map +1 -1
- package/dist/src/ui/hooks/useIncludeDirsTrust.test.js +33 -12
- package/dist/src/ui/hooks/useIncludeDirsTrust.test.js.map +1 -1
- package/dist/src/ui/hooks/useKeypress.test.js +10 -3
- package/dist/src/ui/hooks/useKeypress.test.js.map +1 -1
- package/dist/src/ui/hooks/useLoadingIndicator.d.ts +7 -1
- package/dist/src/ui/hooks/useLoadingIndicator.js +3 -3
- package/dist/src/ui/hooks/useLoadingIndicator.js.map +1 -1
- package/dist/src/ui/hooks/useLoadingIndicator.test.js +17 -9
- package/dist/src/ui/hooks/useLoadingIndicator.test.js.map +1 -1
- package/dist/src/ui/hooks/usePhraseCycler.d.ts +2 -2
- package/dist/src/ui/hooks/usePhraseCycler.js +4 -14
- package/dist/src/ui/hooks/usePhraseCycler.js.map +1 -1
- package/dist/src/ui/hooks/usePhraseCycler.test.js +13 -42
- package/dist/src/ui/hooks/usePhraseCycler.test.js.map +1 -1
- package/dist/src/ui/hooks/useSelectionList.d.ts +4 -1
- package/dist/src/ui/hooks/useSelectionList.js +51 -13
- package/dist/src/ui/hooks/useSelectionList.js.map +1 -1
- package/dist/src/ui/hooks/useSelectionList.test.js +35 -3
- package/dist/src/ui/hooks/useSelectionList.test.js.map +1 -1
- package/dist/src/ui/hooks/useSessionResume.test.js +3 -2
- package/dist/src/ui/hooks/useSessionResume.test.js.map +1 -1
- package/dist/src/ui/hooks/useShellInactivityStatus.d.ts +26 -0
- package/dist/src/ui/hooks/useShellInactivityStatus.js +46 -0
- package/dist/src/ui/hooks/useShellInactivityStatus.js.map +1 -0
- package/dist/src/ui/hooks/useShellInactivityStatus.test.d.ts +6 -0
- package/dist/src/ui/hooks/useShellInactivityStatus.test.js +84 -0
- package/dist/src/ui/hooks/useShellInactivityStatus.test.js.map +1 -0
- package/dist/src/ui/hooks/useTabbedNavigation.d.ts +53 -0
- package/dist/src/ui/hooks/useTabbedNavigation.js +150 -0
- package/dist/src/ui/hooks/useTabbedNavigation.js.map +1 -0
- package/dist/src/ui/hooks/useTabbedNavigation.test.d.ts +6 -0
- package/dist/src/ui/hooks/useTabbedNavigation.test.js +187 -0
- package/dist/src/ui/hooks/useTabbedNavigation.test.js.map +1 -0
- package/dist/src/ui/hooks/useTips.d.ts +10 -0
- package/dist/src/ui/hooks/useTips.js +18 -0
- package/dist/src/ui/hooks/useTips.js.map +1 -0
- package/dist/src/ui/hooks/useTips.test.d.ts +6 -0
- package/dist/src/ui/hooks/useTips.test.js +33 -0
- package/dist/src/ui/hooks/useTips.test.js.map +1 -0
- package/dist/src/ui/hooks/useToolExecutionScheduler.d.ts +30 -0
- package/dist/src/ui/hooks/useToolExecutionScheduler.js +113 -0
- package/dist/src/ui/hooks/useToolExecutionScheduler.js.map +1 -0
- package/dist/src/ui/hooks/useToolExecutionScheduler.test.d.ts +6 -0
- package/dist/src/ui/hooks/useToolExecutionScheduler.test.js +296 -0
- package/dist/src/ui/hooks/useToolExecutionScheduler.test.js.map +1 -0
- package/dist/src/ui/hooks/useToolScheduler.d.ts +29 -0
- package/dist/src/ui/hooks/useToolScheduler.js +30 -0
- package/dist/src/ui/hooks/useToolScheduler.js.map +1 -0
- package/dist/src/ui/hooks/useToolScheduler.test.js +1 -1
- package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -1
- package/dist/src/ui/hooks/useToolSchedulerFacade.test.d.ts +6 -0
- package/dist/src/ui/hooks/useToolSchedulerFacade.test.js +45 -0
- package/dist/src/ui/hooks/useToolSchedulerFacade.test.js.map +1 -0
- package/dist/src/ui/hooks/useTurnActivityMonitor.d.ts +16 -0
- package/dist/src/ui/hooks/useTurnActivityMonitor.js +49 -0
- package/dist/src/ui/hooks/useTurnActivityMonitor.js.map +1 -0
- package/dist/src/ui/hooks/useTurnActivityMonitor.test.d.ts +6 -0
- package/dist/src/ui/hooks/useTurnActivityMonitor.test.js +97 -0
- package/dist/src/ui/hooks/useTurnActivityMonitor.test.js.map +1 -0
- package/dist/src/ui/hooks/vim.js +5 -3
- package/dist/src/ui/hooks/vim.js.map +1 -1
- package/dist/src/ui/hooks/vim.test.js +4 -2
- package/dist/src/ui/hooks/vim.test.js.map +1 -1
- package/dist/src/ui/keyMatchers.js +5 -13
- package/dist/src/ui/keyMatchers.js.map +1 -1
- package/dist/src/ui/keyMatchers.test.js +23 -20
- package/dist/src/ui/keyMatchers.test.js.map +1 -1
- package/dist/src/ui/layouts/DefaultAppLayout.js +10 -2
- package/dist/src/ui/layouts/DefaultAppLayout.js.map +1 -1
- package/dist/src/ui/noninteractive/nonInteractiveUi.js +1 -0
- package/dist/src/ui/noninteractive/nonInteractiveUi.js.map +1 -1
- package/dist/src/ui/types.d.ts +11 -3
- package/dist/src/ui/types.js.map +1 -1
- package/dist/src/ui/utils/clipboardUtils.d.ts +4 -4
- package/dist/src/ui/utils/clipboardUtils.js +198 -12
- package/dist/src/ui/utils/clipboardUtils.js.map +1 -1
- package/dist/src/ui/utils/clipboardUtils.test.js +219 -47
- package/dist/src/ui/utils/clipboardUtils.test.js.map +1 -1
- package/dist/src/ui/utils/clipboardUtils.windows.test.js +3 -0
- package/dist/src/ui/utils/clipboardUtils.windows.test.js.map +1 -1
- package/dist/src/ui/utils/commandUtils.test.js +11 -3
- package/dist/src/ui/utils/commandUtils.test.js.map +1 -1
- package/dist/src/ui/utils/directoryUtils.d.ts +10 -0
- package/dist/src/ui/utils/directoryUtils.js +12 -0
- package/dist/src/ui/utils/directoryUtils.js.map +1 -1
- package/dist/src/ui/utils/directoryUtils.test.js +8 -4
- package/dist/src/ui/utils/directoryUtils.test.js.map +1 -1
- package/dist/src/ui/utils/formatters.d.ts +1 -1
- package/dist/src/ui/utils/formatters.js +2 -3
- package/dist/src/ui/utils/formatters.js.map +1 -1
- package/dist/src/ui/utils/highlight.d.ts +2 -2
- package/dist/src/ui/utils/highlight.js +9 -3
- package/dist/src/ui/utils/highlight.js.map +1 -1
- package/dist/src/ui/utils/highlight.test.js +3 -0
- package/dist/src/ui/utils/highlight.test.js.map +1 -1
- package/dist/src/ui/utils/terminalCapabilityManager.d.ts +1 -2
- package/dist/src/ui/utils/terminalCapabilityManager.js +2 -8
- package/dist/src/ui/utils/terminalCapabilityManager.js.map +1 -1
- package/dist/src/ui/utils/terminalCapabilityManager.test.js +2 -3
- package/dist/src/ui/utils/terminalCapabilityManager.test.js.map +1 -1
- package/dist/src/ui/utils/terminalSetup.test.js +5 -3
- package/dist/src/ui/utils/terminalSetup.test.js.map +1 -1
- package/dist/src/ui/utils/textUtils.d.ts +5 -0
- package/dist/src/ui/utils/textUtils.js +14 -0
- package/dist/src/ui/utils/textUtils.js.map +1 -1
- package/dist/src/ui/utils/textUtils.test.js +19 -1
- package/dist/src/ui/utils/textUtils.test.js.map +1 -1
- package/dist/src/utils/cleanup.js +15 -0
- package/dist/src/utils/cleanup.js.map +1 -1
- package/dist/src/utils/events.d.ts +1 -6
- package/dist/src/utils/events.js +0 -2
- package/dist/src/utils/events.js.map +1 -1
- package/dist/src/utils/events.test.js +4 -4
- package/dist/src/utils/events.test.js.map +1 -1
- package/dist/src/utils/handleAutoUpdate.test.js +3 -0
- package/dist/src/utils/handleAutoUpdate.test.js.map +1 -1
- package/dist/src/utils/installationInfo.js +4 -2
- package/dist/src/utils/installationInfo.js.map +1 -1
- package/dist/src/utils/persistentState.d.ts +2 -0
- package/dist/src/utils/persistentState.js.map +1 -1
- package/dist/src/utils/windowTitle.d.ts +2 -1
- package/dist/src/utils/windowTitle.js +8 -1
- package/dist/src/utils/windowTitle.js.map +1 -1
- package/dist/src/utils/windowTitle.test.js +25 -1
- package/dist/src/utils/windowTitle.test.js.map +1 -1
- package/dist/src/zed-integration/zedIntegration.js +26 -5
- package/dist/src/zed-integration/zedIntegration.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -5
- package/dist/google-gemini-cli-0.26.0-preview.3.tgz +0 -0
- package/dist/src/ui/components/AutoAcceptIndicator.js.map +0 -1
- package/dist/src/ui/components/AutoAcceptIndicator.test.js.map +0 -1
- package/dist/src/ui/components/PrepareLabel.d.ts +0 -15
- package/dist/src/ui/components/PrepareLabel.js.map +0 -1
- package/dist/src/ui/components/PrepareLabel.test.js.map +0 -1
- package/dist/src/ui/hooks/useAutoAcceptIndicator.js.map +0 -1
- package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js.map +0 -1
- /package/dist/src/{ui/components/AutoAcceptIndicator.test.d.ts → config/mcp/mcpServerEnablement.test.d.ts} +0 -0
- /package/dist/src/ui/{components/PrepareLabel.test.d.ts → commands/rewindCommand.test.d.ts} +0 -0
- /package/dist/src/ui/{hooks/useAutoAcceptIndicator.test.d.ts → components/AgentConfigDialog.test.d.ts} +0 -0
|
@@ -1,39 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
* Copyright 2025 Google LLC
|
|
5
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
6
|
-
*/
|
|
7
|
-
import React, { useState, useEffect, useMemo } from 'react';
|
|
8
|
-
import { Box, Text } from 'ink';
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useEffect, useMemo, useCallback } from 'react';
|
|
3
|
+
import { Text } from 'ink';
|
|
9
4
|
import { AsyncFzf } from 'fzf';
|
|
10
5
|
import { theme } from '../semantic-colors.js';
|
|
11
6
|
import { SettingScope } from '../../config/settings.js';
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { getDialogSettingKeys, setPendingSettingValue, getDisplayValue, hasRestartRequiredSettings, saveModifiedSettings, getSettingDefinition, isDefaultValue, requiresRestart, getRestartRequiredFromModified, getEffectiveDefaultValue, setPendingSettingValueAny, getNestedValue, getEffectiveValue, } from '../../utils/settingsUtils.js';
|
|
7
|
+
import { getScopeMessageForSetting } from '../../utils/dialogScopeUtils.js';
|
|
8
|
+
import { getDialogSettingKeys, setPendingSettingValue, getDisplayValue, hasRestartRequiredSettings, saveModifiedSettings, getSettingDefinition, isDefaultValue, requiresRestart, getRestartRequiredFromModified, getEffectiveDefaultValue, setPendingSettingValueAny, getEffectiveValue, } from '../../utils/settingsUtils.js';
|
|
15
9
|
import { useVimMode } from '../contexts/VimModeContext.js';
|
|
16
|
-
import {
|
|
17
|
-
import chalk from 'chalk';
|
|
18
|
-
import { cpSlice, cpLen, stripUnsafeCharacters, getCachedStringWidth, } from '../utils/textUtils.js';
|
|
10
|
+
import { getCachedStringWidth } from '../utils/textUtils.js';
|
|
19
11
|
import { TOGGLE_TYPES, } from '../../config/settingsSchema.js';
|
|
20
12
|
import { coreEvents, debugLogger } from '@google/gemini-cli-core';
|
|
21
|
-
import { keyMatchers, Command } from '../keyMatchers.js';
|
|
22
13
|
import { useUIState } from '../contexts/UIStateContext.js';
|
|
23
14
|
import { useTextBuffer } from './shared/text-buffer.js';
|
|
24
|
-
import {
|
|
15
|
+
import { BaseSettingsDialog, } from './shared/BaseSettingsDialog.js';
|
|
25
16
|
const MAX_ITEMS_TO_SHOW = 8;
|
|
26
17
|
export function SettingsDialog({ settings, onSelect, onRestartRequest, availableTerminalHeight, config, }) {
|
|
27
18
|
// Get vim mode context to sync vim mode changes
|
|
28
19
|
const { vimEnabled, toggleVimEnabled } = useVimMode();
|
|
29
|
-
// Focus state: 'settings' or 'scope'
|
|
30
|
-
const [focusSection, setFocusSection] = useState('settings');
|
|
31
20
|
// Scope selector state (User by default)
|
|
32
21
|
const [selectedScope, setSelectedScope] = useState(SettingScope.User);
|
|
33
|
-
// Active indices
|
|
34
|
-
const [activeSettingIndex, setActiveSettingIndex] = useState(0);
|
|
35
|
-
// Scroll offset for settings
|
|
36
|
-
const [scrollOffset, setScrollOffset] = useState(0);
|
|
37
22
|
const [showRestartPrompt, setShowRestartPrompt] = useState(false);
|
|
38
23
|
// Search state
|
|
39
24
|
const [searchQuery, setSearchQuery] = useState('');
|
|
@@ -73,8 +58,6 @@ export function SettingsDialog({ settings, onSelect, onRestartRequest, available
|
|
|
73
58
|
matchedKeys.add(key);
|
|
74
59
|
});
|
|
75
60
|
setFilteredKeys(Array.from(matchedKeys));
|
|
76
|
-
setActiveSettingIndex(0); // Reset cursor
|
|
77
|
-
setScrollOffset(0);
|
|
78
61
|
};
|
|
79
62
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
80
63
|
doSearch();
|
|
@@ -134,141 +117,160 @@ export function SettingsDialog({ settings, onSelect, onRestartRequest, available
|
|
|
134
117
|
}
|
|
135
118
|
return max;
|
|
136
119
|
}, [selectedScope, settings]);
|
|
137
|
-
|
|
138
|
-
|
|
120
|
+
// Get mainAreaWidth for search buffer viewport
|
|
121
|
+
const { mainAreaWidth } = useUIState();
|
|
122
|
+
const viewportWidth = mainAreaWidth - 8;
|
|
123
|
+
// Search input buffer
|
|
124
|
+
const searchBuffer = useTextBuffer({
|
|
125
|
+
initialText: '',
|
|
126
|
+
initialCursorOffset: 0,
|
|
127
|
+
viewport: {
|
|
128
|
+
width: viewportWidth,
|
|
129
|
+
height: 1,
|
|
130
|
+
},
|
|
131
|
+
isValidPath: () => false,
|
|
132
|
+
singleLine: true,
|
|
133
|
+
onChange: (text) => setSearchQuery(text),
|
|
134
|
+
});
|
|
135
|
+
// Generate items for BaseSettingsDialog
|
|
136
|
+
const settingKeys = searchQuery ? filteredKeys : getDialogSettingKeys();
|
|
137
|
+
const items = useMemo(() => {
|
|
138
|
+
const scopeSettings = settings.forScope(selectedScope).settings;
|
|
139
|
+
const mergedSettings = settings.merged;
|
|
139
140
|
return settingKeys.map((key) => {
|
|
140
141
|
const definition = getSettingDefinition(key);
|
|
142
|
+
const type = definition?.type ?? 'string';
|
|
143
|
+
// Get the display value (with * indicator if modified)
|
|
144
|
+
const displayValue = getDisplayValue(key, scopeSettings, mergedSettings, modifiedSettings, pendingSettings);
|
|
145
|
+
// Get the scope message (e.g., "(Modified in Workspace)")
|
|
146
|
+
const scopeMessage = getScopeMessageForSetting(key, selectedScope, settings);
|
|
147
|
+
// Check if the value is at default (grey it out)
|
|
148
|
+
const isGreyedOut = isDefaultValue(key, scopeSettings);
|
|
149
|
+
// Get raw value for edit mode initialization
|
|
150
|
+
const rawValue = getEffectiveValue(key, pendingSettings, {});
|
|
141
151
|
return {
|
|
152
|
+
key,
|
|
142
153
|
label: definition?.label || key,
|
|
143
154
|
description: definition?.description,
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
}
|
|
150
|
-
const currentValue = getEffectiveValue(key, pendingSettings, {});
|
|
151
|
-
let newValue;
|
|
152
|
-
if (definition?.type === 'boolean') {
|
|
153
|
-
newValue = !currentValue;
|
|
154
|
-
setPendingSettings((prev) => setPendingSettingValue(key, newValue, prev));
|
|
155
|
-
}
|
|
156
|
-
else if (definition?.type === 'enum' && definition.options) {
|
|
157
|
-
const options = definition.options;
|
|
158
|
-
const currentIndex = options?.findIndex((opt) => opt.value === currentValue);
|
|
159
|
-
if (currentIndex !== -1 && currentIndex < options.length - 1) {
|
|
160
|
-
newValue = options[currentIndex + 1].value;
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
newValue = options[0].value; // loop back to start.
|
|
164
|
-
}
|
|
165
|
-
setPendingSettings((prev) => setPendingSettingValueAny(key, newValue, prev));
|
|
166
|
-
}
|
|
167
|
-
if (!requiresRestart(key)) {
|
|
168
|
-
const immediateSettings = new Set([key]);
|
|
169
|
-
const currentScopeSettings = settings.forScope(selectedScope).settings;
|
|
170
|
-
const immediateSettingsObject = setPendingSettingValueAny(key, newValue, currentScopeSettings);
|
|
171
|
-
debugLogger.log(`[DEBUG SettingsDialog] Saving ${key} immediately with value:`, newValue);
|
|
172
|
-
saveModifiedSettings(immediateSettings, immediateSettingsObject, settings, selectedScope);
|
|
173
|
-
// Special handling for vim mode to sync with VimModeContext
|
|
174
|
-
if (key === 'general.vimMode' && newValue !== vimEnabled) {
|
|
175
|
-
// Call toggleVimEnabled to sync the VimModeContext local state
|
|
176
|
-
toggleVimEnabled().catch((error) => {
|
|
177
|
-
coreEvents.emitFeedback('error', 'Failed to toggle vim mode:', error);
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
// Remove from modifiedSettings since it's now saved
|
|
181
|
-
setModifiedSettings((prev) => {
|
|
182
|
-
const updated = new Set(prev);
|
|
183
|
-
updated.delete(key);
|
|
184
|
-
return updated;
|
|
185
|
-
});
|
|
186
|
-
// Also remove from restart-required settings if it was there
|
|
187
|
-
setRestartRequiredSettings((prev) => {
|
|
188
|
-
const updated = new Set(prev);
|
|
189
|
-
updated.delete(key);
|
|
190
|
-
return updated;
|
|
191
|
-
});
|
|
192
|
-
// Remove from global pending changes if present
|
|
193
|
-
setGlobalPendingChanges((prev) => {
|
|
194
|
-
if (!prev.has(key))
|
|
195
|
-
return prev;
|
|
196
|
-
const next = new Map(prev);
|
|
197
|
-
next.delete(key);
|
|
198
|
-
return next;
|
|
199
|
-
});
|
|
200
|
-
if (key === 'general.previewFeatures') {
|
|
201
|
-
config?.setPreviewFeatures(newValue);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
else {
|
|
205
|
-
// For restart-required settings, track as modified
|
|
206
|
-
setModifiedSettings((prev) => {
|
|
207
|
-
const updated = new Set(prev).add(key);
|
|
208
|
-
const needsRestart = hasRestartRequiredSettings(updated);
|
|
209
|
-
debugLogger.log(`[DEBUG SettingsDialog] Modified settings:`, Array.from(updated), 'Needs restart:', needsRestart);
|
|
210
|
-
if (needsRestart) {
|
|
211
|
-
setShowRestartPrompt(true);
|
|
212
|
-
setRestartRequiredSettings((prevRestart) => new Set(prevRestart).add(key));
|
|
213
|
-
}
|
|
214
|
-
return updated;
|
|
215
|
-
});
|
|
216
|
-
// Add/update pending change globally so it persists across scopes
|
|
217
|
-
setGlobalPendingChanges((prev) => {
|
|
218
|
-
const next = new Map(prev);
|
|
219
|
-
next.set(key, newValue);
|
|
220
|
-
return next;
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
},
|
|
155
|
+
type: type,
|
|
156
|
+
displayValue,
|
|
157
|
+
isGreyedOut,
|
|
158
|
+
scopeMessage,
|
|
159
|
+
rawValue: rawValue,
|
|
224
160
|
};
|
|
225
161
|
});
|
|
226
|
-
};
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
const
|
|
233
|
-
|
|
234
|
-
if (!
|
|
235
|
-
setCursorVisible(true);
|
|
162
|
+
}, [settingKeys, selectedScope, settings, modifiedSettings, pendingSettings]);
|
|
163
|
+
// Scope selection handler
|
|
164
|
+
const handleScopeChange = useCallback((scope) => {
|
|
165
|
+
setSelectedScope(scope);
|
|
166
|
+
}, []);
|
|
167
|
+
// Toggle handler for boolean/enum settings
|
|
168
|
+
const handleItemToggle = useCallback((key, _item) => {
|
|
169
|
+
const definition = getSettingDefinition(key);
|
|
170
|
+
if (!TOGGLE_TYPES.has(definition?.type)) {
|
|
236
171
|
return;
|
|
237
172
|
}
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
173
|
+
const currentValue = getEffectiveValue(key, pendingSettings, {});
|
|
174
|
+
let newValue;
|
|
175
|
+
if (definition?.type === 'boolean') {
|
|
176
|
+
newValue = !currentValue;
|
|
177
|
+
setPendingSettings((prev) => setPendingSettingValue(key, newValue, prev));
|
|
178
|
+
}
|
|
179
|
+
else if (definition?.type === 'enum' && definition.options) {
|
|
180
|
+
const options = definition.options;
|
|
181
|
+
const currentIndex = options?.findIndex((opt) => opt.value === currentValue);
|
|
182
|
+
if (currentIndex !== -1 && currentIndex < options.length - 1) {
|
|
183
|
+
newValue = options[currentIndex + 1].value;
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
newValue = options[0].value; // loop back to start.
|
|
187
|
+
}
|
|
188
|
+
setPendingSettings((prev) => setPendingSettingValueAny(key, newValue, prev));
|
|
189
|
+
}
|
|
190
|
+
if (!requiresRestart(key)) {
|
|
191
|
+
const immediateSettings = new Set([key]);
|
|
192
|
+
const currentScopeSettings = settings.forScope(selectedScope).settings;
|
|
193
|
+
const immediateSettingsObject = setPendingSettingValueAny(key, newValue, currentScopeSettings);
|
|
194
|
+
debugLogger.log(`[DEBUG SettingsDialog] Saving ${key} immediately with value:`, newValue);
|
|
195
|
+
saveModifiedSettings(immediateSettings, immediateSettingsObject, settings, selectedScope);
|
|
196
|
+
// Special handling for vim mode to sync with VimModeContext
|
|
197
|
+
if (key === 'general.vimMode' && newValue !== vimEnabled) {
|
|
198
|
+
// Call toggleVimEnabled to sync the VimModeContext local state
|
|
199
|
+
toggleVimEnabled().catch((error) => {
|
|
200
|
+
coreEvents.emitFeedback('error', 'Failed to toggle vim mode:', error);
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
// Remove from modifiedSettings since it's now saved
|
|
204
|
+
setModifiedSettings((prev) => {
|
|
205
|
+
const updated = new Set(prev);
|
|
206
|
+
updated.delete(key);
|
|
207
|
+
return updated;
|
|
208
|
+
});
|
|
209
|
+
// Also remove from restart-required settings if it was there
|
|
210
|
+
setRestartRequiredSettings((prev) => {
|
|
211
|
+
const updated = new Set(prev);
|
|
212
|
+
updated.delete(key);
|
|
213
|
+
return updated;
|
|
214
|
+
});
|
|
215
|
+
// Remove from global pending changes if present
|
|
216
|
+
setGlobalPendingChanges((prev) => {
|
|
217
|
+
if (!prev.has(key))
|
|
218
|
+
return prev;
|
|
219
|
+
const next = new Map(prev);
|
|
220
|
+
next.delete(key);
|
|
221
|
+
return next;
|
|
222
|
+
});
|
|
223
|
+
if (key === 'general.previewFeatures') {
|
|
224
|
+
config?.setPreviewFeatures(newValue);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
// For restart-required settings, track as modified
|
|
229
|
+
setModifiedSettings((prev) => {
|
|
230
|
+
const updated = new Set(prev).add(key);
|
|
231
|
+
const needsRestart = hasRestartRequiredSettings(updated);
|
|
232
|
+
debugLogger.log(`[DEBUG SettingsDialog] Modified settings:`, Array.from(updated), 'Needs restart:', needsRestart);
|
|
233
|
+
if (needsRestart) {
|
|
234
|
+
setShowRestartPrompt(true);
|
|
235
|
+
setRestartRequiredSettings((prevRestart) => new Set(prevRestart).add(key));
|
|
236
|
+
}
|
|
237
|
+
return updated;
|
|
238
|
+
});
|
|
239
|
+
// Record pending change globally
|
|
240
|
+
setGlobalPendingChanges((prev) => {
|
|
241
|
+
const next = new Map(prev);
|
|
242
|
+
next.set(key, newValue);
|
|
243
|
+
return next;
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
}, [
|
|
247
|
+
pendingSettings,
|
|
248
|
+
settings,
|
|
249
|
+
selectedScope,
|
|
250
|
+
vimEnabled,
|
|
251
|
+
toggleVimEnabled,
|
|
252
|
+
config,
|
|
253
|
+
]);
|
|
254
|
+
// Edit commit handler
|
|
255
|
+
const handleEditCommit = useCallback((key, newValue, _item) => {
|
|
248
256
|
const definition = getSettingDefinition(key);
|
|
249
257
|
const type = definition?.type;
|
|
250
|
-
if (
|
|
258
|
+
if (newValue.trim() === '' && type === 'number') {
|
|
251
259
|
// Nothing entered for a number; cancel edit
|
|
252
|
-
setEditingKey(null);
|
|
253
|
-
setEditBuffer('');
|
|
254
|
-
setEditCursorPos(0);
|
|
255
260
|
return;
|
|
256
261
|
}
|
|
257
262
|
let parsed;
|
|
258
263
|
if (type === 'number') {
|
|
259
|
-
const numParsed = Number(
|
|
264
|
+
const numParsed = Number(newValue.trim());
|
|
260
265
|
if (Number.isNaN(numParsed)) {
|
|
261
266
|
// Invalid number; cancel edit
|
|
262
|
-
setEditingKey(null);
|
|
263
|
-
setEditBuffer('');
|
|
264
|
-
setEditCursorPos(0);
|
|
265
267
|
return;
|
|
266
268
|
}
|
|
267
269
|
parsed = numParsed;
|
|
268
270
|
}
|
|
269
271
|
else {
|
|
270
272
|
// For strings, use the buffer as is.
|
|
271
|
-
parsed =
|
|
273
|
+
parsed = newValue;
|
|
272
274
|
}
|
|
273
275
|
// Update pending
|
|
274
276
|
setPendingSettings((prev) => setPendingSettingValueAny(key, parsed, prev));
|
|
@@ -315,84 +317,67 @@ export function SettingsDialog({ settings, onSelect, onRestartRequest, available
|
|
|
315
317
|
return next;
|
|
316
318
|
});
|
|
317
319
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
key: item.value,
|
|
326
|
-
}));
|
|
327
|
-
const handleScopeHighlight = (scope) => {
|
|
328
|
-
setSelectedScope(scope);
|
|
329
|
-
};
|
|
330
|
-
const handleScopeSelect = (scope) => {
|
|
331
|
-
handleScopeHighlight(scope);
|
|
332
|
-
setFocusSection('settings');
|
|
333
|
-
};
|
|
334
|
-
// Height constraint calculations similar to ThemeDialog
|
|
335
|
-
const DIALOG_PADDING = 5;
|
|
336
|
-
const SETTINGS_TITLE_HEIGHT = 2; // "Settings" title + spacing
|
|
337
|
-
const SCROLL_ARROWS_HEIGHT = 2; // Up and down arrows
|
|
338
|
-
const SPACING_HEIGHT = 1; // Space between settings list and scope
|
|
339
|
-
const SCOPE_SELECTION_HEIGHT = 4; // Apply To section height
|
|
340
|
-
const BOTTOM_HELP_TEXT_HEIGHT = 1; // Help text
|
|
341
|
-
const RESTART_PROMPT_HEIGHT = showRestartPrompt ? 1 : 0;
|
|
342
|
-
let currentAvailableTerminalHeight = availableTerminalHeight ?? Number.MAX_SAFE_INTEGER;
|
|
343
|
-
currentAvailableTerminalHeight -= 2; // Top and bottom borders
|
|
344
|
-
// Start with basic fixed height (without scope selection)
|
|
345
|
-
let totalFixedHeight = DIALOG_PADDING +
|
|
346
|
-
SETTINGS_TITLE_HEIGHT +
|
|
347
|
-
SCROLL_ARROWS_HEIGHT +
|
|
348
|
-
SPACING_HEIGHT +
|
|
349
|
-
BOTTOM_HELP_TEXT_HEIGHT +
|
|
350
|
-
RESTART_PROMPT_HEIGHT;
|
|
351
|
-
// Calculate how much space we have for settings
|
|
352
|
-
let availableHeightForSettings = Math.max(1, currentAvailableTerminalHeight - totalFixedHeight);
|
|
353
|
-
// Each setting item takes up to 3 lines (label/value row, description row, and spacing)
|
|
354
|
-
let maxVisibleItems = Math.max(1, Math.floor(availableHeightForSettings / 3));
|
|
355
|
-
// Decide whether to show scope selection based on remaining space
|
|
356
|
-
let showScopeSelection = true;
|
|
357
|
-
// If we have limited height, prioritize showing more settings over scope selection
|
|
358
|
-
if (availableTerminalHeight && availableTerminalHeight < 25) {
|
|
359
|
-
// For very limited height, hide scope selection to show more settings
|
|
360
|
-
const totalWithScope = totalFixedHeight + SCOPE_SELECTION_HEIGHT;
|
|
361
|
-
const availableWithScope = Math.max(1, currentAvailableTerminalHeight - totalWithScope);
|
|
362
|
-
const maxItemsWithScope = Math.max(1, Math.floor(availableWithScope / 3));
|
|
363
|
-
// If hiding scope selection allows us to show significantly more settings, do it
|
|
364
|
-
if (maxVisibleItems > maxItemsWithScope + 1) {
|
|
365
|
-
showScopeSelection = false;
|
|
320
|
+
}, [settings, selectedScope]);
|
|
321
|
+
// Clear/reset handler - removes the value from settings.json so it falls back to default
|
|
322
|
+
const handleItemClear = useCallback((key, _item) => {
|
|
323
|
+
const defaultValue = getEffectiveDefaultValue(key, config);
|
|
324
|
+
// Update local pending state to show the default value
|
|
325
|
+
if (typeof defaultValue === 'boolean') {
|
|
326
|
+
setPendingSettings((prev) => setPendingSettingValue(key, defaultValue, prev));
|
|
366
327
|
}
|
|
367
|
-
else
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
availableHeightForSettings = Math.max(1, currentAvailableTerminalHeight - totalFixedHeight);
|
|
371
|
-
maxVisibleItems = Math.max(1, Math.floor(availableHeightForSettings / 3));
|
|
328
|
+
else if (typeof defaultValue === 'number' ||
|
|
329
|
+
typeof defaultValue === 'string') {
|
|
330
|
+
setPendingSettings((prev) => setPendingSettingValueAny(key, defaultValue, prev));
|
|
372
331
|
}
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
332
|
+
// Clear the value from settings.json (set to undefined to remove the key)
|
|
333
|
+
if (!requiresRestart(key)) {
|
|
334
|
+
settings.setValue(selectedScope, key, undefined);
|
|
335
|
+
// Special handling for vim mode
|
|
336
|
+
if (key === 'general.vimMode') {
|
|
337
|
+
const booleanDefaultValue = typeof defaultValue === 'boolean' ? defaultValue : false;
|
|
338
|
+
if (booleanDefaultValue !== vimEnabled) {
|
|
339
|
+
toggleVimEnabled().catch((error) => {
|
|
340
|
+
coreEvents.emitFeedback('error', 'Failed to toggle vim mode:', error);
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
if (key === 'general.previewFeatures') {
|
|
345
|
+
const booleanDefaultValue = typeof defaultValue === 'boolean' ? defaultValue : false;
|
|
346
|
+
config?.setPreviewFeatures(booleanDefaultValue);
|
|
347
|
+
}
|
|
388
348
|
}
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
349
|
+
// Remove from modified sets
|
|
350
|
+
setModifiedSettings((prev) => {
|
|
351
|
+
const updated = new Set(prev);
|
|
352
|
+
updated.delete(key);
|
|
353
|
+
return updated;
|
|
354
|
+
});
|
|
355
|
+
setRestartRequiredSettings((prev) => {
|
|
356
|
+
const updated = new Set(prev);
|
|
357
|
+
updated.delete(key);
|
|
358
|
+
return updated;
|
|
359
|
+
});
|
|
360
|
+
setGlobalPendingChanges((prev) => {
|
|
361
|
+
if (!prev.has(key))
|
|
362
|
+
return prev;
|
|
363
|
+
const next = new Map(prev);
|
|
364
|
+
next.delete(key);
|
|
365
|
+
return next;
|
|
366
|
+
});
|
|
367
|
+
// Update restart prompt
|
|
368
|
+
setShowRestartPrompt((_prev) => {
|
|
369
|
+
const remaining = getRestartRequiredFromModified(modifiedSettings);
|
|
370
|
+
return remaining.filter((k) => k !== key).length > 0;
|
|
371
|
+
});
|
|
372
|
+
}, [
|
|
373
|
+
config,
|
|
374
|
+
settings,
|
|
375
|
+
selectedScope,
|
|
376
|
+
vimEnabled,
|
|
377
|
+
toggleVimEnabled,
|
|
378
|
+
modifiedSettings,
|
|
379
|
+
]);
|
|
380
|
+
const saveRestartRequiredSettings = useCallback(() => {
|
|
396
381
|
const restartRequiredSettings = getRestartRequiredFromModified(modifiedSettings);
|
|
397
382
|
const restartRequiredSet = new Set(restartRequiredSettings);
|
|
398
383
|
if (restartRequiredSet.size > 0) {
|
|
@@ -408,317 +393,82 @@ export function SettingsDialog({ settings, onSelect, onRestartRequest, available
|
|
|
408
393
|
return next;
|
|
409
394
|
});
|
|
410
395
|
}
|
|
411
|
-
};
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
if (key.name === 'paste' && key.sequence) {
|
|
423
|
-
let pasted = key.sequence;
|
|
424
|
-
if (type === 'number') {
|
|
425
|
-
pasted = key.sequence.replace(/[^0-9\-+.]/g, '');
|
|
426
|
-
}
|
|
427
|
-
if (pasted) {
|
|
428
|
-
setEditBuffer((b) => {
|
|
429
|
-
const before = cpSlice(b, 0, editCursorPos);
|
|
430
|
-
const after = cpSlice(b, editCursorPos);
|
|
431
|
-
return before + pasted + after;
|
|
432
|
-
});
|
|
433
|
-
setEditCursorPos((pos) => pos + cpLen(pasted));
|
|
434
|
-
}
|
|
435
|
-
return;
|
|
436
|
-
}
|
|
437
|
-
if (name === 'backspace' || name === 'delete') {
|
|
438
|
-
if (name === 'backspace' && editCursorPos > 0) {
|
|
439
|
-
setEditBuffer((b) => {
|
|
440
|
-
const before = cpSlice(b, 0, editCursorPos - 1);
|
|
441
|
-
const after = cpSlice(b, editCursorPos);
|
|
442
|
-
return before + after;
|
|
443
|
-
});
|
|
444
|
-
setEditCursorPos((pos) => pos - 1);
|
|
445
|
-
}
|
|
446
|
-
else if (name === 'delete' && editCursorPos < cpLen(editBuffer)) {
|
|
447
|
-
setEditBuffer((b) => {
|
|
448
|
-
const before = cpSlice(b, 0, editCursorPos);
|
|
449
|
-
const after = cpSlice(b, editCursorPos + 1);
|
|
450
|
-
return before + after;
|
|
451
|
-
});
|
|
452
|
-
// Cursor position stays the same for delete
|
|
453
|
-
}
|
|
454
|
-
return;
|
|
455
|
-
}
|
|
456
|
-
if (keyMatchers[Command.ESCAPE](key)) {
|
|
457
|
-
commitEdit(editingKey);
|
|
458
|
-
return;
|
|
459
|
-
}
|
|
460
|
-
if (keyMatchers[Command.RETURN](key)) {
|
|
461
|
-
commitEdit(editingKey);
|
|
462
|
-
return;
|
|
463
|
-
}
|
|
464
|
-
let ch = key.sequence;
|
|
465
|
-
let isValidChar = false;
|
|
466
|
-
if (type === 'number') {
|
|
467
|
-
// Allow digits, minus, plus, and dot.
|
|
468
|
-
isValidChar = /[0-9\-+.]/.test(ch);
|
|
469
|
-
}
|
|
470
|
-
else {
|
|
471
|
-
ch = stripUnsafeCharacters(ch);
|
|
472
|
-
// For strings, allow any single character that isn't a control
|
|
473
|
-
// sequence.
|
|
474
|
-
isValidChar = ch.length === 1;
|
|
475
|
-
}
|
|
476
|
-
if (isValidChar) {
|
|
477
|
-
setEditBuffer((currentBuffer) => {
|
|
478
|
-
const beforeCursor = cpSlice(currentBuffer, 0, editCursorPos);
|
|
479
|
-
const afterCursor = cpSlice(currentBuffer, editCursorPos);
|
|
480
|
-
return beforeCursor + ch + afterCursor;
|
|
481
|
-
});
|
|
482
|
-
setEditCursorPos((pos) => pos + 1);
|
|
483
|
-
return;
|
|
484
|
-
}
|
|
485
|
-
// Arrow key navigation
|
|
486
|
-
if (name === 'left') {
|
|
487
|
-
setEditCursorPos((pos) => Math.max(0, pos - 1));
|
|
488
|
-
return;
|
|
489
|
-
}
|
|
490
|
-
if (name === 'right') {
|
|
491
|
-
setEditCursorPos((pos) => Math.min(cpLen(editBuffer), pos + 1));
|
|
492
|
-
return;
|
|
493
|
-
}
|
|
494
|
-
// Home and End keys
|
|
495
|
-
if (keyMatchers[Command.HOME](key)) {
|
|
496
|
-
setEditCursorPos(0);
|
|
497
|
-
return;
|
|
498
|
-
}
|
|
499
|
-
if (keyMatchers[Command.END](key)) {
|
|
500
|
-
setEditCursorPos(cpLen(editBuffer));
|
|
501
|
-
return;
|
|
502
|
-
}
|
|
503
|
-
// Block other keys while editing
|
|
504
|
-
return;
|
|
505
|
-
}
|
|
506
|
-
if (keyMatchers[Command.DIALOG_NAVIGATION_UP](key)) {
|
|
507
|
-
// If editing, commit first
|
|
508
|
-
if (editingKey) {
|
|
509
|
-
commitEdit(editingKey);
|
|
510
|
-
}
|
|
511
|
-
const newIndex = activeSettingIndex > 0 ? activeSettingIndex - 1 : items.length - 1;
|
|
512
|
-
setActiveSettingIndex(newIndex);
|
|
513
|
-
// Adjust scroll offset for wrap-around
|
|
514
|
-
if (newIndex === items.length - 1) {
|
|
515
|
-
setScrollOffset(Math.max(0, items.length - effectiveMaxItemsToShow));
|
|
516
|
-
}
|
|
517
|
-
else if (newIndex < scrollOffset) {
|
|
518
|
-
setScrollOffset(newIndex);
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
else if (keyMatchers[Command.DIALOG_NAVIGATION_DOWN](key)) {
|
|
522
|
-
// If editing, commit first
|
|
523
|
-
if (editingKey) {
|
|
524
|
-
commitEdit(editingKey);
|
|
525
|
-
}
|
|
526
|
-
const newIndex = activeSettingIndex < items.length - 1 ? activeSettingIndex + 1 : 0;
|
|
527
|
-
setActiveSettingIndex(newIndex);
|
|
528
|
-
// Adjust scroll offset for wrap-around
|
|
529
|
-
if (newIndex === 0) {
|
|
530
|
-
setScrollOffset(0);
|
|
531
|
-
}
|
|
532
|
-
else if (newIndex >= scrollOffset + effectiveMaxItemsToShow) {
|
|
533
|
-
setScrollOffset(newIndex - effectiveMaxItemsToShow + 1);
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
else if (keyMatchers[Command.RETURN](key)) {
|
|
537
|
-
const currentItem = items[activeSettingIndex];
|
|
538
|
-
if (currentItem?.type === 'number' ||
|
|
539
|
-
currentItem?.type === 'string') {
|
|
540
|
-
startEditing(currentItem.value);
|
|
541
|
-
}
|
|
542
|
-
else {
|
|
543
|
-
currentItem?.toggle();
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
else if (/^[0-9]$/.test(key.sequence || '') && !editingKey) {
|
|
547
|
-
const currentItem = items[activeSettingIndex];
|
|
548
|
-
if (currentItem?.type === 'number') {
|
|
549
|
-
startEditing(currentItem.value, key.sequence);
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
else if (keyMatchers[Command.CLEAR_INPUT](key) ||
|
|
553
|
-
keyMatchers[Command.CLEAR_SCREEN](key)) {
|
|
554
|
-
// Ctrl+C or Ctrl+L: Clear current setting and reset to default
|
|
555
|
-
const currentSetting = items[activeSettingIndex];
|
|
556
|
-
if (currentSetting) {
|
|
557
|
-
const defaultValue = getEffectiveDefaultValue(currentSetting.value, config);
|
|
558
|
-
const defType = currentSetting.type;
|
|
559
|
-
if (defType === 'boolean') {
|
|
560
|
-
const booleanDefaultValue = typeof defaultValue === 'boolean' ? defaultValue : false;
|
|
561
|
-
setPendingSettings((prev) => setPendingSettingValue(currentSetting.value, booleanDefaultValue, prev));
|
|
562
|
-
}
|
|
563
|
-
else if (defType === 'number' || defType === 'string') {
|
|
564
|
-
if (typeof defaultValue === 'number' ||
|
|
565
|
-
typeof defaultValue === 'string') {
|
|
566
|
-
setPendingSettings((prev) => setPendingSettingValueAny(currentSetting.value, defaultValue, prev));
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
// Remove from modified settings since it's now at default
|
|
570
|
-
setModifiedSettings((prev) => {
|
|
571
|
-
const updated = new Set(prev);
|
|
572
|
-
updated.delete(currentSetting.value);
|
|
573
|
-
return updated;
|
|
574
|
-
});
|
|
575
|
-
// Remove from restart-required settings if it was there
|
|
576
|
-
setRestartRequiredSettings((prev) => {
|
|
577
|
-
const updated = new Set(prev);
|
|
578
|
-
updated.delete(currentSetting.value);
|
|
579
|
-
return updated;
|
|
580
|
-
});
|
|
581
|
-
// If this setting doesn't require restart, save it immediately
|
|
582
|
-
if (!requiresRestart(currentSetting.value)) {
|
|
583
|
-
const immediateSettings = new Set([currentSetting.value]);
|
|
584
|
-
const toSaveValue = currentSetting.type === 'boolean'
|
|
585
|
-
? typeof defaultValue === 'boolean'
|
|
586
|
-
? defaultValue
|
|
587
|
-
: false
|
|
588
|
-
: typeof defaultValue === 'number' ||
|
|
589
|
-
typeof defaultValue === 'string'
|
|
590
|
-
? defaultValue
|
|
591
|
-
: undefined;
|
|
592
|
-
const currentScopeSettings = settings.forScope(selectedScope).settings;
|
|
593
|
-
const immediateSettingsObject = toSaveValue !== undefined
|
|
594
|
-
? setPendingSettingValueAny(currentSetting.value, toSaveValue, currentScopeSettings)
|
|
595
|
-
: currentScopeSettings;
|
|
596
|
-
saveModifiedSettings(immediateSettings, immediateSettingsObject, settings, selectedScope);
|
|
597
|
-
// Remove from global pending changes if present
|
|
598
|
-
setGlobalPendingChanges((prev) => {
|
|
599
|
-
if (!prev.has(currentSetting.value))
|
|
600
|
-
return prev;
|
|
601
|
-
const next = new Map(prev);
|
|
602
|
-
next.delete(currentSetting.value);
|
|
603
|
-
return next;
|
|
604
|
-
});
|
|
605
|
-
}
|
|
606
|
-
else {
|
|
607
|
-
// Track default reset as a pending change if restart required
|
|
608
|
-
if ((currentSetting.type === 'boolean' &&
|
|
609
|
-
typeof defaultValue === 'boolean') ||
|
|
610
|
-
(currentSetting.type === 'number' &&
|
|
611
|
-
typeof defaultValue === 'number') ||
|
|
612
|
-
(currentSetting.type === 'string' &&
|
|
613
|
-
typeof defaultValue === 'string')) {
|
|
614
|
-
setGlobalPendingChanges((prev) => {
|
|
615
|
-
const next = new Map(prev);
|
|
616
|
-
next.set(currentSetting.value, defaultValue);
|
|
617
|
-
return next;
|
|
618
|
-
});
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
if (showRestartPrompt && name === 'r') {
|
|
625
|
-
// Only save settings that require restart (non-restart settings were already saved immediately)
|
|
626
|
-
saveRestartRequiredSettings();
|
|
396
|
+
}, [modifiedSettings, pendingSettings, settings, selectedScope]);
|
|
397
|
+
// Close handler
|
|
398
|
+
const handleClose = useCallback(() => {
|
|
399
|
+
// Save any restart-required settings before closing
|
|
400
|
+
saveRestartRequiredSettings();
|
|
401
|
+
onSelect(undefined, selectedScope);
|
|
402
|
+
}, [saveRestartRequiredSettings, onSelect, selectedScope]);
|
|
403
|
+
// Custom key handler for restart key
|
|
404
|
+
const handleKeyPress = useCallback((key, _currentItem) => {
|
|
405
|
+
// 'r' key for restart
|
|
406
|
+
if (showRestartPrompt && key.sequence === 'r') {
|
|
627
407
|
setShowRestartPrompt(false);
|
|
628
|
-
|
|
408
|
+
setModifiedSettings(new Set());
|
|
409
|
+
setRestartRequiredSettings(new Set());
|
|
629
410
|
if (onRestartRequest)
|
|
630
411
|
onRestartRequest();
|
|
412
|
+
return true;
|
|
631
413
|
}
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
414
|
+
return false;
|
|
415
|
+
}, [showRestartPrompt, onRestartRequest]);
|
|
416
|
+
// Calculate effective max items and scope visibility based on terminal height
|
|
417
|
+
const { effectiveMaxItemsToShow, showScopeSelection } = useMemo(() => {
|
|
418
|
+
// Only show scope selector if we have a workspace
|
|
419
|
+
const hasWorkspace = settings.workspace.path !== undefined;
|
|
420
|
+
if (!availableTerminalHeight) {
|
|
421
|
+
return {
|
|
422
|
+
effectiveMaxItemsToShow: Math.min(MAX_ITEMS_TO_SHOW, items.length),
|
|
423
|
+
showScopeSelection: hasWorkspace,
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
// Layout constants
|
|
427
|
+
const DIALOG_PADDING = 2; // Top and bottom borders
|
|
428
|
+
const SETTINGS_TITLE_HEIGHT = 1;
|
|
429
|
+
const SEARCH_BOX_HEIGHT = 3;
|
|
430
|
+
const SCROLL_ARROWS_HEIGHT = 2;
|
|
431
|
+
const SPACING_HEIGHT = 2;
|
|
432
|
+
const SCOPE_SELECTION_HEIGHT = 4;
|
|
433
|
+
const BOTTOM_HELP_TEXT_HEIGHT = 1;
|
|
434
|
+
const RESTART_PROMPT_HEIGHT = showRestartPrompt ? 1 : 0;
|
|
435
|
+
const ITEM_HEIGHT = 3; // Label + description + spacing
|
|
436
|
+
const currentAvailableHeight = availableTerminalHeight - DIALOG_PADDING;
|
|
437
|
+
const baseFixedHeight = SETTINGS_TITLE_HEIGHT +
|
|
438
|
+
SEARCH_BOX_HEIGHT +
|
|
439
|
+
SCROLL_ARROWS_HEIGHT +
|
|
440
|
+
SPACING_HEIGHT +
|
|
441
|
+
BOTTOM_HELP_TEXT_HEIGHT +
|
|
442
|
+
RESTART_PROMPT_HEIGHT;
|
|
443
|
+
// Calculate max items with scope selector
|
|
444
|
+
const heightWithScope = baseFixedHeight + SCOPE_SELECTION_HEIGHT;
|
|
445
|
+
const availableForItemsWithScope = currentAvailableHeight - heightWithScope;
|
|
446
|
+
const maxItemsWithScope = Math.max(1, Math.floor(availableForItemsWithScope / ITEM_HEIGHT));
|
|
447
|
+
// Calculate max items without scope selector
|
|
448
|
+
const availableForItemsWithoutScope = currentAvailableHeight - baseFixedHeight;
|
|
449
|
+
const maxItemsWithoutScope = Math.max(1, Math.floor(availableForItemsWithoutScope / ITEM_HEIGHT));
|
|
450
|
+
// In small terminals, hide scope selector if it would allow more items to show
|
|
451
|
+
let shouldShowScope = hasWorkspace;
|
|
452
|
+
let maxItems = maxItemsWithScope;
|
|
453
|
+
if (hasWorkspace && availableTerminalHeight < 25) {
|
|
454
|
+
// Hide scope selector if it gains us more than 1 extra item
|
|
455
|
+
if (maxItemsWithoutScope > maxItemsWithScope + 1) {
|
|
456
|
+
shouldShowScope = false;
|
|
457
|
+
maxItems = maxItemsWithoutScope;
|
|
640
458
|
}
|
|
641
459
|
}
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
});
|
|
656
|
-
return (_jsx(Box, { borderStyle: "round", borderColor: theme.border.default, flexDirection: "row", padding: 1, width: "100%", height: "100%", children: _jsxs(Box, { flexDirection: "column", flexGrow: 1, children: [_jsx(Box, { marginX: 1, children: _jsxs(Text, { bold: focusSection === 'settings' && !editingKey, wrap: "truncate", children: [focusSection === 'settings' ? '> ' : ' ', "Settings", ' '] }) }), _jsx(Box, { borderStyle: "round", borderColor: editingKey
|
|
657
|
-
? theme.border.default
|
|
658
|
-
: focusSection === 'settings'
|
|
659
|
-
? theme.border.focused
|
|
660
|
-
: theme.border.default, paddingX: 1, height: 3, marginTop: 1, children: _jsx(TextInput, { focus: focusSection === 'settings' && !editingKey, buffer: buffer, placeholder: "Search to filter" }) }), _jsx(Box, { height: 1 }), visibleItems.length === 0 ? (_jsx(Box, { marginX: 1, height: 1, flexDirection: "column", children: _jsx(Text, { color: theme.text.secondary, children: "No matches found." }) })) : (_jsxs(_Fragment, { children: [showScrollUp && (_jsx(Box, { marginX: 1, children: _jsx(Text, { color: theme.text.secondary, children: "\u25B2" }) })), visibleItems.map((item, idx) => {
|
|
661
|
-
const isActive = focusSection === 'settings' &&
|
|
662
|
-
activeSettingIndex === idx + scrollOffset;
|
|
663
|
-
const scopeSettings = settings.forScope(selectedScope).settings;
|
|
664
|
-
const mergedSettings = settings.merged;
|
|
665
|
-
let displayValue;
|
|
666
|
-
if (editingKey === item.value) {
|
|
667
|
-
// Show edit buffer with advanced cursor highlighting
|
|
668
|
-
if (cursorVisible && editCursorPos < cpLen(editBuffer)) {
|
|
669
|
-
// Cursor is in the middle or at start of text
|
|
670
|
-
const beforeCursor = cpSlice(editBuffer, 0, editCursorPos);
|
|
671
|
-
const atCursor = cpSlice(editBuffer, editCursorPos, editCursorPos + 1);
|
|
672
|
-
const afterCursor = cpSlice(editBuffer, editCursorPos + 1);
|
|
673
|
-
displayValue =
|
|
674
|
-
beforeCursor + chalk.inverse(atCursor) + afterCursor;
|
|
675
|
-
}
|
|
676
|
-
else if (cursorVisible &&
|
|
677
|
-
editCursorPos >= cpLen(editBuffer)) {
|
|
678
|
-
// Cursor is at the end - show inverted space
|
|
679
|
-
displayValue = editBuffer + chalk.inverse(' ');
|
|
680
|
-
}
|
|
681
|
-
else {
|
|
682
|
-
// Cursor not visible
|
|
683
|
-
displayValue = editBuffer;
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
else if (item.type === 'number' || item.type === 'string') {
|
|
687
|
-
// For numbers/strings, get the actual current value from pending settings
|
|
688
|
-
const path = item.value.split('.');
|
|
689
|
-
const currentValue = getNestedValue(pendingSettings, path);
|
|
690
|
-
const defaultValue = getEffectiveDefaultValue(item.value, config);
|
|
691
|
-
if (currentValue !== undefined && currentValue !== null) {
|
|
692
|
-
displayValue = String(currentValue);
|
|
693
|
-
}
|
|
694
|
-
else {
|
|
695
|
-
displayValue =
|
|
696
|
-
defaultValue !== undefined && defaultValue !== null
|
|
697
|
-
? String(defaultValue)
|
|
698
|
-
: '';
|
|
699
|
-
}
|
|
700
|
-
// Add * if value differs from default OR if currently being modified
|
|
701
|
-
const isModified = modifiedSettings.has(item.value);
|
|
702
|
-
const effectiveCurrentValue = currentValue !== undefined && currentValue !== null
|
|
703
|
-
? currentValue
|
|
704
|
-
: defaultValue;
|
|
705
|
-
const isDifferentFromDefault = effectiveCurrentValue !== defaultValue;
|
|
706
|
-
if (isDifferentFromDefault || isModified) {
|
|
707
|
-
displayValue += '*';
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
else {
|
|
711
|
-
// For booleans and other types, use existing logic
|
|
712
|
-
displayValue = getDisplayValue(item.value, scopeSettings, mergedSettings, modifiedSettings, pendingSettings);
|
|
713
|
-
}
|
|
714
|
-
const shouldBeGreyedOut = isDefaultValue(item.value, scopeSettings);
|
|
715
|
-
// Generate scope message for this setting
|
|
716
|
-
const scopeMessage = getScopeMessageForSetting(item.value, selectedScope, settings);
|
|
717
|
-
return (_jsxs(React.Fragment, { children: [_jsxs(Box, { marginX: 1, flexDirection: "row", alignItems: "flex-start", children: [_jsx(Box, { minWidth: 2, flexShrink: 0, children: _jsx(Text, { color: isActive ? theme.status.success : theme.text.secondary, children: isActive ? '●' : '' }) }), _jsxs(Box, { flexDirection: "row", flexGrow: 1, minWidth: 0, alignItems: "flex-start", children: [_jsxs(Box, { flexDirection: "column", width: maxLabelOrDescriptionWidth, minWidth: 0, children: [_jsxs(Text, { color: isActive ? theme.status.success : theme.text.primary, children: [item.label, scopeMessage && (_jsxs(Text, { color: theme.text.secondary, children: [' ', scopeMessage] }))] }), _jsx(Text, { color: theme.text.secondary, wrap: "truncate", children: item.description ?? '' })] }), _jsx(Box, { minWidth: 3 }), _jsx(Box, { flexShrink: 0, children: _jsx(Text, { color: isActive
|
|
718
|
-
? theme.status.success
|
|
719
|
-
: shouldBeGreyedOut
|
|
720
|
-
? theme.text.secondary
|
|
721
|
-
: theme.text.primary, children: displayValue }) })] })] }), _jsx(Box, { height: 1 })] }, item.value));
|
|
722
|
-
}), showScrollDown && (_jsx(Box, { marginX: 1, children: _jsx(Text, { color: theme.text.secondary, children: "\u25BC" }) }))] })), _jsx(Box, { height: 1 }), showScopeSelection && (_jsxs(Box, { marginX: 1, flexDirection: "column", children: [_jsxs(Text, { bold: focusSection === 'scope', wrap: "truncate", children: [focusSection === 'scope' ? '> ' : ' ', "Apply To"] }), _jsx(RadioButtonSelect, { items: scopeItems, initialIndex: scopeItems.findIndex((item) => item.value === selectedScope), onSelect: handleScopeSelect, onHighlight: handleScopeHighlight, isFocused: focusSection === 'scope', showNumbers: focusSection === 'scope' })] })), _jsx(Box, { height: 1 }), _jsx(Box, { marginX: 1, children: _jsxs(Text, { color: theme.text.secondary, children: ["(Use Enter to select", showScopeSelection ? ', Tab to change focus' : '', ", Esc to close)"] }) }), showRestartPrompt && (_jsx(Box, { marginX: 1, children: _jsx(Text, { color: theme.status.warning, children: "To see changes, Gemini CLI must be restarted. Press r to exit and apply changes now." }) }))] }) }));
|
|
460
|
+
return {
|
|
461
|
+
effectiveMaxItemsToShow: Math.min(maxItems, items.length),
|
|
462
|
+
showScopeSelection: shouldShowScope,
|
|
463
|
+
};
|
|
464
|
+
}, [
|
|
465
|
+
availableTerminalHeight,
|
|
466
|
+
items.length,
|
|
467
|
+
settings.workspace.path,
|
|
468
|
+
showRestartPrompt,
|
|
469
|
+
]);
|
|
470
|
+
// Footer content for restart prompt
|
|
471
|
+
const footerContent = showRestartPrompt ? (_jsx(Text, { color: theme.status.warning, children: "To see changes, Gemini CLI must be restarted. Press r to exit and apply changes now." })) : null;
|
|
472
|
+
return (_jsx(BaseSettingsDialog, { title: "Settings", searchEnabled: true, searchBuffer: searchBuffer, items: items, showScopeSelector: showScopeSelection, selectedScope: selectedScope, onScopeChange: handleScopeChange, maxItemsToShow: effectiveMaxItemsToShow, maxLabelWidth: maxLabelOrDescriptionWidth, onItemToggle: handleItemToggle, onEditCommit: handleEditCommit, onItemClear: handleItemClear, onClose: handleClose, onKeyPress: handleKeyPress, footerContent: footerContent }));
|
|
723
473
|
}
|
|
724
474
|
//# sourceMappingURL=SettingsDialog.js.map
|