summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJackson Popkin <jackson@donorschoose.org>2022-07-15 21:58:05 -0400
committerGitHub <noreply@github.com>2022-07-15 21:58:05 -0400
commitb3cc0f8cae943ec87a4e7b300af431cecda80b68 (patch)
treedae2dc53cf39cd9e2bf4b1d718797509d87dba3d
parentf556db8d4edac47c6b053191f02568969a14f06a (diff)
Fix git-grep match-highlighting at line-start (#1057)
* 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.
-rw-r--r--src/handlers/grep.rs68
1 files changed, 63 insertions, 5 deletions
diff --git a/src/handlers/grep.rs b/src/handlers/grep.rs
index 3bb92147..88e4130a 100644
--- a/src/handlers/grep.rs
+++ b/src/handlers/grep.rs
@@ -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)
@@ -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 {")
+ ]))
+ );
+ }
}