(key: Key)
| 316 | } |
| 317 | |
| 318 | function mapKey(key: Key): InputMapper { |
| 319 | switch (true) { |
| 320 | case key.escape: |
| 321 | return () => { |
| 322 | // Skip when a keybinding context (e.g. Autocomplete) owns escape. |
| 323 | // useKeybindings can't shield us via stopImmediatePropagation — |
| 324 | // BaseTextInput's useInput registers first (child effects fire |
| 325 | // before parent effects), so this handler has already run by the |
| 326 | // time the keybinding's handler stops propagation. |
| 327 | if (disableEscapeDoublePress) return cursor |
| 328 | handleEscape() |
| 329 | // Return the current cursor unchanged - handleEscape manages state internally |
| 330 | return cursor |
| 331 | } |
| 332 | case key.leftArrow && (key.ctrl || key.meta || key.fn): |
| 333 | return () => cursor.prevWord() |
| 334 | case key.rightArrow && (key.ctrl || key.meta || key.fn): |
| 335 | return () => cursor.nextWord() |
| 336 | case key.backspace: |
| 337 | return key.meta || key.ctrl |
| 338 | ? killWordBefore |
| 339 | : () => cursor.deleteTokenBefore() ?? cursor.backspace() |
| 340 | case key.delete: |
| 341 | return key.meta ? killToLineEnd : () => cursor.del() |
| 342 | case key.ctrl: |
| 343 | return handleCtrl |
| 344 | case key.home: |
| 345 | return () => cursor.startOfLine() |
| 346 | case key.end: |
| 347 | return () => cursor.endOfLine() |
| 348 | case key.pageDown: |
| 349 | // In fullscreen mode, PgUp/PgDn scroll the message viewport instead |
| 350 | // of moving the cursor — no-op here, ScrollKeybindingHandler handles it. |
| 351 | if (isFullscreenEnvEnabled()) { |
| 352 | return NOOP_HANDLER |
| 353 | } |
| 354 | return () => cursor.endOfLine() |
| 355 | case key.pageUp: |
| 356 | if (isFullscreenEnvEnabled()) { |
| 357 | return NOOP_HANDLER |
| 358 | } |
| 359 | return () => cursor.startOfLine() |
| 360 | case key.wheelUp: |
| 361 | case key.wheelDown: |
| 362 | // Mouse wheel events only exist when fullscreen mouse tracking is on. |
| 363 | // ScrollKeybindingHandler handles them; no-op here to avoid inserting |
| 364 | // the raw SGR sequence as text. |
| 365 | return NOOP_HANDLER |
| 366 | case key.return: |
| 367 | // Must come before key.meta so Option+Return inserts newline |
| 368 | return () => handleEnter(key) |
| 369 | case key.meta: |
| 370 | return handleMeta |
| 371 | case key.tab: |
| 372 | return () => cursor |
| 373 | case key.upArrow && !key.shift: |
| 374 | return upOrHistoryUp |
| 375 | case key.downArrow && !key.shift: |
no test coverage detected