summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Davison <dandavison7@gmail.com>2021-11-18 20:52:58 -0500
committerDan Davison <dandavison7@gmail.com>2021-11-28 18:28:22 -0500
commit39ef747843d3f49078a5402577bde8e6ae235b67 (patch)
treebe90e3ee700fcdd4981b31c2bd37c57585d566aa
parent8a275c361743f1689c1a9118deab4a35ad975f86 (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.rs14
-rw-r--r--src/paint.rs30
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();
}