(input: string, key: Key)
| 430 | } |
| 431 | |
| 432 | function onInput(input: string, key: Key): void { |
| 433 | // Note: Image paste shortcut (chat:imagePaste) is handled via useKeybindings in PromptInput |
| 434 | |
| 435 | // Apply filter if provided |
| 436 | const filteredInput = inputFilter ? inputFilter(input, key) : input |
| 437 | |
| 438 | // If the input was filtered out, do nothing |
| 439 | if (filteredInput === '' && input !== '') { |
| 440 | return |
| 441 | } |
| 442 | |
| 443 | // Fix Issue #1853: Filter DEL characters that interfere with backspace in SSH/tmux |
| 444 | // In SSH/tmux environments, backspace generates both key events and raw DEL chars |
| 445 | if (!key.backspace && !key.delete && input.includes('\x7f')) { |
| 446 | const delCount = (input.match(/\x7f/g) || []).length |
| 447 | |
| 448 | // Apply all DEL characters as backspace operations synchronously |
| 449 | // Try to delete tokens first, fall back to character backspace |
| 450 | let currentCursor = cursor |
| 451 | for (let i = 0; i < delCount; i++) { |
| 452 | currentCursor = |
| 453 | currentCursor.deleteTokenBefore() ?? currentCursor.backspace() |
| 454 | } |
| 455 | |
| 456 | // Update state once with the final result |
| 457 | if (!cursor.equals(currentCursor)) { |
| 458 | if (cursor.text !== currentCursor.text) { |
| 459 | onChange(currentCursor.text) |
| 460 | } |
| 461 | setOffset(currentCursor.offset) |
| 462 | } |
| 463 | resetKillAccumulation() |
| 464 | resetYankState() |
| 465 | return |
| 466 | } |
| 467 | |
| 468 | // Reset kill accumulation for non-kill keys |
| 469 | if (!isKillKey(key, filteredInput)) { |
| 470 | resetKillAccumulation() |
| 471 | } |
| 472 | |
| 473 | // Reset yank state for non-yank keys (breaks yank-pop chain) |
| 474 | if (!isYankKey(key, filteredInput)) { |
| 475 | resetYankState() |
| 476 | } |
| 477 | |
| 478 | const nextCursor = mapKey(key)(filteredInput) |
| 479 | if (nextCursor) { |
| 480 | if (!cursor.equals(nextCursor)) { |
| 481 | if (cursor.text !== nextCursor.text) { |
| 482 | onChange(nextCursor.text) |
| 483 | } |
| 484 | setOffset(nextCursor.offset) |
| 485 | } |
| 486 | // SSH-coalesced Enter: on slow links, "o" + Enter can arrive as one |
| 487 | // chunk "o\r". parseKeypress only matches s === '\r', so it hit the |
| 488 | // default handler above (which stripped the trailing \r). Text with |
| 489 | // exactly one trailing \r is coalesced Enter; lone \r is Alt+Enter |
no test coverage detected