This commit is contained in:
A.K.M. Adib
2026-01-20 16:08:18 -05:00
parent 13facb6d05
commit 4bfd4781b5
6 changed files with 49 additions and 42 deletions
+1 -1
View File
@@ -143,7 +143,7 @@ export const defaultKeyBindings: KeyBindingConfig = {
// Editing
[Command.KILL_LINE_RIGHT]: [{ key: 'k', ctrl: true }],
[Command.KILL_LINE_LEFT]: [{ key: 'u', ctrl: true }],
[Command.CLEAR_INPUT]: [{ key: 'c', ctrl: true }],
[Command.CLEAR_INPUT]: [{ key: 'escape' }],
// Added command (meta/alt/option) for mac compatibility
[Command.DELETE_WORD_BACKWARD]: [
{ key: 'backspace', ctrl: true },
@@ -1253,25 +1253,6 @@ describe('InputPrompt', () => {
unmount();
});
it('should clear the buffer on Ctrl+C if it has text', async () => {
await act(async () => {
props.buffer.setText('some text to clear');
});
const { stdin, unmount } = renderWithProviders(<InputPrompt {...props} />, {
uiActions,
});
await act(async () => {
stdin.write('\x03'); // Ctrl+C character
});
await waitFor(() => {
expect(props.buffer.setText).toHaveBeenCalledWith('');
expect(mockCommandCompletion.resetCompletionState).toHaveBeenCalled();
});
expect(props.onSubmit).not.toHaveBeenCalled();
unmount();
});
it('should NOT clear the buffer on Ctrl+C if it is empty', async () => {
props.buffer.text = '';
const { stdin, unmount } = renderWithProviders(<InputPrompt {...props} />, {
@@ -1874,7 +1855,7 @@ describe('InputPrompt', () => {
beforeEach(() => vi.useFakeTimers());
afterEach(() => vi.useRealTimers());
it('should clear buffer on Ctrl-C', async () => {
it('should NOT clear buffer on Ctrl-C', async () => {
const onEscapePromptChange = vi.fn();
props.onEscapePromptChange = onEscapePromptChange;
props.buffer.setText('text to clear');
@@ -1887,16 +1868,16 @@ describe('InputPrompt', () => {
stdin.write('\x03');
vi.advanceTimersByTime(100);
expect(props.buffer.setText).toHaveBeenCalledWith('');
expect(mockCommandCompletion.resetCompletionState).toHaveBeenCalled();
expect(props.buffer.setText).not.toHaveBeenCalledWith('');
});
unmount();
});
it('should submit /rewind on double ESC', async () => {
it('should submit /rewind on double ESC when buffer is empty', async () => {
const onEscapePromptChange = vi.fn();
props.onEscapePromptChange = onEscapePromptChange;
props.buffer.setText('some text');
props.buffer.setText('');
vi.mocked(props.buffer.setText).mockClear();
const { stdin, unmount } = renderWithProviders(
<InputPrompt {...props} />,
@@ -1911,6 +1892,26 @@ describe('InputPrompt', () => {
unmount();
});
it('should clear the buffer on esc esc if it has text', async () => {
const onEscapePromptChange = vi.fn();
props.onEscapePromptChange = onEscapePromptChange;
props.buffer.setText('some text');
vi.mocked(props.buffer.setText).mockClear();
const { stdin, unmount } = renderWithProviders(
<InputPrompt {...props} />,
);
await act(async () => {
stdin.write('\x1B\x1B');
vi.advanceTimersByTime(100);
expect(props.buffer.setText).toHaveBeenCalledWith('');
expect(props.onSubmit).not.toHaveBeenCalledWith('/rewind');
});
unmount();
});
it('should reset escape state on any non-ESC key', async () => {
const onEscapePromptChange = vi.fn();
props.onEscapePromptChange = onEscapePromptChange;
+8 -12
View File
@@ -495,7 +495,7 @@ export const InputPrompt: React.FC<InputPromptProps> = ({
return;
}
// Handle double ESC for rewind
// Handle double ESC
if (escPressCount.current === 0) {
escPressCount.current = 1;
setShowEscapePrompt(true);
@@ -506,9 +506,14 @@ export const InputPrompt: React.FC<InputPromptProps> = ({
resetEscapeState();
}, 500);
} else {
// Second ESC triggers rewind
// Second ESC
resetEscapeState();
onSubmit('/rewind');
if (keyMatchers[Command.CLEAR_INPUT](key) && buffer.text.length > 0) {
buffer.setText('');
resetCompletionState();
} else {
onSubmit('/rewind');
}
}
return;
}
@@ -790,15 +795,6 @@ export const InputPrompt: React.FC<InputPromptProps> = ({
buffer.move('end');
return;
}
// Ctrl+C (Clear input)
if (keyMatchers[Command.CLEAR_INPUT](key)) {
if (buffer.text.length > 0) {
buffer.setText('');
resetCompletionState();
}
return;
}
// Kill line commands
if (keyMatchers[Command.KILL_LINE_RIGHT](key)) {
buffer.killLineRight();
@@ -45,7 +45,12 @@ export const StatusDisplay: React.FC<StatusDisplayProps> = ({
}
if (uiState.showEscapePrompt) {
return <Text color={theme.text.secondary}>Press Esc again to rewind.</Text>;
const isPromptEmpty = uiState.buffer.text.trim().length === 0;
return (
<Text color={theme.text.secondary}>
Press Esc again to {isPromptEmpty ? 'rewind' : 'clear prompt'}.
</Text>
);
}
if (uiState.queueErrorMessage) {
+6 -2
View File
@@ -96,8 +96,12 @@ describe('keyMatchers', () => {
},
{
command: Command.CLEAR_INPUT,
positive: [createKey('c', { ctrl: true })],
negative: [createKey('c'), createKey('k', { ctrl: true })],
positive: [createKey('escape')],
negative: [
createKey('c', { ctrl: true }),
createKey('c'),
createKey('k', { ctrl: true }),
],
},
{
command: Command.DELETE_CHAR_LEFT,