1
0
mirror of https://github.com/BurntSushi/ripgrep.git synced 2025-11-23 21:54:45 +02:00

colors: add highlight type support for matching lines

This lets users highlight non-matching text in matching lines.

Closes #3024, Closes #3107
This commit is contained in:
emrebengue
2025-07-23 21:45:17 -04:00
committed by Andrew Gallant
parent 126bbeab8c
commit 99fe884536
6 changed files with 88 additions and 17 deletions

View File

@@ -51,13 +51,13 @@ impl std::fmt::Display for ColorError {
ColorError::UnrecognizedOutType(ref name) => write!(
f,
"unrecognized output type '{}'. Choose from: \
path, line, column, match.",
path, line, column, match, highlight.",
name,
),
ColorError::UnrecognizedSpecType(ref name) => write!(
f,
"unrecognized spec type '{}'. Choose from: \
fg, bg, style, none.",
fg, bg, style, none.",
name,
),
ColorError::UnrecognizedColor(_, ref msg) => write!(f, "{}", msg),
@@ -70,8 +70,8 @@ impl std::fmt::Display for ColorError {
),
ColorError::InvalidFormat(ref original) => write!(
f,
"invalid color spec format: '{}'. Valid format \
is '(path|line|column|match):(fg|bg|style):(value)'.",
"invalid color spec format: '{}'. Valid format is \
'(path|line|column|match|highlight):(fg|bg|style):(value)'.",
original,
),
}
@@ -90,6 +90,7 @@ pub struct ColorSpecs {
line: ColorSpec,
column: ColorSpec,
matched: ColorSpec,
highlight: ColorSpec,
}
/// A single color specification provided by the user.
@@ -99,7 +100,7 @@ pub struct ColorSpecs {
/// The format of a `Spec` is a triple: `{type}:{attribute}:{value}`. Each
/// component is defined as follows:
///
/// * `{type}` can be one of `path`, `line`, `column` or `match`.
/// * `{type}` can be one of `path`, `line`, `column`, `match` or `highlight`.
/// * `{attribute}` can be one of `fg`, `bg` or `style`. `{attribute}` may also
/// be the special value `none`, in which case, `{value}` can be omitted.
/// * `{value}` is either a color name (for `fg`/`bg`) or a style instruction.
@@ -181,6 +182,7 @@ enum OutType {
Line,
Column,
Match,
Highlight,
}
/// The specification type.
@@ -216,6 +218,7 @@ impl ColorSpecs {
OutType::Line => spec.merge_into(&mut merged.line),
OutType::Column => spec.merge_into(&mut merged.column),
OutType::Match => spec.merge_into(&mut merged.matched),
OutType::Highlight => spec.merge_into(&mut merged.highlight),
}
}
merged
@@ -249,6 +252,12 @@ impl ColorSpecs {
pub fn matched(&self) -> &ColorSpec {
&self.matched
}
/// Return the color specification for coloring entire line if there is a
/// matched text.
pub fn highlight(&self) -> &ColorSpec {
&self.highlight
}
}
impl UserColorSpec {
@@ -348,6 +357,7 @@ impl std::str::FromStr for OutType {
"line" => Ok(OutType::Line),
"column" => Ok(OutType::Column),
"match" => Ok(OutType::Match),
"highlight" => Ok(OutType::Highlight),
_ => Err(ColorError::UnrecognizedOutType(s.to_string())),
}
}

View File

@@ -1320,6 +1320,7 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
self.write(&bytes[line])?;
return Ok(());
}
self.start_line_highlight()?;
while !line.is_empty() {
if matches[*match_index].end() <= line.start() {
if *match_index + 1 < matches.len() {
@@ -1346,6 +1347,7 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
}
}
self.end_color_match()?;
self.end_line_highlight()?;
Ok(())
}
@@ -1547,11 +1549,37 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
if !self.in_color_match.get() {
return Ok(());
}
self.wtr().borrow_mut().reset()?;
if self.highlight_on() {
self.wtr()
.borrow_mut()
.set_color(self.config().colors.highlight())?;
} else {
self.wtr().borrow_mut().reset()?;
}
self.in_color_match.set(false);
Ok(())
}
fn highlight_on(&self) -> bool {
!self.config().colors.highlight().is_none() && !self.is_context()
}
fn start_line_highlight(&self) -> io::Result<()> {
if self.highlight_on() {
self.wtr()
.borrow_mut()
.set_color(self.config().colors.highlight())?;
}
Ok(())
}
fn end_line_highlight(&self) -> io::Result<()> {
if self.highlight_on() {
self.wtr().borrow_mut().reset()?;
}
Ok(())
}
fn write(&self, buf: &[u8]) -> io::Result<()> {
self.wtr().borrow_mut().write_all(buf)
}