Merge pull request #125 from Aschenbath/fix/selection-palette-regressions

fix(terminal): honor explicit selection foreground colors
This commit is contained in:
Kuddev authored and GitHub committed 2026-09-13 20:48:48 +08:00
commit 643d92712c
3 files changed
+95 -3

No files matched your search

+24
View File
@@ -105,6 +105,30 @@ Files successfully loaded through `require` are added to the live-reload watch
list. Extra local files can be registered with
`pebrel.add_to_config_reload_watch_list(path)`.
## Terminal Selection Colors (TOML Compatibility)
For a legacy `pebrel.toml` configuration, the GPUI terminal accepts explicit
selection foreground and background colors in `#rrggbb` or `0xrrggbb` form:
```toml
[colors.selection]
foreground = "#102030"
background = "#e5e9f0"
```
Previously the GPUI adapter loaded the selection background but ignored the
foreground, which could leave selected text unreadable against a custom
background. It also cleared a custom foreground when applying a theme such as
Paper that does not declare selection colors. Both values now survive loading
and themes that do not override them. A theme that explicitly declares selection
colors, such as Nord, retains its existing precedence.
Missing or invalid foreground colors keep the existing fallback. Relative
`CellForeground` / `CellBackground` values are not added by this change. The
regression tests cover parsing and theme precedence; this does not change the
answer reader's selection overlay, formula selection layout, or the default
selection contrast. No new setting, dependency, or per-frame work is introduced.
## Platform Values
The module exposes stable runtime paths and platform data:
+70 -2
View File
@@ -270,7 +270,9 @@ fn apply_theme(palette: &mut Palette, theme: nebula_settings::ThemeName) {
if let Some(selection) = exact.selection_background {
palette.selection = rgba8(selection);
}
palette.selection_foreground = exact.selection_foreground.map(rgba8);
if let Some(selection_foreground) = exact.selection_foreground {
palette.selection_foreground = Some(rgba8(selection_foreground));
}
return;
}
if term.is_light {
@@ -552,6 +554,7 @@ fn build_palette(raw: &RawColors) -> Palette {
// 用户显式选区色保持主应用的不透明语义。
palette.selection = selection;
}
palette.selection_foreground = raw.selection.foreground.as_deref().and_then(parse_rgb);
let ansi8 = |group: &RawAnsi8| -> [Option<gpui::Rgba>; 8] {
[
@@ -604,7 +607,10 @@ fn build_palette(raw: &RawColors) -> Palette {
#[cfg(test)]
mod tests {
use super::{Settings, apply_theme, resolve_ui_language, rgba8, runtime_background};
use super::{
RawColors, Settings, apply_theme, build_palette, resolve_ui_language, rgba8,
runtime_background,
};
use crate::display::UiLanguage;
use crate::gpui_shell::terminal::colors::Palette;
use nebula_settings::{LanguagePref, ThemeName};
@@ -652,6 +658,68 @@ mod tests {
assert_eq!(palette.selection_foreground, None);
}
#[test]
fn explicit_selection_colors_are_loaded_together() {
let raw: RawColors = toml::from_str(
r##"
[selection]
foreground = "#102030"
background = "0xe5e9f0"
"##,
)
.unwrap();
let palette = build_palette(&raw);
assert_eq!(palette.selection_foreground, Some(rgba8([0x10, 0x20, 0x30])));
assert_eq!(palette.selection, rgba8([0xe5, 0xe9, 0xf0]));
}
#[test]
fn invalid_or_relative_selection_foreground_keeps_default() {
for foreground in ["#invalid", "#fff", "CellForeground", "CellBackground"] {
let raw: RawColors = toml::from_str(&format!(
"[selection]\nforeground = {foreground:?}\nbackground = \"#e5e9f0\"\n"
))
.unwrap();
let palette = build_palette(&raw);
assert_eq!(palette.selection_foreground, None, "{foreground}");
assert_eq!(palette.selection, rgba8([0xe5, 0xe9, 0xf0]));
}
}
#[test]
fn theme_without_selection_colors_preserves_user_foreground() {
let foreground = rgba8([0x10, 0x20, 0x30]);
let background = rgba8([0xe5, 0xe9, 0xf0]);
for theme in [ThemeName::Nebula, ThemeName::Paper] {
let mut palette = Palette {
selection_foreground: Some(foreground),
selection: background,
..Palette::default()
};
apply_theme(&mut palette, theme);
assert_eq!(palette.selection_foreground, Some(foreground));
assert_eq!(palette.selection, background);
}
}
#[test]
fn theme_with_selection_colors_keeps_its_existing_precedence() {
let mut palette = Palette {
selection_foreground: Some(rgba8([1, 2, 3])),
selection: rgba8([4, 5, 6]),
..Palette::default()
};
apply_theme(&mut palette, ThemeName::Nord);
assert_eq!(palette.selection_foreground, Some(rgba8([0x2e, 0x34, 0x40])));
assert_eq!(palette.selection, rgba8([0xe5, 0xe9, 0xf0]));
}
#[test]
fn themes_apply_only_the_colors_they_declare() {
let mut nord = Palette::default();
+1 -1
View File
@@ -27,7 +27,7 @@ pub struct Palette {
/// 选区叠加色。主应用默认是反色语义;本壳以半透明叠加近似,
/// 用户显式配置 `colors.selection.background` 时用不透明具体色。
pub selection: Rgba,
/// 主题明确声明的选区文字色;普通 Nebula 主题保留原字色。
/// 主题或用户明确声明的选区文字色;未声明时保留原字色。
pub selection_foreground: Option<Rgba>,
/// ANSI 0-15。
pub ansi: [Rgba; 16],