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
+50 -17
View File
@@ -62,6 +62,19 @@ struct TerminalSession {
hook: Arc<Mutex<HookState>>,
}
struct ColorSchemeNotifications(bool);
impl crossterm::Command for ColorSchemeNotifications {
fn write_ansi(&self, f: &mut impl std::fmt::Write) -> std::fmt::Result {
f.write_str(if self.0 { "\x1b[?2031h" } else { "\x1b[?2031l" })
}
#[cfg(windows)]
fn execute_winapi(&self) -> io::Result<()> {
Ok(())
}
}
fn restore_terminal() {
let _ = disable_raw_mode();
let _ = execute!(
@@ -70,6 +83,7 @@ fn restore_terminal() {
DisableBracketedPaste,
DisableMouseCapture,
DisableFocusChange,
ColorSchemeNotifications(false),
LeaveAlternateScreen,
Show
);
@@ -109,7 +123,8 @@ impl TerminalSession {
EnterAlternateScreen,
EnableBracketedPaste,
EnableMouseCapture,
EnableFocusChange
EnableFocusChange,
ColorSchemeNotifications(true)
)?;
body()
}));
@@ -787,7 +802,7 @@ pub fn run(session: &mut EditorSession) -> io::Result<()> {
pending = following;
}
Event::Resize(_, _) => redraw = true,
Event::FocusGained => query_theme = true,
Event::FocusGained | Event::ColorSchemeChanged => query_theme = true,
_ => {}
}
}
@@ -2982,8 +2997,8 @@ impl DiffColors {
Color::Rgb(channels[0], channels[1], channels[2])
};
Self {
row: [blend(theme.red, 12), blend(theme.green, 12)],
character: [blend(theme.red, 28), blend(theme.green, 28)],
row: [blend(theme.red, 18), blend(theme.green, 18)],
character: [blend(theme.red, 38), blend(theme.green, 38)],
}
}
}
@@ -4247,19 +4262,7 @@ mod tests {
#[test]
fn character_diff_backgrounds_preserve_common_unicode_and_syntax_across_viewports() {
for (theme, row, character) in [
(
Some(LIGHT_DIFF_THEME),
[Color::Rgb(245, 219, 217), Color::Rgb(222, 234, 218)],
[Color::Rgb(239, 185, 187), Color::Rgb(186, 218, 190)],
),
(
Some(DARK_DIFF_THEME),
[Color::Rgb(44, 29, 36), Color::Rgb(22, 44, 38)],
[Color::Rgb(76, 35, 44), Color::Rgb(26, 68, 50)],
),
(None, [Color::Reset; 2], [Color::Reset; 2]),
] {
for theme in [Some(LIGHT_DIFF_THEME), Some(DARK_DIFF_THEME), None] {
let mut diff = diff_comparison(vec![syntax_diff_file(
"changes.rs",
"let 界e\u{301} = old + old;",
@@ -4272,6 +4275,36 @@ mod tests {
..WheelPanels::default()
};
render_diff(&mut terminal, &diff, &mut panels);
let row = panels.diff_colors.row;
let character = panels.diff_colors.character;
if let Some(theme) = theme {
for (index, accent) in [theme.red, theme.green].into_iter().enumerate() {
let Color::Rgb(r, g, b) = row[index] else {
panic!("theme row background must be RGB");
};
let Color::Rgb(cr, cg, cb) = character[index] else {
panic!("theme character background must be RGB");
};
for ((common, changed), (background, accent)) in [r, g, b]
.into_iter()
.zip([cr, cg, cb])
.zip(theme.background.into_iter().zip(accent))
{
assert!(
(background.min(accent)..=background.max(accent)).contains(&common)
);
assert!(
(background.min(accent)..=background.max(accent)).contains(&changed)
);
if background != accent {
assert!(changed.abs_diff(accent) < common.abs_diff(accent));
}
}
}
} else {
assert_eq!(row, [Color::Reset; 2]);
assert_eq!(character, [Color::Reset; 2]);
}
for index in 0..2 {
let pane = panels.diff.as_ref().unwrap().regions[index + 1].0;
let buffer = terminal.backend().buffer();