mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-22 19:14:33 -07:00
feat(cli): add quick clear input shortcuts in vim mode (#17470)
Co-authored-by: Tommaso Sciortino <sciortino@gmail.com>
This commit is contained in:
committed by
GitHub
parent
4827333c48
commit
b8319bee76
@@ -89,6 +89,7 @@ const TEST_SEQUENCES = {
|
||||
LINE_START: createKey({ sequence: '0' }),
|
||||
LINE_END: createKey({ sequence: '$' }),
|
||||
REPEAT: createKey({ sequence: '.' }),
|
||||
CTRL_C: createKey({ sequence: '\x03', name: 'c', ctrl: true }),
|
||||
} as const;
|
||||
|
||||
describe('useVim hook', () => {
|
||||
@@ -1614,4 +1615,141 @@ describe('useVim hook', () => {
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe('double-escape to clear buffer', () => {
|
||||
beforeEach(() => {
|
||||
mockBuffer = createMockBuffer('hello world');
|
||||
mockVimContext.vimEnabled = true;
|
||||
mockVimContext.vimMode = 'NORMAL';
|
||||
mockHandleFinalSubmit = vi.fn();
|
||||
vi.useFakeTimers();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it('should clear buffer on double-escape in NORMAL mode', async () => {
|
||||
const { result } = renderHook(() =>
|
||||
useVim(mockBuffer as TextBuffer, mockHandleFinalSubmit),
|
||||
);
|
||||
|
||||
// First escape - should pass through (return false)
|
||||
let handled: boolean;
|
||||
await act(async () => {
|
||||
handled = result.current.handleInput(TEST_SEQUENCES.ESCAPE);
|
||||
});
|
||||
expect(handled!).toBe(false);
|
||||
|
||||
// Second escape within timeout - should clear buffer (return true)
|
||||
await act(async () => {
|
||||
handled = result.current.handleInput(TEST_SEQUENCES.ESCAPE);
|
||||
});
|
||||
expect(handled!).toBe(true);
|
||||
expect(mockBuffer.setText).toHaveBeenCalledWith('');
|
||||
});
|
||||
|
||||
it('should clear buffer on double-escape in INSERT mode', async () => {
|
||||
mockVimContext.vimMode = 'INSERT';
|
||||
const { result } = renderHook(() =>
|
||||
useVim(mockBuffer as TextBuffer, mockHandleFinalSubmit),
|
||||
);
|
||||
|
||||
// First escape - switches to NORMAL mode
|
||||
let handled: boolean;
|
||||
await act(async () => {
|
||||
handled = result.current.handleInput(TEST_SEQUENCES.ESCAPE);
|
||||
});
|
||||
expect(handled!).toBe(true);
|
||||
expect(mockBuffer.vimEscapeInsertMode).toHaveBeenCalled();
|
||||
|
||||
// Second escape within timeout - should clear buffer
|
||||
await act(async () => {
|
||||
handled = result.current.handleInput(TEST_SEQUENCES.ESCAPE);
|
||||
});
|
||||
expect(handled!).toBe(true);
|
||||
expect(mockBuffer.setText).toHaveBeenCalledWith('');
|
||||
});
|
||||
|
||||
it('should NOT clear buffer if escapes are too slow', async () => {
|
||||
const { result } = renderHook(() =>
|
||||
useVim(mockBuffer as TextBuffer, mockHandleFinalSubmit),
|
||||
);
|
||||
|
||||
// First escape
|
||||
await act(async () => {
|
||||
result.current.handleInput(TEST_SEQUENCES.ESCAPE);
|
||||
});
|
||||
|
||||
// Wait longer than timeout (500ms)
|
||||
await act(async () => {
|
||||
vi.advanceTimersByTime(600);
|
||||
});
|
||||
|
||||
// Second escape - should NOT clear buffer because timeout expired
|
||||
let handled: boolean;
|
||||
await act(async () => {
|
||||
handled = result.current.handleInput(TEST_SEQUENCES.ESCAPE);
|
||||
});
|
||||
// First escape of new sequence, passes through
|
||||
expect(handled!).toBe(false);
|
||||
expect(mockBuffer.setText).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should clear escape history when clearing pending operator', async () => {
|
||||
const { result } = renderHook(() =>
|
||||
useVim(mockBuffer as TextBuffer, mockHandleFinalSubmit),
|
||||
);
|
||||
|
||||
// First escape
|
||||
await act(async () => {
|
||||
result.current.handleInput(TEST_SEQUENCES.ESCAPE);
|
||||
});
|
||||
|
||||
// Type 'd' to set pending operator
|
||||
await act(async () => {
|
||||
result.current.handleInput(TEST_SEQUENCES.DELETE);
|
||||
});
|
||||
|
||||
// Escape to clear pending operator
|
||||
await act(async () => {
|
||||
result.current.handleInput(TEST_SEQUENCES.ESCAPE);
|
||||
});
|
||||
|
||||
// Another escape - should NOT clear buffer (history was reset)
|
||||
let handled: boolean;
|
||||
await act(async () => {
|
||||
handled = result.current.handleInput(TEST_SEQUENCES.ESCAPE);
|
||||
});
|
||||
expect(handled!).toBe(false);
|
||||
expect(mockBuffer.setText).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should pass Ctrl+C through to InputPrompt in NORMAL mode', async () => {
|
||||
const { result } = renderHook(() =>
|
||||
useVim(mockBuffer as TextBuffer, mockHandleFinalSubmit),
|
||||
);
|
||||
|
||||
let handled: boolean;
|
||||
await act(async () => {
|
||||
handled = result.current.handleInput(TEST_SEQUENCES.CTRL_C);
|
||||
});
|
||||
// Should return false to let InputPrompt handle it
|
||||
expect(handled!).toBe(false);
|
||||
});
|
||||
|
||||
it('should pass Ctrl+C through to InputPrompt in INSERT mode', async () => {
|
||||
mockVimContext.vimMode = 'INSERT';
|
||||
const { result } = renderHook(() =>
|
||||
useVim(mockBuffer as TextBuffer, mockHandleFinalSubmit),
|
||||
);
|
||||
|
||||
let handled: boolean;
|
||||
await act(async () => {
|
||||
handled = result.current.handleInput(TEST_SEQUENCES.CTRL_C);
|
||||
});
|
||||
// Should return false to let InputPrompt handle it
|
||||
expect(handled!).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user