fix: retain alternate screen across executable restart

This commit is contained in:
2026-10-12 23:26:38 +02:00
parent d85998e1cb
commit c35abe0f03
6 changed files with 273 additions and 103 deletions
+4 -2
View File
@@ -24,7 +24,7 @@ One editor crate; the workspace also includes its patched Crossterm dependency.
- `session`: `EditorSession` owns the editor, native LSP, and Ruby hosts together. It loads configuration once, registers eligible plugins before installing shared bindings, tracks document open/change/save/close events, polls native and plugin results, validates versioned diagnostics/navigation/completion, and retires failed plugin ownership. Each tab with a comparison has a cancellable repository worker; inactive tabs keep their workers and receive tagged results without changing visible focus. Closed or superseded comparisons reject stale results. Focused diff text supports native LSP navigation, hover, and diagnostics; read-only buffers still reject asynchronous editing effects, and selectors/file lists are not document-action targets.
- `tui`: translates terminal events to session input, renders read-only active-buffer state, keeps frontend-owned viewports and syntax caches by stable buffer ID or immutable diff snapshot/file identity, and advertises `text`, `styled_text`, and `diagnostics` capabilities. It maps semantic tokens and diagnostics to terminal styling and has no server/protocol logic or paste acceptance policy.
- `ruby`: evaluates configuration and runs isolated plugin hosts. Protocol, deadlines, and process cleanup stay inside this module.
- The executable selects paths and frontend capabilities, opens an editor session, and launches the TUI. On restart, it restores the terminal and drops the entire `EditorSession`, including workers and plugin hosts, before relaunching the same executable with the original CLI arguments. Unix replaces the process with `exec`; other platforms spawn a fresh process and return. Startup rereads configuration and the original startup file, or creates an unnamed buffer; current buffers, tabs, views, and session state are not restored.
- The executable selects paths and frontend capabilities, opens an editor session, and launches the TUI inside a terminal guard covering startup, rendering, session teardown, and executable handoff. On restart, it drops the entire `EditorSession`, including workers and plugin hosts, then briefly disables raw mode and input reporting without leaving the alternate screen before relaunching the same executable with the original CLI arguments. Unix replaces the process with `exec`; other platforms spawn a fresh process and wait for it. Startup rereads configuration and the original startup file, or creates an unnamed buffer; current buffers, tabs, views, and session state are not restored.
## Frontend interface
@@ -59,7 +59,9 @@ Frontends borrow `snippet_selections()` for the active argument's end-exclusive
## Terminal lifecycle and layout
The terminal adapter owns raw mode, alternate-screen state, bracketed paste, mouse capture, focus reporting, DEC 2031 color-scheme notifications, and its panic hook for one session lifetime. Entry failure, normal return, I/O errors, and unwinding panics restore the caller's hook; active-terminal cleanup runs before caller panic diagnostics. Panics retain their original payload and propagate rather than being swallowed. Terminal state and panic hooks are process-global: run one TUI at a time and do not replace its hook while that session is active.
The terminal guard owns raw mode, alternate-screen state, bracketed paste, mouse capture, focus reporting, DEC 2031 color-scheme notifications, and its panic hook across startup, rendering, session teardown, and relaunch. An inherited-screen restart installs cleanup and its panic hook before argument, file, or configuration parsing, resumes raw mode and input reporting without entering the alternate screen again, and clears and repaints inherited contents in its first synchronized frame. A private first-argument marker identifies this handoff without changing the original CLI arguments. Final quit, startup or I/O errors, failed relaunch, and unwinding panics restore normal input modes, the normal screen, cursor visibility, and the caller's hook; active-terminal cleanup runs before caller panic diagnostics. Panics retain their original payload and propagate rather than being swallowed. Terminal state and panic hooks are process-global: run one TUI at a time and do not replace its hook while the guard is active.
`tui::TerminalSession::run(inherited_screen, body)` scopes this ownership; `tui::run(&mut session, inherited_screen)` renders inside that active guard. `TerminalSession::prepare_restart()` resets process-local input state without leaving the alternate screen, and the guard stays armed if relaunch fails.
Redraws stage Ratatui's buffer diff, cursor placement, and DEC synchronized-update commands (mode 2026) in a reusable byte buffer, then write and flush the complete frame to the terminal. Frame computation never suspends terminal presentation; synchronization covers transmitted painting rather than layout/highlighting work. The hardware cursor is hidden before painting even when synchronization is unsupported. Terminal cleanup releases synchronization before leaving the alternate screen or invoking caller panic diagnostics. Backend-writer access is enabled solely for this staging seam.