mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-12 12:54:07 -07:00
Stop printing garbage characters for F1,F2.. keys (#12835)
This commit is contained in:
committed by
GitHub
parent
2136598e87
commit
3c9052a751
@@ -1450,6 +1450,7 @@ describe('AppContainer State Management', () => {
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: false,
|
||||||
sequence: '\x13',
|
sequence: '\x13',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -1476,6 +1477,7 @@ describe('AppContainer State Management', () => {
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: false,
|
||||||
sequence: '\x13',
|
sequence: '\x13',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -1490,6 +1492,7 @@ describe('AppContainer State Management', () => {
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: true,
|
||||||
sequence: 'a',
|
sequence: 'a',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -1510,6 +1513,7 @@ describe('AppContainer State Management', () => {
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: false,
|
||||||
sequence: '\x13',
|
sequence: '\x13',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -1525,6 +1529,7 @@ describe('AppContainer State Management', () => {
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: true,
|
||||||
sequence: 'a',
|
sequence: 'a',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -188,6 +188,7 @@ describe('<ModelDialog />', () => {
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: false,
|
||||||
sequence: '',
|
sequence: '',
|
||||||
});
|
});
|
||||||
expect(props.onClose).toHaveBeenCalledTimes(1);
|
expect(props.onClose).toHaveBeenCalledTimes(1);
|
||||||
@@ -198,6 +199,7 @@ describe('<ModelDialog />', () => {
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: true,
|
||||||
sequence: '',
|
sequence: '',
|
||||||
});
|
});
|
||||||
expect(props.onClose).toHaveBeenCalledTimes(1);
|
expect(props.onClose).toHaveBeenCalledTimes(1);
|
||||||
|
|||||||
@@ -977,6 +977,7 @@ describe('useTextBuffer', () => {
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: true,
|
||||||
sequence: 'h',
|
sequence: 'h',
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@@ -987,6 +988,7 @@ describe('useTextBuffer', () => {
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: true,
|
||||||
sequence: 'i',
|
sequence: 'i',
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@@ -1004,6 +1006,7 @@ describe('useTextBuffer', () => {
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: true,
|
||||||
sequence: '\r',
|
sequence: '\r',
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@@ -1021,6 +1024,7 @@ describe('useTextBuffer', () => {
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: false,
|
||||||
sequence: '\t',
|
sequence: '\t',
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@@ -1038,6 +1042,7 @@ describe('useTextBuffer', () => {
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: true,
|
shift: true,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: false,
|
||||||
sequence: '\u001b[9;2u',
|
sequence: '\u001b[9;2u',
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@@ -1060,6 +1065,7 @@ describe('useTextBuffer', () => {
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: false,
|
||||||
sequence: '\x7f',
|
sequence: '\x7f',
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@@ -1084,6 +1090,7 @@ describe('useTextBuffer', () => {
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: false,
|
||||||
sequence: '\x7f',
|
sequence: '\x7f',
|
||||||
});
|
});
|
||||||
result.current.handleInput({
|
result.current.handleInput({
|
||||||
@@ -1092,6 +1099,7 @@ describe('useTextBuffer', () => {
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: false,
|
||||||
sequence: '\x7f',
|
sequence: '\x7f',
|
||||||
});
|
});
|
||||||
result.current.handleInput({
|
result.current.handleInput({
|
||||||
@@ -1100,6 +1108,7 @@ describe('useTextBuffer', () => {
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: false,
|
||||||
sequence: '\x7f',
|
sequence: '\x7f',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -1159,6 +1168,7 @@ describe('useTextBuffer', () => {
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: false,
|
||||||
sequence: '\x1b[D',
|
sequence: '\x1b[D',
|
||||||
}),
|
}),
|
||||||
); // cursor [0,1]
|
); // cursor [0,1]
|
||||||
@@ -1170,6 +1180,7 @@ describe('useTextBuffer', () => {
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: false,
|
||||||
sequence: '\x1b[C',
|
sequence: '\x1b[C',
|
||||||
}),
|
}),
|
||||||
); // cursor [0,2]
|
); // cursor [0,2]
|
||||||
@@ -1189,6 +1200,7 @@ describe('useTextBuffer', () => {
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: true,
|
||||||
sequence: textWithAnsi,
|
sequence: textWithAnsi,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@@ -1206,6 +1218,7 @@ describe('useTextBuffer', () => {
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: true,
|
shift: true,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: true,
|
||||||
sequence: '\r',
|
sequence: '\r',
|
||||||
}),
|
}),
|
||||||
); // Simulates Shift+Enter in VSCode terminal
|
); // Simulates Shift+Enter in VSCode terminal
|
||||||
@@ -1410,6 +1423,7 @@ Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: true,
|
||||||
sequence,
|
sequence,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1468,6 +1482,7 @@ Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: true,
|
||||||
sequence: largeTextWithUnsafe,
|
sequence: largeTextWithUnsafe,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@@ -1502,6 +1517,7 @@ Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: true,
|
||||||
sequence: largeTextWithAnsi,
|
sequence: largeTextWithAnsi,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@@ -1526,6 +1542,7 @@ Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: true,
|
||||||
sequence: emojis,
|
sequence: emojis,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@@ -1717,12 +1734,35 @@ Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: true,
|
||||||
sequence: '\r',
|
sequence: '\r',
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
expect(getBufferState(result).lines).toEqual(['']);
|
expect(getBufferState(result).lines).toEqual(['']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not print anything for function keys when singleLine is true', () => {
|
||||||
|
const { result } = renderHook(() =>
|
||||||
|
useTextBuffer({
|
||||||
|
viewport,
|
||||||
|
isValidPath: () => false,
|
||||||
|
singleLine: true,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
act(() =>
|
||||||
|
result.current.handleInput({
|
||||||
|
name: 'f1',
|
||||||
|
ctrl: false,
|
||||||
|
meta: false,
|
||||||
|
shift: false,
|
||||||
|
paste: false,
|
||||||
|
insertable: false,
|
||||||
|
sequence: '\u001bOP',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
expect(getBufferState(result).lines).toEqual(['']);
|
||||||
|
});
|
||||||
|
|
||||||
it('should strip newlines from pasted text when singleLine is true', () => {
|
it('should strip newlines from pasted text when singleLine is true', () => {
|
||||||
const { result } = renderHook(() =>
|
const { result } = renderHook(() =>
|
||||||
useTextBuffer({
|
useTextBuffer({
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import {
|
|||||||
stripUnsafeCharacters,
|
stripUnsafeCharacters,
|
||||||
getCachedStringWidth,
|
getCachedStringWidth,
|
||||||
} from '../../utils/textUtils.js';
|
} from '../../utils/textUtils.js';
|
||||||
|
import type { Key } from '../../contexts/KeypressContext.js';
|
||||||
import type { VimAction } from './vim-buffer-actions.js';
|
import type { VimAction } from './vim-buffer-actions.js';
|
||||||
import { handleVimAction } from './vim-buffer-actions.js';
|
import { handleVimAction } from './vim-buffer-actions.js';
|
||||||
|
|
||||||
@@ -1907,14 +1908,7 @@ export function useTextBuffer({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleInput = useCallback(
|
const handleInput = useCallback(
|
||||||
(key: {
|
(key: Key): void => {
|
||||||
name: string;
|
|
||||||
ctrl: boolean;
|
|
||||||
meta: boolean;
|
|
||||||
shift: boolean;
|
|
||||||
paste: boolean;
|
|
||||||
sequence: string;
|
|
||||||
}): void => {
|
|
||||||
const { sequence: input } = key;
|
const { sequence: input } = key;
|
||||||
|
|
||||||
if (key.paste) {
|
if (key.paste) {
|
||||||
@@ -1964,7 +1958,7 @@ export function useTextBuffer({
|
|||||||
else if (key.name === 'delete' || (key.ctrl && key.name === 'd')) del();
|
else if (key.name === 'delete' || (key.ctrl && key.name === 'd')) del();
|
||||||
else if (key.ctrl && !key.shift && key.name === 'z') undo();
|
else if (key.ctrl && !key.shift && key.name === 'z') undo();
|
||||||
else if (key.ctrl && key.shift && key.name === 'z') redo();
|
else if (key.ctrl && key.shift && key.name === 'z') redo();
|
||||||
else if (input && !key.ctrl && !key.meta && key.name !== 'tab') {
|
else if (key.insertable) {
|
||||||
insert(input, { paste: key.paste });
|
insert(input, { paste: key.paste });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -2266,14 +2260,7 @@ export interface TextBuffer {
|
|||||||
/**
|
/**
|
||||||
* High level "handleInput" – receives what Ink gives us.
|
* High level "handleInput" – receives what Ink gives us.
|
||||||
*/
|
*/
|
||||||
handleInput: (key: {
|
handleInput: (key: Key) => void;
|
||||||
name: string;
|
|
||||||
ctrl: boolean;
|
|
||||||
meta: boolean;
|
|
||||||
shift: boolean;
|
|
||||||
paste: boolean;
|
|
||||||
sequence: string;
|
|
||||||
}) => void;
|
|
||||||
/**
|
/**
|
||||||
* Opens the current buffer contents in the user's preferred terminal text
|
* Opens the current buffer contents in the user's preferred terminal text
|
||||||
* editor ($VISUAL or $EDITOR, falling back to "vi"). The method blocks
|
* editor ($VISUAL or $EDITOR, falling back to "vi"). The method blocks
|
||||||
|
|||||||
@@ -224,6 +224,7 @@ function bufferPaste(
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: true,
|
paste: true,
|
||||||
|
insertable: true,
|
||||||
sequence: buffer,
|
sequence: buffer,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -273,6 +274,7 @@ function* emitKeys(
|
|||||||
let meta = false;
|
let meta = false;
|
||||||
let shift = false;
|
let shift = false;
|
||||||
let code = undefined;
|
let code = undefined;
|
||||||
|
let insertable = false;
|
||||||
|
|
||||||
if (ch === ESC) {
|
if (ch === ESC) {
|
||||||
escaped = true;
|
escaped = true;
|
||||||
@@ -455,6 +457,7 @@ function* emitKeys(
|
|||||||
} else if (ch === ' ') {
|
} else if (ch === ' ') {
|
||||||
name = 'space';
|
name = 'space';
|
||||||
meta = escaped;
|
meta = escaped;
|
||||||
|
insertable = true;
|
||||||
} else if (!escaped && ch <= '\x1a') {
|
} else if (!escaped && ch <= '\x1a') {
|
||||||
// ctrl+letter
|
// ctrl+letter
|
||||||
name = String.fromCharCode(ch.charCodeAt(0) + 'a'.charCodeAt(0) - 1);
|
name = String.fromCharCode(ch.charCodeAt(0) + 'a'.charCodeAt(0) - 1);
|
||||||
@@ -464,6 +467,7 @@ function* emitKeys(
|
|||||||
name = ch.toLowerCase();
|
name = ch.toLowerCase();
|
||||||
shift = /^[A-Z]$/.exec(ch) !== null;
|
shift = /^[A-Z]$/.exec(ch) !== null;
|
||||||
meta = escaped;
|
meta = escaped;
|
||||||
|
insertable = true;
|
||||||
} else if (MAC_ALT_KEY_CHARACTER_MAP[ch] && process.platform === 'darwin') {
|
} else if (MAC_ALT_KEY_CHARACTER_MAP[ch] && process.platform === 'darwin') {
|
||||||
name = MAC_ALT_KEY_CHARACTER_MAP[ch];
|
name = MAC_ALT_KEY_CHARACTER_MAP[ch];
|
||||||
meta = true;
|
meta = true;
|
||||||
@@ -479,12 +483,16 @@ function* emitKeys(
|
|||||||
meta,
|
meta,
|
||||||
shift,
|
shift,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: false,
|
||||||
sequence: ESC,
|
sequence: ESC,
|
||||||
});
|
});
|
||||||
} else if (escaped) {
|
} else if (escaped) {
|
||||||
// Escape sequence timeout
|
// Escape sequence timeout
|
||||||
name = ch.length ? undefined : 'escape';
|
name = ch.length ? undefined : 'escape';
|
||||||
meta = true;
|
meta = true;
|
||||||
|
} else {
|
||||||
|
// Any other character is considered printable.
|
||||||
|
insertable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -497,6 +505,7 @@ function* emitKeys(
|
|||||||
meta,
|
meta,
|
||||||
shift,
|
shift,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable,
|
||||||
sequence,
|
sequence,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -510,6 +519,7 @@ export interface Key {
|
|||||||
meta: boolean;
|
meta: boolean;
|
||||||
shift: boolean;
|
shift: boolean;
|
||||||
paste: boolean;
|
paste: boolean;
|
||||||
|
insertable: boolean;
|
||||||
sequence: string;
|
sequence: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ class MockStdin extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
describe(`useKeypress with useKitty=%s`, () => {
|
describe(`useKeypress`, () => {
|
||||||
let stdin: MockStdin;
|
let stdin: MockStdin;
|
||||||
const mockSetRawMode = vi.fn();
|
const mockSetRawMode = vi.fn();
|
||||||
const onKeypress = vi.fn();
|
const onKeypress = vi.fn();
|
||||||
@@ -144,6 +144,7 @@ describe(`useKeypress with useKitty=%s`, () => {
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: true,
|
paste: true,
|
||||||
|
insertable: true,
|
||||||
sequence: pasteText,
|
sequence: pasteText,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -281,6 +282,7 @@ describe(`useKeypress with useKitty=%s`, () => {
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: true,
|
paste: true,
|
||||||
|
insertable: true,
|
||||||
sequence: pasteText,
|
sequence: pasteText,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ describe('useSelectionList', () => {
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: options.shift ?? false,
|
shift: options.shift ?? false,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: false,
|
||||||
};
|
};
|
||||||
activeKeypressHandler(key);
|
activeKeypressHandler(key);
|
||||||
} else {
|
} else {
|
||||||
@@ -331,6 +332,7 @@ describe('useSelectionList', () => {
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: true,
|
||||||
};
|
};
|
||||||
handler(key);
|
handler(key);
|
||||||
};
|
};
|
||||||
@@ -380,6 +382,7 @@ describe('useSelectionList', () => {
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: false,
|
||||||
};
|
};
|
||||||
handler(key);
|
handler(key);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ const createKey = (partial: Partial<Key>): Key => ({
|
|||||||
meta: partial.meta || false,
|
meta: partial.meta || false,
|
||||||
shift: partial.shift || false,
|
shift: partial.shift || false,
|
||||||
paste: partial.paste || false,
|
paste: partial.paste || false,
|
||||||
|
insertable: partial.insertable || false,
|
||||||
...partial,
|
...partial,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -313,6 +313,7 @@ export function useVim(buffer: TextBuffer, onSubmit?: (value: string) => void) {
|
|||||||
meta: key.meta || false,
|
meta: key.meta || false,
|
||||||
shift: key.shift || false,
|
shift: key.shift || false,
|
||||||
paste: key.paste || false,
|
paste: key.paste || false,
|
||||||
|
insertable: key.insertable || false,
|
||||||
}),
|
}),
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ describe('keyMatchers', () => {
|
|||||||
meta: false,
|
meta: false,
|
||||||
shift: false,
|
shift: false,
|
||||||
paste: false,
|
paste: false,
|
||||||
|
insertable: false,
|
||||||
sequence: name,
|
sequence: name,
|
||||||
...mods,
|
...mods,
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user