Skip to content

Commit e3c0263

Browse files
Niralisjscidomino
authored andcommitted
fix(cli): prevent spam loop when preferredEditor is invalid (google-gemini#25324)
Co-authored-by: Tommaso Sciortino <sciortino@gmail.com>
1 parent 689ba67 commit e3c0263

3 files changed

Lines changed: 54 additions & 8 deletions

File tree

packages/cli/src/ui/components/EditorSettingsDialog.test.tsx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,4 +175,45 @@ describe('EditorSettingsDialog', () => {
175175
}
176176
expect(frame).toContain('(Also modified');
177177
});
178+
179+
it('emits error feedback only once when preferredEditor is invalid', async () => {
180+
const mockEmitFeedback = vi.fn();
181+
vi.spyOn(
182+
await import('@google/gemini-cli-core').then((m) => m.coreEvents),
183+
'emitFeedback',
184+
).mockImplementation(mockEmitFeedback);
185+
186+
const invalidSettings = {
187+
forScope: (_scope: string) => ({
188+
settings: {
189+
general: {
190+
preferredEditor: 'invalideditor',
191+
},
192+
},
193+
}),
194+
merged: {
195+
general: {
196+
preferredEditor: 'invalideditor',
197+
},
198+
},
199+
} as unknown as LoadedSettings;
200+
201+
const { unmount } = await renderWithProvider(
202+
<EditorSettingsDialog
203+
onSelect={vi.fn()}
204+
settings={invalidSettings}
205+
onExit={vi.fn()}
206+
/>,
207+
);
208+
209+
await waitFor(() => {
210+
expect(mockEmitFeedback).toHaveBeenCalledWith(
211+
'error',
212+
'Editor is not supported: invalideditor',
213+
);
214+
});
215+
216+
expect(mockEmitFeedback).toHaveBeenCalledTimes(1);
217+
unmount();
218+
});
178219
});

packages/cli/src/ui/components/EditorSettingsDialog.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66

77
import type React from 'react';
8-
import { useState } from 'react';
8+
import { useState, useEffect } from 'react';
99
import { Box, Text } from 'ink';
1010
import { theme } from '../semantic-colors.js';
1111
import {
@@ -22,6 +22,7 @@ import {
2222
type EditorType,
2323
isEditorAvailable,
2424
EDITOR_DISPLAY_NAMES,
25+
coreEvents,
2526
} from '@google/gemini-cli-core';
2627
import { useKeypress } from '../hooks/useKeypress.js';
2728

@@ -70,10 +71,20 @@ export function EditorSettingsDialog({
7071
(item: EditorDisplay) => item.type === currentPreference,
7172
)
7273
: 0;
73-
if (editorIndex === -1) {
74+
const isUnsupportedEditor = editorIndex === -1;
75+
if (isUnsupportedEditor) {
7476
editorIndex = 0;
7577
}
7678

79+
useEffect(() => {
80+
if (isUnsupportedEditor && currentPreference) {
81+
coreEvents.emitFeedback(
82+
'error',
83+
`Editor is not supported: ${currentPreference}`,
84+
);
85+
}
86+
}, [isUnsupportedEditor, currentPreference]);
87+
7788
const scopeItems: Array<{
7889
label: string;
7990
value: LoadableSettingScope;

packages/cli/src/ui/components/__snapshots__/InputPrompt.test.tsx.snap

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,6 @@ exports[`InputPrompt > Highlighting and Cursor Display > single-line scenarios >
6060
────────────────────────────────────────────────────────────────────────────────────────────────────"
6161
`;
6262

63-
exports[`InputPrompt > Highlighting and Cursor Display > single-line scenarios > should display cursor correctly 'at the end of the line' 2`] = `
64-
"────────────────────────────────────────────────────────────────────────────────────────────────────
65-
> hello
66-
────────────────────────────────────────────────────────────────────────────────────────────────────"
67-
`;
68-
6963
exports[`InputPrompt > Highlighting and Cursor Display > single-line scenarios > should display cursor correctly 'for multi-byte unicode characters' 1`] = `
7064
"────────────────────────────────────────────────────────────────────────────────────────────────────
7165
> hello 👍 world

0 commit comments

Comments
 (0)