mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-10-06 05:36:58 +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:
committed by
Andrew Gallant
parent
126bbeab8c
commit
99fe884536
@@ -43,6 +43,8 @@ Feature enhancements:
|
||||
When using multithreading, schedule files to search in order given on CLI.
|
||||
* [FEATURE #2943](https://github.com/BurntSushi/ripgrep/issues/2943):
|
||||
Add `aarch64` release artifacts for Windows.
|
||||
* [FEATURE #3024](https://github.com/BurntSushi/ripgrep/issues/3024):
|
||||
Add `highlight` color type, for styling non-matching text in a matching line.
|
||||
* [FEATURE #3048](https://github.com/BurntSushi/ripgrep/pull/3048):
|
||||
Globs in ripgrep (and the `globset` crate) now support nested alternates.
|
||||
|
||||
|
4
FAQ.md
4
FAQ.md
@@ -285,8 +285,8 @@ As a special case, `--colors '{type}:none'` will clear all colors and styles
|
||||
associated with `{type}`, which lets you start with a clean slate (instead of
|
||||
building on top of ripgrep's default color settings).
|
||||
|
||||
Here's an example that makes highlights the matches with a nice blue background
|
||||
with bolded white text:
|
||||
Here's an example that highlights the matches with a nice blue background with
|
||||
bolded white text:
|
||||
|
||||
```
|
||||
$ rg somepattern \
|
||||
|
@@ -363,10 +363,11 @@ _rg() {
|
||||
'column:specify coloring for column numbers'
|
||||
'line:specify coloring for line numbers'
|
||||
'match:specify coloring for match text'
|
||||
'highlight:specify coloring for matching lines'
|
||||
'path:specify coloring for file names'
|
||||
)
|
||||
descr='color/style type'
|
||||
elif [[ ${IPREFIX#--*=}$PREFIX == (column|line|match|path):[^:]# ]]; then
|
||||
elif [[ ${IPREFIX#--*=}$PREFIX == (column|line|match|highlight|path):[^:]# ]]; then
|
||||
suf=( -qS: )
|
||||
tmp=(
|
||||
'none:clear color/style for type'
|
||||
|
@@ -751,7 +751,8 @@ the \flag{colors} flag to manually set all color styles to \fBnone\fP:
|
||||
\-\-colors 'path:none' \\
|
||||
\-\-colors 'line:none' \\
|
||||
\-\-colors 'column:none' \\
|
||||
\-\-colors 'match:none'
|
||||
\-\-colors 'match:none' \\
|
||||
\-\-colors 'highlight:none'
|
||||
.EE
|
||||
.sp
|
||||
"
|
||||
@@ -829,7 +830,7 @@ impl Flag for Colors {
|
||||
"Configure color settings and styles."
|
||||
}
|
||||
fn doc_long(&self) -> &'static str {
|
||||
r"
|
||||
r#"
|
||||
This flag specifies color settings for use in the output. This flag may be
|
||||
provided multiple times. Settings are applied iteratively. Pre-existing color
|
||||
labels are limited to one of eight choices: \fBred\fP, \fBblue\fP, \fBgreen\fP,
|
||||
@@ -839,11 +840,11 @@ are limited to \fBnobold\fP, \fBbold\fP, \fBnointense\fP, \fBintense\fP,
|
||||
.sp
|
||||
The format of the flag is
|
||||
\fB{\fP\fItype\fP\fB}:{\fP\fIattribute\fP\fB}:{\fP\fIvalue\fP\fB}\fP.
|
||||
\fItype\fP should be one of \fBpath\fP, \fBline\fP, \fBcolumn\fP or
|
||||
\fBmatch\fP. \fIattribute\fP can be \fBfg\fP, \fBbg\fP or \fBstyle\fP.
|
||||
\fIvalue\fP is either a color (for \fBfg\fP and \fBbg\fP) or a text style. A
|
||||
special format, \fB{\fP\fItype\fP\fB}:none\fP, will clear all color settings
|
||||
for \fItype\fP.
|
||||
\fItype\fP should be one of \fBpath\fP, \fBline\fP, \fBcolumn\fP,
|
||||
\fBhighlight\fP or \fBmatch\fP. \fIattribute\fP can be \fBfg\fP, \fBbg\fP or
|
||||
\fBstyle\fP. \fIvalue\fP is either a color (for \fBfg\fP and \fBbg\fP) or a
|
||||
text style. A special format, \fB{\fP\fItype\fP\fB}:none\fP, will clear all
|
||||
color settings for \fItype\fP.
|
||||
.sp
|
||||
For example, the following command will change the match color to magenta and
|
||||
the background color for line numbers to yellow:
|
||||
@@ -852,6 +853,17 @@ the background color for line numbers to yellow:
|
||||
rg \-\-colors 'match:fg:magenta' \-\-colors 'line:bg:yellow'
|
||||
.EE
|
||||
.sp
|
||||
Another example, the following command will "highlight" the non-matching text
|
||||
in matching lines:
|
||||
.sp
|
||||
.EX
|
||||
rg \-\-colors 'highlight:bg:yellow' \-\-colors 'highlight:fg:black'
|
||||
.EE
|
||||
.sp
|
||||
The "highlight" color type is particularly useful for contrasting matching
|
||||
lines with surrounding context printed by the \flag{before-context},
|
||||
\flag{after-context}, \flag{context} or \flag{passthru} flags.
|
||||
.sp
|
||||
Extended colors can be used for \fIvalue\fP when the tty supports ANSI color
|
||||
sequences. These are specified as either \fIx\fP (256-color) or
|
||||
.IB x , x , x
|
||||
@@ -874,7 +886,7 @@ or, equivalently,
|
||||
.sp
|
||||
Note that the \fBintense\fP and \fBnointense\fP styles will have no effect when
|
||||
used alongside these extended color codes.
|
||||
"
|
||||
"#
|
||||
}
|
||||
|
||||
fn update(&self, v: FlagValue, args: &mut LowArgs) -> anyhow::Result<()> {
|
||||
@@ -908,6 +920,24 @@ fn test_colors() {
|
||||
"line:bg:yellow".parse().unwrap()
|
||||
]
|
||||
);
|
||||
|
||||
let args = parse_low_raw(["--colors", "highlight:bg:240"]).unwrap();
|
||||
assert_eq!(args.colors, vec!["highlight:bg:240".parse().unwrap()]);
|
||||
|
||||
let args = parse_low_raw([
|
||||
"--colors",
|
||||
"match:fg:magenta",
|
||||
"--colors",
|
||||
"highlight:bg:blue",
|
||||
])
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
args.colors,
|
||||
vec![
|
||||
"match:fg:magenta".parse().unwrap(),
|
||||
"highlight:bg:blue".parse().unwrap()
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/// --column
|
||||
|
@@ -51,7 +51,7 @@ 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!(
|
||||
@@ -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())),
|
||||
}
|
||||
}
|
||||
|
@@ -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(());
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
Reference in New Issue
Block a user