fix: refresh diff colors on terminal theme changes

This commit is contained in:
2026-10-11 21:21:17 +02:00
parent d6f6203fb6
commit ffdd42fcce
55 changed files with 11999 additions and 24 deletions
+5 -3
View File
@@ -6,7 +6,7 @@ Contributor-facing module boundaries and implementation contracts. Project termi
## Module ownership
One crate; no workspace or terminal-coordinate types in the editing backend:
One editor crate; the workspace also includes its patched Crossterm dependency. Terminal-coordinate types remain outside the editing backend:
- `editor`: owns buffer lifecycle and per-buffer text, saved state, primary/selection set, modes, search, and undo/redo; session-wide clipboard policy, independent registers and owned-system fragment metadata, semantic native repeat, action metadata, command-palette and file-picker focus/dispatch, key notation, key-sequence/count prefixes and binding resolution, modal paste policy, saving, command ownership, capabilities, and validated edit effects. Its low-level interface returns an `Invocation` when an external command is selected.
- `files`: owns the gitignore-aware directory/file catalog, authoritative OS paths, compact tree projection, query filtering, browse/search focus, expansion/selection restoration, navigation, and scan/error state shared by floating and docked presentations.
@@ -46,11 +46,13 @@ 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, 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 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.
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.
`terminal_colors` intercepts crossterm's key-shaped OSC 11/4 replies before editor dispatch, assembles a bounded RGB background/red/green triple, and preserves unrelated events and opaque bracketed paste. Queries never block input and start after painting, so syntax initialization does not spend their reply deadline. Startup and focus-regain queries replace cached diff tints atomically; an unanswered/partial query expires after 250 ms and removes stale tints rather than assuming a dark theme. Valid late replies are consumed without becoming editing commands. The frontend precomputes rounded RGB blends from the original background (12% row, 28% character), propagating them to active, parked, and newly created panes.
`terminal_colors` intercepts crossterm's key-shaped OSC 11/4 replies before editor dispatch, assembles a bounded RGB background/red/green triple, and preserves unrelated events and opaque bracketed paste. Queries never block input and start after painting, so syntax initialization does not spend their reply deadline. Startup, color-scheme notifications, and fallback focus-regain queries replace cached diff tints atomically; an unanswered/partial query expires after 250 ms and removes stale tints rather than assuming a dark theme. Valid late replies are consumed without becoming editing commands. The frontend precomputes rounded RGB blends from the original background (18% row, 38% character), propagating them to active, parked, and newly created panes.
`vendor/crossterm` retains Crossterm 0.29.0's upstream source and MIT license, with a small Unix decoder patch exposing `Event::ColorSchemeChanged` for `CSI ? 997 ; 1/2 n`. The report signals a palette refresh, not a choice of hard-coded light/dark colors. Valid fragmented reports and malformed color reports leave following keys intact. Cargo patches both direct and Ratatui dependency paths to this one copy; remove the patch/workspace member once upstream supports these notifications.
The TUI uses Ratatui constraint-based layout for a flexible buffer viewport, a one-row status bar, and a one-row prompt/message area. Scrolling, clipping, highlights, and cursor placement use the allocated regions, not terminal-wide offsets. Below three rows the status bar is hidden; at one row the buffer remains visible unless an active command/search prompt takes priority. Zero-sized terminals render nothing. Layout and terminal-cell text mapping remain frontend-owned.
+5 -1
View File
@@ -8,14 +8,18 @@ Local verification and implementation constraints. See [architecture](architectu
```sh
cargo test
cargo test -p crossterm color_scheme_notifications
cargo test -p crossterm --doc
cargo clippy --all-targets -- -D warnings
cargo fmt --check
cargo fmt --package vamp --check
for file in src/ruby_*.rb examples/config.rb examples/plugins/greeting.rb; do
ruby -c "$file" || exit
done
rubocop
```
The default workspace member is the editor. `vendor/crossterm` is included to test its minimal DEC 2031 notification decoder patch; the rest of its source retains upstream formatting. The decoder checks cover fragmented reports and keyboard recovery, and its doctests verify the added event does not break upstream examples.
## Ruby types
Use YARD `@param`, `@return`, and `@yieldparam` annotations for Ruby APIs, and `@type` for locals where inference needs help. Examples annotate DSL block parameters before the call, without adding runtime assignments or dependencies. `Vamp::Action` / `Vamp::Mode` field types and the dynamically defined mode methods use Solargraph-supported directives.
+1 -1
View File
@@ -300,7 +300,7 @@ In split diffs, changed text rows use muted red backgrounds in Before and muted
Character-wise highlighting is enabled automatically within paired changed lines: only changed graphemes receive a stronger red/green background, while common text retains the muted row tint. Combining sequences, wide characters, and expanded tabs keep their source geometry through horizontal scrolling and word wrap. Syntax/semantic foregrounds remain intact, and cursor/search/selection styles keep their normal precedence. Character ranges are cached with aligned rows; stable live edits refresh only the edited paired lines rather than computing character diffs during painting.
Diff backgrounds blend the terminal's default background with its red/green palette colors: a subtle 12% accent for changed rows and a stronger 28% accent for changed characters, both computed from the original background. Read-only OSC 11/4 queries run after the initial paint and again on terminal focus regain; cached colors apply across editor panes. If you switch terminal themes while vamp remains focused, switch away and back to refresh the tints. If the complete palette is unavailable within 250 ms, change backgrounds remain normal and gutter colors/markers still identify changes.
Diff backgrounds blend the terminal's default background with its red/green palette colors: an 18% accent for changed rows and a stronger 38% accent for changed characters, both computed from the original background. Read-only OSC 11/4 queries run after the initial paint and whenever a subscribed DEC 2031 color-scheme notification arrives, so supported terminals update tints while the editor stays focused, including changes between two themes with the same light/dark preference. Focus-regain queries remain the fallback for terminals without notifications; cached colors apply across editor panes. If the complete palette is unavailable within 250 ms, change backgrounds remain normal and gutter colors/markers still identify changes.
Missing counterparts use adjacent muted `╱` diagonals (U+2571, box drawings light diagonal) on the normal terminal background, one per column. Unlike the text slash `/`, this glyph is designed to reach cell corners so diagonals can join end to end across successive rows. Pixel-perfect joins depend on the terminal's font and line-spacing rendering. Actual empty source lines retain their normal/change background and are not hatched.