diff --git a/packages/cli/src/ui/components/EditorSettingsDialog.test.tsx b/packages/cli/src/ui/components/EditorSettingsDialog.test.tsx index 18b47def7b..7646ac4817 100644 --- a/packages/cli/src/ui/components/EditorSettingsDialog.test.tsx +++ b/packages/cli/src/ui/components/EditorSettingsDialog.test.tsx @@ -175,4 +175,45 @@ describe('EditorSettingsDialog', () => { } expect(frame).toContain('(Also modified'); }); + + it('emits error feedback only once when preferredEditor is invalid', async () => { + const mockEmitFeedback = vi.fn(); + vi.spyOn( + await import('@google/gemini-cli-core').then((m) => m.coreEvents), + 'emitFeedback', + ).mockImplementation(mockEmitFeedback); + + const invalidSettings = { + forScope: (_scope: string) => ({ + settings: { + general: { + preferredEditor: 'invalideditor', + }, + }, + }), + merged: { + general: { + preferredEditor: 'invalideditor', + }, + }, + } as unknown as LoadedSettings; + + const { unmount } = await renderWithProvider( + , + ); + + await waitFor(() => { + expect(mockEmitFeedback).toHaveBeenCalledWith( + 'error', + 'Editor is not supported: invalideditor', + ); + }); + + expect(mockEmitFeedback).toHaveBeenCalledTimes(1); + unmount(); + }); }); diff --git a/packages/cli/src/ui/components/EditorSettingsDialog.tsx b/packages/cli/src/ui/components/EditorSettingsDialog.tsx index 5d4206a104..a98042773f 100644 --- a/packages/cli/src/ui/components/EditorSettingsDialog.tsx +++ b/packages/cli/src/ui/components/EditorSettingsDialog.tsx @@ -5,7 +5,7 @@ */ import type React from 'react'; -import { useState } from 'react'; +import { useState, useEffect } from 'react'; import { Box, Text } from 'ink'; import { theme } from '../semantic-colors.js'; import { @@ -22,6 +22,7 @@ import { type EditorType, isEditorAvailable, EDITOR_DISPLAY_NAMES, + coreEvents, } from '@google/gemini-cli-core'; import { useKeypress } from '../hooks/useKeypress.js'; @@ -70,10 +71,20 @@ export function EditorSettingsDialog({ (item: EditorDisplay) => item.type === currentPreference, ) : 0; - if (editorIndex === -1) { + const isUnsupportedEditor = editorIndex === -1; + if (isUnsupportedEditor) { editorIndex = 0; } + useEffect(() => { + if (isUnsupportedEditor && currentPreference) { + coreEvents.emitFeedback( + 'error', + `Editor is not supported: ${currentPreference}`, + ); + } + }, [isUnsupportedEditor, currentPreference]); + const scopeItems: Array<{ label: string; value: LoadableSettingScope; diff --git a/packages/cli/src/ui/components/__snapshots__/InputPrompt.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/InputPrompt.test.tsx.snap index c6afb12614..db449ce4d7 100644 --- a/packages/cli/src/ui/components/__snapshots__/InputPrompt.test.tsx.snap +++ b/packages/cli/src/ui/components/__snapshots__/InputPrompt.test.tsx.snap @@ -60,12 +60,6 @@ exports[`InputPrompt > Highlighting and Cursor Display > single-line scenarios > ────────────────────────────────────────────────────────────────────────────────────────────────────" `; -exports[`InputPrompt > Highlighting and Cursor Display > single-line scenarios > should display cursor correctly 'at the end of the line' 2`] = ` -"──────────────────────────────────────────────────────────────────────────────────────────────────── - > hello -────────────────────────────────────────────────────────────────────────────────────────────────────" -`; - exports[`InputPrompt > Highlighting and Cursor Display > single-line scenarios > should display cursor correctly 'for multi-byte unicode characters' 1`] = ` "──────────────────────────────────────────────────────────────────────────────────────────────────── > hello 👍 world