diff options
author | Dan Davison <dandavison7@gmail.com> | 2021-11-18 20:52:58 -0500 |
---|---|---|
committer | Dan Davison <dandavison7@gmail.com> | 2021-11-28 18:28:22 -0500 |
commit | 39ef747843d3f49078a5402577bde8e6ae235b67 (patch) | |
tree | be90e3ee700fcdd4981b31c2bd37c57585d566aa | |
parent | 8a275c361743f1689c1a9118deab4a35ad975f86 (diff) |
Change rules for non-emph style
Fixes #776
Previously, when a paired plus line had no edits, it received
plus-style. With this commit such a line receives
plus-non-emph-style.
There's no change to unpaired lines (still plus-style) and paired
lines with edits (still a mosaic of plus-non-emph-style and plus-emph-style).
(The above statements hold for minus lines also).
Since *-non-emph-style defaults to *-emph-style, this commit does not
result in any change in output for users using the defaults.
-rw-r--r-- | src/edits.rs | 14 | ||||
-rw-r--r-- | src/paint.rs | 30 |
2 files changed, 37 insertions, 7 deletions
diff --git a/src/edits.rs b/src/edits.rs index 11979aa8..bd90787d 100644 --- a/src/edits.rs +++ b/src/edits.rs @@ -8,10 +8,16 @@ use crate::align; /// Infer the edit operations responsible for the differences between a collection of old and new /// lines. A "line" is a string. An annotated line is a Vec of (op, &str) pairs, where the &str /// slices are slices of the line, and their concatenation equals the line. Return the input minus -/// and plus lines, in annotated form. Also return a specification of the inferred alignment of -/// minus and plus lines. `noop_deletions[i]` is the appropriate deletion operation tag to be used -/// for `minus_lines[i]`; `noop_deletions` is guaranteed to be the same length as `minus_lines`. -/// The equivalent statements hold for `plus_insertions` and `plus_lines`. +/// and plus lines, in annotated form. +/// +/// Also return a specification of the inferred alignment of minus and plus lines: a paired minus +/// and plus line is represented in this alignment specification as +/// (Some(minus_line_index),Some(plus_line_index)), whereas an unpaired minus line is +/// (Some(minus_line_index), None). +/// +/// `noop_deletions[i]` is the appropriate deletion operation tag to be used for `minus_lines[i]`; +/// `noop_deletions` is guaranteed to be the same length as `minus_lines`. The equivalent statements +/// hold for `plus_insertions` and `plus_lines`. #[allow(clippy::too_many_arguments)] #[allow(clippy::type_complexity)] pub fn infer_edits<'a, EditOperation>( diff --git a/src/paint.rs b/src/paint.rs index a3f8f416..79b44db1 100644 --- a/src/paint.rs +++ b/src/paint.rs @@ -625,11 +625,27 @@ impl<'p> Painter<'p> { None }; let mut lines_style_sections = MinusPlus::new(&mut diff_sections.0, &mut diff_sections.1); + // PERF: avoid heap allocations here? + let mut lines_have_homolog: MinusPlus<Vec<bool>> = MinusPlus::new( + diff_sections + .2 + .iter() + .filter(|(m, _)| m.is_some()) + .map(|(_, p)| p.is_some()) + .collect(), + diff_sections + .2 + .iter() + .filter(|(_, p)| p.is_some()) + .map(|(m, _)| m.is_some()) + .collect(), + ); Self::update_styles( minus_lines_and_states, lines_style_sections[Minus], None, minus_non_emph_style, + &mut lines_have_homolog[Minus], config, ); let plus_non_emph_style = if config.plus_non_emph_style != config.plus_emph_style { @@ -642,6 +658,7 @@ impl<'p> Painter<'p> { lines_style_sections[Plus], Some(config.whitespace_error_style), plus_non_emph_style, + &mut lines_have_homolog[Plus], config, ); diff_sections @@ -664,9 +681,14 @@ impl<'p> Painter<'p> { lines_style_sections: &mut Vec<LineSections<'a, Style>>, whitespace_error_style: Option<Style>, non_emph_style: Option<Style>, + lines_have_homolog: &mut Vec<bool>, config: &config::Config, ) { - for ((_, state), style_sections) in lines_and_states.iter().zip(lines_style_sections) { + for (((_, state), style_sections), line_has_homolog) in lines_and_states + .iter() + .zip(lines_style_sections) + .zip(lines_have_homolog) + { match state { State::HunkMinus(Some(raw_line)) | State::HunkPlus(Some(raw_line)) => { *style_sections = parse_style_sections(raw_line, config); @@ -676,14 +698,16 @@ impl<'p> Painter<'p> { }; let line_has_emph_and_non_emph_sections = style_sections_contain_more_than_one_style(style_sections); - let should_update_non_emph_styles = - non_emph_style.is_some() && line_has_emph_and_non_emph_sections; + let should_update_non_emph_styles = non_emph_style.is_some() && *line_has_homolog; let is_whitespace_error = whitespace_error_style.is_some() && is_whitespace_error(style_sections); for (style, _) in style_sections.iter_mut() { // If the line as a whole constitutes a whitespace error then highlight this // section if either (a) it is an emph section, or (b) the line lacks any // emph/non-emph distinction. + + // TODO: is this logic correct now, after introducing + // line_has_homolog for non_emph style? if is_whitespace_error && (style.is_emph || !line_has_emph_and_non_emph_sections) { *style = whitespace_error_style.unwrap(); } |