Skip to content

Forward Opt+Enter as ESC+CR to alt-screen programs on macOS#9350

Draft
altjx wants to merge 1 commit intowarpdotdev:masterfrom
altjx:fix/opt-enter-tui-newline
Draft

Forward Opt+Enter as ESC+CR to alt-screen programs on macOS#9350
altjx wants to merge 1 commit intowarpdotdev:masterfrom
altjx:fix/opt-enter-tui-newline

Conversation

@altjx
Copy link
Copy Markdown

@altjx altjx commented Apr 29, 2026

Summary

When a TUI like Claude, vim, or fish runs in alt-screen mode, pressing Option+Enter on macOS (without the "Option as Meta" setting enabled) was sending a bare \r to the PTY instead of the xterm-style \x1b\r. The TUI then treated it as a plain Enter and submitted, instead of inserting a newline.

Root cause

When alt-screen is active, focus is on TerminalView (via focus_terminal()ctx.focus_self()), so the editor's alt-enter keybinding never fires. The keystroke reaches alt_screen_element.rs's KeyDown handler and calls KeystrokeWithDetails::to_escape_sequence(). In the legacy fallback chain inside meta_keystroke_to_escape_sequence (crates/warp_terminal/src/model/escape_sequences.rs):

if OperatingSystem::get().is_mac() {
    if !keystroke.meta {
        return None;            // ← exits here for Opt+Enter on Mac
    }
}

For default Mac config, Opt+Enter has keystroke.alt = true, keystroke.meta = false. The function returns None, the rest of the chain returns None too, and the alt_screen_element falls through to key_down(chars) which dispatches the raw \r to the PTY. The Mac meta-only gate is correct for letter keys (Option+E = é, etc., shouldn't become ESC+e) but Enter has no Option-modified glyph, so it's safe — and expected by xterm-style TUIs — to encode Opt+Enter as a meta keystroke.

A secondary bug: when users do have Option-as-Meta enabled (alt → meta upstream), map_special_key_to_bytes had no entry for "enter", so the fallback at the end of meta_keystroke_to_escape_sequence sent literal ESC + the bytes of the string "enter".

Changes

  • crates/warp_terminal/src/model/escape_sequences.rs
    • Allow alt-enter through meta_keystroke_to_escape_sequence on Mac even when meta is unset.
    • Add "enter" => "\r" to map_special_key_to_bytes.
  • crates/warp_terminal/src/model/escape_sequences_test.rs
    • Extend the existing meta keystroke test to cover Enter.
    • Add a Mac-only test asserting alt-enter produces ESC+CR when Option-as-Meta is off.

Test plan

  • cargo test -p warp_terminal escape_sequences passes
  • Built locally (./script/macos/bundle --selfsign --nouniversal) and verified Opt+Enter inserts a newline in Claude inside the alt-screen instead of submitting
  • Verify behavior is unchanged with extra_meta_keys.left_alt = true (Option-as-Meta enabled)
  • Verify behavior is unchanged when Kitty keyboard protocol is enabled (CSI u path takes precedence)
  • Sanity-check that Opt+letter still produces special glyphs (é, ø, etc.) and isn't being intercepted as ESC+letter

Notes

Filed as a draft. Per CONTRIBUTING.md, bug fixes need a triaged issue first — happy to file one and link it back here once a maintainer confirms scope.

@cla-bot
Copy link
Copy Markdown

cla-bot Bot commented Apr 29, 2026

Thank you for your pull request and welcome to our community. We could not parse the GitHub identity of the following contributors: =.
This is most likely caused by a git client misconfiguration; please make sure to:

  1. check if your git client is configured with an email to sign commits git config --list | grep email
  2. If not, set it up using git config --global user.email email@example.com
  3. Make sure that the git commit email is configured in your GitHub account settings, see https://github.com/settings/emails

When a TUI like Claude, vim, or fish runs in alt-screen mode, pressing
Option+Enter on macOS without "Option as Meta" enabled was sending a bare
`\r` to the PTY instead of the xterm-style `\x1b\r`. The legacy escape
sequence path early-returned on Mac whenever `keystroke.meta` was unset,
which is correct for letter keys (Opt+E = é) but wrong for Enter, which
never has an Option-modified glyph. Allow alt-enter through the meta path
and add `"enter" => "\r"` to the special-key map so the existing meta
path also handles users who have Option-as-Meta enabled.
@altjx altjx force-pushed the fix/opt-enter-tui-newline branch from a2b37b0 to 6fe5041 Compare April 29, 2026 01:06
@cla-bot
Copy link
Copy Markdown

cla-bot Bot commented Apr 29, 2026

Thank you for your pull request and welcome to our community. We require contributors to sign our Contributor License Agreement, and we don't seem to have the users @altjx on file. In order for us to review and merge your code, each contributor must visit https://cla.warp.dev to read and agree to our CLA. Once you have done so, please comment @cla-bot check to trigger another check.

@oz-for-oss
Copy link
Copy Markdown

oz-for-oss Bot commented Apr 29, 2026

@altjx

I'm checking this implementation PR for association with a likely matching ready issue.

Powered by Oz

@altjx
Copy link
Copy Markdown
Author

altjx commented Apr 29, 2026

@cla-bot check

@cla-bot
Copy link
Copy Markdown

cla-bot Bot commented Apr 29, 2026

Thank you for your pull request and welcome to our community. We require contributors to sign our Contributor License Agreement, and we don't seem to have the users @altjx on file. In order for us to review and merge your code, each contributor must visit https://cla.warp.dev to read and agree to our CLA. Once you have done so, please comment @cla-bot check to trigger another check.

@cla-bot
Copy link
Copy Markdown

cla-bot Bot commented Apr 29, 2026

The cla-bot has been summoned, and re-checked this pull request!

@altjx
Copy link
Copy Markdown
Author

altjx commented Apr 29, 2026

@cla-bot check

@cla-bot cla-bot Bot added the cla-signed label Apr 29, 2026
@cla-bot
Copy link
Copy Markdown

cla-bot Bot commented Apr 29, 2026

The cla-bot has been summoned, and re-checked this pull request!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant