Apply fish_color_search_match foreground only if explicit

Historically, up-arrow search matches have been highlighted by

1. using the usual foreground (from syntax highlighting) 
2. using the background from $fish_color_search_match

Commit 9af6a64fd2 (Fix bad contrast in search match highlighting, 2024-04-15)
broke this by also applying the foreground from $fish_color_search_match.

As reported on gitter, there is a meaningful scenario where the foreground
from syntax highlighting should not be overwritten:

	set fish_color_search_match --reverse

this copies the foreground from syntax highlighting to the background.

Since commit 9af6a64fd2 overwrites the foreground highlight, the resulting
background will be monocolored (black in my case) instead of whatever is
the syntax-colored foreground.

FWIW the reversed foreground will always be monocolored, because we have
always done 2.

Let's unbreak this scenario by using the foreground from
fish_color_search_match only if it's explicitly set (like we do since
9af6a64fd2).

This is hacky because an empty color is normally the same as "normal", but
it gets us closer to historical behavior. In future we should try to come
up with a better approach to color blending/transparency.
This commit is contained in:
Johannes Altmanninger
2025-03-02 06:27:23 +01:00
parent c926a87bdb
commit b6269438e9
2 changed files with 18 additions and 5 deletions

View File

@@ -1,5 +1,5 @@
// Generic output functions.
use crate::color::RgbColor;
use crate::color::{self, RgbColor};
use crate::common::{self, wcs2string_appending};
use crate::env::EnvVar;
use crate::terminal::{self, tparm1, Term};
@@ -493,6 +493,14 @@ pub fn best_color(candidates: &[RgbColor], support: ColorSupport) -> RgbColor {
/// In particular, the argument parsing still isn't fully capable.
#[allow(clippy::collapsible_else_if)]
pub fn parse_color(var: &EnvVar, is_background: bool) -> RgbColor {
let mut result = parse_color_maybe_none(var, is_background);
if result.is_none() {
result.typ = color::Type::Normal;
}
result
}
pub fn parse_color_maybe_none(var: &EnvVar, is_background: bool) -> RgbColor {
let mut is_bold = false;
let mut is_underline = false;
let mut is_italics = false;
@@ -551,9 +559,6 @@ pub fn parse_color(var: &EnvVar, is_background: bool) -> RgbColor {
}
let mut result = best_color(&candidates, get_color_support());
if result.is_none() {
result = RgbColor::NORMAL;
}
result.set_bold(is_bold);
result.set_underline(is_underline);
result.set_italics(is_italics);

View File

@@ -104,6 +104,7 @@
use crate::nix::{getpgrp, getpid, isatty};
use crate::operation_context::{get_bg_context, OperationContext};
use crate::output::parse_color;
use crate::output::parse_color_maybe_none;
use crate::output::Outputter;
use crate::pager::{PageRendering, Pager, SelectionMotion};
use crate::panic::AT_EXIT;
@@ -1639,8 +1640,15 @@ fn paint_layout(&mut self, reason: &wstr, is_final_rendering: bool) {
range.end = colors.len();
}
let explicit_foreground = self
.vars()
.get_unless_empty(L!("fish_color_search_match"))
.is_some_and(|var| !parse_color_maybe_none(&var, false).is_none());
for color in &mut colors[range] {
color.foreground = HighlightRole::search_match;
if explicit_foreground {
color.foreground = HighlightRole::search_match;
}
color.background = HighlightRole::search_match;
}
}