fix: handle Enter key on Linux terminals that emit \n instead of \r (#818)

Co-authored-by: Letta <noreply@letta.com>
This commit is contained in:
Charles Packer
2026-02-04 12:12:29 -08:00
committed by GitHub
parent 8aed720e10
commit 7081876088

View File

@@ -60,18 +60,32 @@ const useInput = (inputHandler, options = {}) => {
// or with event type: ESC [ keycode ; modifier : event u // or with event type: ESC [ keycode ; modifier : event u
// parseKeypress doesn't handle this, so we parse it ourselves as a fallback // parseKeypress doesn't handle this, so we parse it ourselves as a fallback
if (!keypress.name && typeof data === 'string') { if (!keypress.name && typeof data === 'string') {
let keycode = null;
let modifier = 0;
let event = 1;
// Match CSI u: ESC [ keycode ; modifier u OR ESC [ keycode ; modifier : event u // Match CSI u: ESC [ keycode ; modifier u OR ESC [ keycode ; modifier : event u
const csiUMatch = data.match(/^\x1b\[(\d+)(?:;(\d+))?(?::(\d+))?u$/); const csiUMatch = data.match(/^\x1b\[(\d+)(?:;(\d+))?(?::(\d+))?u$/);
if (csiUMatch) { if (csiUMatch) {
const keycode = parseInt(csiUMatch[1], 10); keycode = parseInt(csiUMatch[1], 10);
const modifier = parseInt(csiUMatch[2] || '1', 10) - 1; modifier = parseInt(csiUMatch[2] || '1', 10) - 1;
const event = csiUMatch[3] ? parseInt(csiUMatch[3], 10) : 1; event = csiUMatch[3] ? parseInt(csiUMatch[3], 10) : 1;
} else {
// modifyOtherKeys format: CSI 27 ; modifier ; key ~
// Treat it like CSI u (key + 'u')
const modifyOtherKeysMatch = data.match(/^\x1b\[27;(\d+);(\d+)~$/);
if (modifyOtherKeysMatch) {
modifier = parseInt(modifyOtherKeysMatch[1], 10) - 1;
keycode = parseInt(modifyOtherKeysMatch[2], 10);
}
}
if (keycode !== null) {
// Ignore key release events (event=3) // Ignore key release events (event=3)
if (event === 3) { if (event === 3) {
return; return;
} }
// Map keycodes to names // Map keycodes to names
const csiUKeyMap = { const csiUKeyMap = {
9: 'tab', 9: 'tab',
@@ -79,16 +93,16 @@ const useInput = (inputHandler, options = {}) => {
27: 'escape', 27: 'escape',
127: 'backspace', 127: 'backspace',
}; };
let name = csiUKeyMap[keycode] || ''; let name = csiUKeyMap[keycode] || '';
// Handle letter keycodes (a-z: 97-122, A-Z: 65-90) // Handle letter keycodes (a-z: 97-122, A-Z: 65-90)
if (!name && keycode >= 97 && keycode <= 122) { if (!name && keycode >= 97 && keycode <= 122) {
name = String.fromCharCode(keycode); // lowercase letter name = String.fromCharCode(keycode); // lowercase letter
} else if (!name && keycode >= 65 && keycode <= 90) { } else if (!name && keycode >= 65 && keycode <= 90) {
name = String.fromCharCode(keycode + 32); // convert to lowercase name = String.fromCharCode(keycode + 32); // convert to lowercase
} }
if (name) { if (name) {
keypress = { keypress = {
name, name,
@@ -110,7 +124,7 @@ const useInput = (inputHandler, options = {}) => {
rightArrow: keypress.name === 'right', rightArrow: keypress.name === 'right',
pageDown: keypress.name === 'pagedown', pageDown: keypress.name === 'pagedown',
pageUp: keypress.name === 'pageup', pageUp: keypress.name === 'pageup',
return: keypress.name === 'return', return: keypress.name === 'return' || keypress.name === 'enter',
escape: keypress.name === 'escape', escape: keypress.name === 'escape',
ctrl: keypress.ctrl, ctrl: keypress.ctrl,
shift: keypress.shift, shift: keypress.shift,
@@ -160,5 +174,3 @@ const useInput = (inputHandler, options = {}) => {
}; };
export default useInput; export default useInput;