Merge pull request #125 from Aschenbath/fix/selection-palette-regressions
fix(terminal): honor explicit selection foreground colors
This commit is contained in:
3 files changed
+95
-3
No files matched your search
@@ -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:
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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],
|
||||
|
||||
Reference in new issue
Block a user