feat(tui): portable newline keys in the composer#31176
Conversation
🔎 Lint report:
|
|
/copilot review |
Shift+Enter, Alt+Enter and Ctrl+Enter only reach the app when the
terminal forwards them via the kitty keyboard or modifyOtherKeys
protocols. On Windows + WSL2, plain Apple Terminal, and SSH-without-
extended-keys, every Enter variant collapses onto a bare '\r' (or
'\x1b\r' for Alt) and submits the message with no way to insert a
newline. Three small changes give every terminal a working newline
binding without any capability detection:
1. parse-keypress now recognises the legacy single/two-byte Enter
encodings:
'\r' -> return
'\n' -> Ctrl+Enter (Ctrl+J)
'\x1b\r' -> Alt+Enter
'\x1b\n' -> Alt+Ctrl+Enter
Modern CSI-u sequences still parse via the kitty path; this only
fills the legacy gap.
2. The composer's Enter handler picks up `\<Enter>` as an inline
line continuation: when the char left of the cursor is a literal
backslash, the '\\' is consumed and replaced with '\n'. Mirrors
Claude Code's PromptInput behaviour — discoverable, universal,
in-place (vs. the existing submit-time buffered fallback).
Extracted as a pure `resolveReturn(value, cursor, modifier)`
helper so the contract is unit-tested.
3. Hotkeys help documents the trio: Shift+Enter / Alt+Enter / Ctrl+J
plus `\\+Enter` inline.
Prior art: Claude Code (`\\+Enter` inline backspace), OpenAI Codex
(Ctrl+J / Ctrl+M / Enter / Shift+Enter / Alt+Enter as alternates),
Aider (`/multiline` modal toggle). This PR takes the union of the
discoverable variants without the modal mode.
f3784a1 to
696a714
Compare
|
@copilot review please |
There was a problem hiding this comment.
Pull request overview
This PR improves multiline composition in the TUI composer across terminals that don’t forward extended modified-Enter key sequences, by adding portable “newline insert” keypaths and documenting them.
Changes:
- Extend
parse-keypressto recognize legacy Enter/LF/ESC+Enter encodings and map them ontoreturnwith appropriatectrl/metamodifiers. - Add a pure
resolveReturn(value, cursor, modifier)helper to implement universal newline insertion, including inline\+ Enter continuation (consumes the backslash and inserts\n). - Add unit tests for both the new return-family decoding and the
resolveReturncontract, and update hotkeys help text.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| ui-tui/src/content/hotkeys.ts | Updates hotkeys help to document Ctrl+J and inline \+Enter behavior. |
| ui-tui/src/components/textInput.tsx | Introduces resolveReturn and routes Enter handling through it for portable newline insertion. |
| ui-tui/src/tests/textInputReturn.test.ts | Adds unit tests covering resolveReturn submit/newline/continuation behaviors. |
| ui-tui/packages/hermes-ink/src/ink/parse-keypress.ts | Adds legacy Enter-family decoding for \r, \n, ESC+\r, ESC+\n with modifier flags. |
| ui-tui/packages/hermes-ink/src/ink/parse-keypress.test.ts | Adds tests verifying the new return-family modifier decoding. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Summary
Shift+Enter, Alt+Enter and Ctrl+Enter only reach the app when the terminal forwards them via the kitty keyboard or modifyOtherKeys protocols. On Windows + WSL2, plain Apple Terminal, and SSH-without-extended-keys, every Enter variant collapses onto a bare `\r` (or `\x1b\r` for Alt) and submits the message with no way to insert a newline.
This PR gives every terminal a working newline binding without any capability detection.
Changes
parse-keypress — recognise the legacy single/two-byte Enter encodings:
Modern CSI-u sequences still parse via the existing kitty / modifyOtherKeys path; this only fills the legacy gap.
Inline `\+Enter` — when the char left of the cursor is a literal backslash, the `\` is consumed and replaced with `\n` in-place. Mirrors Claude Code's `PromptInput` behaviour: discoverable, universal, in-editor (vs. the existing submit-time buffered fallback in `useSubmission.ts`, which is kept as a paste safety net).
Extracted as a pure `resolveReturn(value, cursor, modifier)` helper so the contract is unit-tested independently of React.
Hotkeys help documents the trio: `Shift+Enter / Alt+Enter / Ctrl+J` plus `\+Enter` inline.
Prior art
This PR takes the union of the discoverable variants without the modal mode.
Test plan