Skip to content

Commit

Permalink
Fix git-grep match-highlighting at line-start (#1057)
Browse files Browse the repository at this point in the history
* Fix git-grep match-highlighting at line-start

This commit fixes highlighting the part of the line of code that matches
the git grep query in cases where the match starts at the beginning of
the lines.

Fixes #1056.

* Fix handling of non-match highlight

In some cases, `git grep` will customize the foreground-color for more
than just the subset of the line that matches the grep pattern. This
breaks the current match-detection behavior, which considers any
characters with a non-default "foreground color" within the "code" part
of a git-grep-ouput-line to be part of the match. This commit makes
match-detection check for boldness and a red foreground instead of just
checking for a non-default foreground-color.

git grep matches are bold and red by default. But git grep isn't the
only reason input to delta may contain color codes; there may still be
cases where the highlighting looks wrong here.
  • Loading branch information
jdpopkin authored Jul 16, 2022
1 parent f556db8 commit b3cc0f8
Showing 1 changed file with 63 additions and 5 deletions.
68 changes: 63 additions & 5 deletions src/handlers/grep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,17 +222,19 @@ fn get_code_style_sections<'b>(
non_match_style: Style,
grep: &GrepLine,
) -> Option<StyleSectionSpecifier<'b>> {
if let Some(raw_code_start) = ansi::ansi_preserving_index(
if let Some(prefix_end) = ansi::ansi_preserving_index(
raw_line,
match grep.line_number {
Some(n) => format!("{}:{}:", grep.path, n).len(),
None => grep.path.len() + 1,
Some(n) => format!("{}:{}:", grep.path, n).len() - 1,
None => grep.path.len(),
},
) {
let match_style_sections = ansi::parse_style_sections(&raw_line[raw_code_start..])
let match_style_sections = ansi::parse_style_sections(&raw_line[(prefix_end + 1)..])
.iter()
.map(|(ansi_term_style, s)| {
if ansi_term_style.foreground.is_some() {
if ansi_term_style.is_bold
&& ansi_term_style.foreground == Some(ansi_term::Colour::Red)
{
(match_style, *s)
} else {
(non_match_style, *s)
Expand Down Expand Up @@ -900,4 +902,60 @@ mod tests {
let apparently_grep_output = "src/co-7-fig.rs:xxx";
assert_eq!(parse_grep_line(apparently_grep_output), None);
}

#[test]
fn test_get_code_style_sections() {
use crate::ansi::strip_ansi_codes;
use crate::handlers::grep::get_code_style_sections;
use crate::paint::StyleSectionSpecifier;
use crate::style::Style;

let fake_parent_grep_command = "git --doesnt-matter grep --nor-this nor_this -- nor_this";
let _args = FakeParentArgs::for_scope(fake_parent_grep_command);

let miss = Style::new();
let hit = Style {
is_emph: true,
..miss
};

let escape = "\x1B";
let working_example = format!("foo/bar/baz.yaml{escape}[36m:{escape}[m1090{escape}[36m:{escape}[m - {escape}[1;31mkind: Service{escape}[mAccount");
let stripped = strip_ansi_codes(&working_example);
let grep = parse_grep_line(&stripped).unwrap();

assert_eq!(
get_code_style_sections(&working_example, hit, miss, &grep),
Some(StyleSectionSpecifier::StyleSections(vec![
(miss, " - "),
(hit, "kind: Service"),
(miss, "Account")
]))
);

let broken_example = format!("foo/bar/baz.yaml{escape}[36m:{escape}[m2{escape}[36m:{escape}[m{escape}[1;31mkind: Service{escape}[m");
let broken_stripped = strip_ansi_codes(&broken_example);
let broken_grep = parse_grep_line(&broken_stripped).unwrap();

assert_eq!(
get_code_style_sections(&broken_example, hit, miss, &broken_grep),
Some(StyleSectionSpecifier::StyleSections(vec![(
hit,
"kind: Service"
)]))
);

let plus_example = format!("etc/examples/189-merge-conflict.2.diff{escape}[36m:{escape}[m10{escape}[36m:{escape}[m{escape}[32m + let (style, non_emph_style) = {escape}[1;31mmatch{escape}[m state {{{escape}[m");
let plus_stripped = strip_ansi_codes(&plus_example);
let plus_grep = parse_grep_line(&plus_stripped).unwrap();

assert_eq!(
get_code_style_sections(&plus_example, hit, miss, &plus_grep),
Some(StyleSectionSpecifier::StyleSections(vec![
(miss, " + let (style, non_emph_style) = "),
(hit, "match"),
(miss, " state {")
]))
);
}
}

0 comments on commit b3cc0f8

Please sign in to comment.