feat(cli):suggestion-navigation-shortcut (#3641)

Co-authored-by: N. Taylor Mullen <ntaylormullen@google.com>
This commit is contained in:
Seydulla Narkulyyev 2025-07-22 01:43:23 +04:00 committed by GitHub
parent b4d00ab4fb
commit f7b4e74932
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 79 additions and 2 deletions

View File

@ -221,6 +221,83 @@ describe('InputPrompt', () => {
unmount();
});
it('should call completion.navigateUp for both up arrow and Ctrl+P when suggestions are showing', async () => {
mockedUseCompletion.mockReturnValue({
...mockCompletion,
showSuggestions: true,
suggestions: [
{ label: 'memory', value: 'memory' },
{ label: 'memcache', value: 'memcache' },
],
});
props.buffer.setText('/mem');
const { stdin, unmount } = render(<InputPrompt {...props} />);
await wait();
// Test up arrow
stdin.write('\u001B[A'); // Up arrow
await wait();
stdin.write('\u0010'); // Ctrl+P
await wait();
expect(mockCompletion.navigateUp).toHaveBeenCalledTimes(2);
expect(mockCompletion.navigateDown).not.toHaveBeenCalled();
unmount();
});
it('should call completion.navigateDown for both down arrow and Ctrl+N when suggestions are showing', async () => {
mockedUseCompletion.mockReturnValue({
...mockCompletion,
showSuggestions: true,
suggestions: [
{ label: 'memory', value: 'memory' },
{ label: 'memcache', value: 'memcache' },
],
});
props.buffer.setText('/mem');
const { stdin, unmount } = render(<InputPrompt {...props} />);
await wait();
// Test down arrow
stdin.write('\u001B[B'); // Down arrow
await wait();
stdin.write('\u000E'); // Ctrl+N
await wait();
expect(mockCompletion.navigateDown).toHaveBeenCalledTimes(2);
expect(mockCompletion.navigateUp).not.toHaveBeenCalled();
unmount();
});
it('should NOT call completion navigation when suggestions are not showing', async () => {
mockedUseCompletion.mockReturnValue({
...mockCompletion,
showSuggestions: false,
});
props.buffer.setText('some text');
const { stdin, unmount } = render(<InputPrompt {...props} />);
await wait();
stdin.write('\u001B[A'); // Up arrow
await wait();
stdin.write('\u001B[B'); // Down arrow
await wait();
stdin.write('\u0010'); // Ctrl+P
await wait();
stdin.write('\u000E'); // Ctrl+N
await wait();
expect(mockCompletion.navigateUp).not.toHaveBeenCalled();
expect(mockCompletion.navigateDown).not.toHaveBeenCalled();
unmount();
});
describe('clipboard image paste', () => {
beforeEach(() => {
vi.mocked(clipboardUtils.clipboardHasImage).mockResolvedValue(false);

View File

@ -320,11 +320,11 @@ export const InputPrompt: React.FC<InputPromptProps> = ({
if (completion.showSuggestions) {
if (completion.suggestions.length > 1) {
if (key.name === 'up') {
if (key.name === 'up' || (key.ctrl && key.name === 'p')) {
completion.navigateUp();
return;
}
if (key.name === 'down') {
if (key.name === 'down' || (key.ctrl && key.name === 'n')) {
completion.navigateDown();
return;
}