mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-14 16:10:59 -07:00
fix(cli): allow perfect match @-path completions to submit on Enter (#19562)
This commit is contained in:
@@ -1065,7 +1065,7 @@ describe('InputPrompt', () => {
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('should NOT submit on Enter when an @-path is a perfect match', async () => {
|
||||
it('should submit on Enter when an @-path is a perfect match', async () => {
|
||||
mockedUseCommandCompletion.mockReturnValue({
|
||||
...mockCommandCompletion,
|
||||
showSuggestions: true,
|
||||
@@ -1085,13 +1085,38 @@ describe('InputPrompt', () => {
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
// Should handle autocomplete but NOT submit
|
||||
expect(mockCommandCompletion.handleAutocomplete).toHaveBeenCalledWith(0);
|
||||
expect(props.onSubmit).not.toHaveBeenCalled();
|
||||
// Should submit directly
|
||||
expect(props.onSubmit).toHaveBeenCalledWith('@file.txt');
|
||||
});
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('should NOT submit on Shift+Enter even if an @-path is a perfect match', async () => {
|
||||
mockedUseCommandCompletion.mockReturnValue({
|
||||
...mockCommandCompletion,
|
||||
showSuggestions: true,
|
||||
suggestions: [{ label: 'file.txt', value: 'file.txt' }],
|
||||
activeSuggestionIndex: 0,
|
||||
isPerfectMatch: true,
|
||||
completionMode: CompletionMode.AT,
|
||||
});
|
||||
props.buffer.text = '@file.txt';
|
||||
|
||||
const { stdin, unmount } = renderWithProviders(<InputPrompt {...props} />, {
|
||||
uiActions,
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
// Simulate Shift+Enter using CSI u sequence
|
||||
stdin.write('\x1b[13;2u');
|
||||
});
|
||||
|
||||
// Should NOT submit, should call newline instead
|
||||
expect(props.onSubmit).not.toHaveBeenCalled();
|
||||
expect(props.buffer.newline).toHaveBeenCalled();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('should auto-execute commands with autoExecute: true on Enter', async () => {
|
||||
const aboutCommand: SlashCommand = {
|
||||
name: 'about',
|
||||
@@ -2285,6 +2310,36 @@ describe('InputPrompt', () => {
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('should prevent perfect match auto-submission immediately after an unsafe paste', async () => {
|
||||
// isTerminalPasteTrusted will be false due to beforeEach setup.
|
||||
mockedUseCommandCompletion.mockReturnValue({
|
||||
...mockCommandCompletion,
|
||||
isPerfectMatch: true,
|
||||
completionMode: CompletionMode.AT,
|
||||
});
|
||||
props.buffer.text = '@file.txt';
|
||||
|
||||
const { stdin, unmount } = renderWithProviders(
|
||||
<InputPrompt {...props} />,
|
||||
);
|
||||
|
||||
// Simulate an unsafe paste of a perfect match
|
||||
await act(async () => {
|
||||
stdin.write(`\x1b[200~@file.txt\x1b[201~`);
|
||||
});
|
||||
|
||||
// Simulate an Enter key press immediately after paste
|
||||
await act(async () => {
|
||||
stdin.write('\r');
|
||||
});
|
||||
|
||||
// Verify that onSubmit was NOT called due to recent paste protection
|
||||
expect(props.onSubmit).not.toHaveBeenCalled();
|
||||
// It should call newline() instead
|
||||
expect(props.buffer.newline).toHaveBeenCalled();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('should allow submission after unsafe paste protection timeout', async () => {
|
||||
// isTerminalPasteTrusted will be false due to beforeEach setup.
|
||||
props.buffer.text = 'pasted text';
|
||||
|
||||
@@ -890,14 +890,20 @@ export const InputPrompt: React.FC<InputPromptProps> = ({
|
||||
// We prioritize execution unless the user is explicitly selecting a different suggestion.
|
||||
if (
|
||||
completion.isPerfectMatch &&
|
||||
completion.completionMode !== CompletionMode.AT &&
|
||||
keyMatchers[Command.RETURN](key) &&
|
||||
keyMatchers[Command.SUBMIT](key) &&
|
||||
recentUnsafePasteTime === null &&
|
||||
(!completion.showSuggestions || completion.activeSuggestionIndex <= 0)
|
||||
) {
|
||||
handleSubmit(buffer.text);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Newline insertion
|
||||
if (keyMatchers[Command.NEWLINE](key)) {
|
||||
buffer.newline();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (completion.showSuggestions) {
|
||||
if (completion.suggestions.length > 1) {
|
||||
if (keyMatchers[Command.COMPLETION_UP](key)) {
|
||||
@@ -1078,12 +1084,6 @@ export const InputPrompt: React.FC<InputPromptProps> = ({
|
||||
return true;
|
||||
}
|
||||
|
||||
// Newline insertion
|
||||
if (keyMatchers[Command.NEWLINE](key)) {
|
||||
buffer.newline();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ctrl+A (Home) / Ctrl+E (End)
|
||||
if (keyMatchers[Command.HOME](key)) {
|
||||
buffer.move('home');
|
||||
|
||||
Reference in New Issue
Block a user