Render alt-screen apps in the TUI and forward input to the PTY#13626
Render alt-screen apps in the TUI and forward input to the PTY#13626warp-dev-github-integration[bot] wants to merge 2 commits into
Conversation
When a PTY app enters the alternate screen (vim, htop, less, top, …) in the Warp TUI, the pane went blank and swallowed input: the model tracked the alt screen but the TUI never rendered it or routed keys to it. Render the alt-screen grid full-area and forward keystrokes to the PTY: - Add `AltScreenElement`, which paints the alt-screen grid (reusing the block cell renderer) and positions the terminal cursor. - Forward keystrokes as escape sequences (shared terminal encoder) or raw/printable bytes via a new `ForwardToPty` action -> `PtyIntent::WriteAgentInput`; named control keys (escape, enter, tab, backspace) map to their C0 bytes so e.g. Escape leaves insert mode. - While the alt screen is active, move focus off the input editor so keys reach the PTY rather than the input keymap; ctrl-c stays as the exit escape hatch, and input focus is restored on exit. Slice 1 covers rendering + keyboard. Mouse forwarding and resize polish are tracked as follow-ups. Co-Authored-By: Warp <agent@warp.dev>
|
@warp-dev-github-integration[bot] I'm starting a first review of this pull request. You can view the conversation on Warp. I completed the review and no human review was requested for this pull request. Comment Powered by Oz |
There was a problem hiding this comment.
Overview
This PR adds a TUI alt-screen renderer and routes keyboard input to the PTY while full-screen terminal apps are active.
Concerns
- Ctrl+letter key combinations can be mis-forwarded as printable letters in the TUI fallback path. The shared legacy encoder only emits C0 bytes for a small Ctrl+number/space set unless keyboard protocol is active, while the TUI key conversion supplies
charsfor Ctrl+letter presses; the fallback therefore sends letters likeaordinstead of control bytes like0x01or0x04. - This is a user-facing TUI behavior change, but the attached PR description does not include the required TUI visual evidence. Please attach the
tmux capture-panetranscript/snapshot, arender_to_lines/TuiBuffer::to_linessnapshot diff, or a./script/run-tuicapture directly to the PR.
Verdict
Found: 0 critical, 2 important, 0 suggestions
Request changes
Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).
Powered by Oz
| } | ||
| .to_escape_sequence(model.deref()) | ||
| }; | ||
| let bytes = escape_sequence.or_else(|| fallback_key_bytes(&keystroke.key, chars)); |
There was a problem hiding this comment.
fallback_key_bytes receives non-empty chars for Ctrl+letter TUI key events after the legacy encoder returns None, so combinations like Ctrl+A/Ctrl+D get forwarded as printable letters. Handle Ctrl+A–Z as C0 bytes, or suppress printable fallback when Ctrl is held, before falling back to chars.
There was a problem hiding this comment.
Fixed in 3562bb4. Added ctrl_letter_c0, applied before the printable chars fallback, so Ctrl+A..Ctrl+Z forward as C0 bytes (0x01..0x1A) instead of the letter. Ctrl+C still returns early to the TUI exit escape hatch. Covered by a unit test and live-verified: Ctrl+D scrolls vim half a page (ruler 1,1 Top → 17,1 6%).
- Ctrl+A..Ctrl+Z now forward as C0 control bytes (0x01..0x1A) instead of the printable letter the TUI conversion leaves in `chars`, so control shortcuts work in full-screen apps. The shared legacy encoder only emits C0 bytes for a small Ctrl+number/space set without the kitty keyboard protocol; a new `ctrl_letter_c0` covers Ctrl+A..Z. Ctrl+C stays as the TUI exit escape hatch. - Move the inline `#[cfg(test)] mod tests` to a sibling `alt_screen_view_tests.rs` per the repo convention, fixing the "Check for inline Rust test modules" CI check. Co-Authored-By: Warp <agent@warp.dev>
TUI visual evidence (attached per review)Verified with the Before this PR: running a full-screen app (e.g. After: Interaction checks (all read back from
Also covered by |
|
/oz-review |
Description
When a PTY app enters the alternate screen (vim, htop, less, top, …) inside the Warp TUI (
crates/warp_tui), the pane went blank and swallowed input. The terminal model already tracked the alt screen (TerminalModel::is_alt_screen_active, a populatedalt_screen()grid) andwarp_terminalalready had the key/mouse escape-sequence encoders — but the TUI never rendered the alt-screen grid or routed keys to it.This PR makes the TUI render the alt-screen app full-area and forward keyboard input to the PTY, mirroring the GUI's
app/src/terminal/alt_screen/alt_screen_element.rs:AltScreenElement(crates/warp_tui/src/alt_screen_view.rs) paints the alt-screen grid (reusing the block cell renderer viaterminal_block::render_grid_handler) and positions the terminal cursor.TuiTerminalSessionAction::ForwardToPty→PtyIntent::WriteAgentInput: special/control keys use the sharedToEscapeSequenceencoder; printable keys forward their UTF‑8 bytes; named control keys (escape, enter, tab, backspace) map to their C0 bytes so e.g. Escape leaves an editor's insert mode.TuiTerminalSessionView::renderreturns the alt-screen element whileis_alt_screen_active(); redraws ride the existing wakeup stream.Scope: this is slice 1 (render + keyboard). Mouse forwarding and resize polish are intentional follow-ups (noted in code) — this is a meaty, multi-subsystem area, so a TUI owner's eyes are welcome.
Testing
Live-verified with the
tui-verify-changeflow (warp-tui-devunder tmux,CARGO_BUILD_JOBS=1):vimleft the pane blank (matches the report).vimrenders full-area;Gjumps to the bottom (200,1 Bot); insert mode types text; Escape leaves insert mode;:q!quits and the normal TUI is restored (input box + footer).Added
warp_tuiunit tests for the key→bytes fallback (alt_screen_view::tests): printable → UTF‑8 bytes, named control keys → C0 bytes (escape0x1b, enter\r, tab\t, backspace0x7f), and unmapped keys → nothing.cargo nextest run -p warp_tui(alt-screen tests) andcargo clippy -p warp_tui --all-targets -- -D warningspass;cargo fmtclean.Screenshots / Videos
Captured
tmux capture-paneframe of vim rendered inside the TUI (posted in the Slack thread).Agent Mode
Conversation: https://staging.warp.dev/conversation/9e5f8b04-805e-4fc7-a44c-9006ea7eaa73
Run: https://oz.staging.warp.dev/runs/019f58b4-1630-7a22-ac5e-1197961b8dfd
This PR was generated with Oz.