diff --git a/CHANGELOG.md b/CHANGELOG.md index 01326bd57..fe0237d84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,9 @@ Fixed an issue where comment replacements were not detected. Changed words in comments are now only highlighted when comments are relatively similar (according to their Levenshtein distance). +Improved alignment for lines at the beginning of a changed group of +lines. + ### Command Line Interface Removed unused `--inline` argument. diff --git a/src/syntax.rs b/src/syntax.rs index 2f88bc2e2..b11c648b4 100644 --- a/src/syntax.rs +++ b/src/syntax.rs @@ -711,6 +711,34 @@ pub fn aligned_lines( lhs_lines: &[LineNumber], rhs_lines: &[LineNumber], lhs_line_matches: &HashMap, +) -> Vec<(Option, Option)> { + // When adding padding to a LineGroup where each side has a + // different number of lines, we can end up with extra padding on + // the side with fewer lines. + // + // Work around that by discarding any lines at the beginning with + // aren't matched. + // + // TODO: fix padding to be smarter. + aligned_lines_(lhs_lines, rhs_lines, lhs_line_matches) + .iter() + .skip_while(|(lhs, rhs)| lhs.is_none() || rhs.is_none()) + .copied() + .collect() +} + +/// Given two slices of contiguous line numbers, return pairs of +/// matched lines. +/// +/// A LHS line is matched with a RHS line if it's present in +/// `lhs_line_matches` and hasn't already been matched. +/// +/// If a line has no match on the other side, the pair will contain +/// None on the other side. +fn aligned_lines_( + lhs_lines: &[LineNumber], + rhs_lines: &[LineNumber], + lhs_line_matches: &HashMap, ) -> Vec<(Option, Option)> { let mut rhs_highest_matched = rhs_lines.first().map(|l| l.0 as isize).unwrap_or(0) - 1; @@ -827,7 +855,7 @@ mod tests { line_matches.insert(2.into(), 12.into()); assert_eq!( - aligned_lines(&lhs_lines, &rhs_lines, &line_matches), + aligned_lines_(&lhs_lines, &rhs_lines, &line_matches), vec![ (Some(1.into()), None), (Some(2.into()), Some(12.into())), @@ -836,6 +864,20 @@ mod tests { ); } + #[test] + fn test_aligned_middle_drop_none_at_start() { + let lhs_lines: Vec = vec![1.into(), 2.into()]; + let rhs_lines: Vec = vec![12.into(), 13.into()]; + + let mut line_matches: HashMap = HashMap::new(); + line_matches.insert(2.into(), 12.into()); + + assert_eq!( + aligned_lines(&lhs_lines, &rhs_lines, &line_matches), + vec![(Some(2.into()), Some(12.into())), (None, Some(13.into()))] + ); + } + #[test] fn test_aligned_all() { let lhs_lines: Vec = vec![1.into(), 2.into()]; @@ -846,7 +888,7 @@ mod tests { line_matches.insert(2.into(), 12.into()); assert_eq!( - aligned_lines(&lhs_lines, &rhs_lines, &line_matches), + aligned_lines_(&lhs_lines, &rhs_lines, &line_matches), vec![ (Some(1.into()), Some(11.into())), (Some(2.into()), Some(12.into())), @@ -862,7 +904,7 @@ mod tests { let line_matches: HashMap = HashMap::new(); assert_eq!( - aligned_lines(&lhs_lines, &rhs_lines, &line_matches), + aligned_lines_(&lhs_lines, &rhs_lines, &line_matches), vec![(Some(1.into()), Some(11.into()))] ); } @@ -877,7 +919,7 @@ mod tests { line_matches.insert(2.into(), 11.into()); assert_eq!( - aligned_lines(&lhs_lines, &rhs_lines, &line_matches), + aligned_lines_(&lhs_lines, &rhs_lines, &line_matches), vec![(Some(1.into()), Some(11.into())), (Some(2.into()), None)] ); } @@ -892,7 +934,7 @@ mod tests { line_matches.insert(1.into(), 12.into()); assert_eq!( - aligned_lines(&lhs_lines, &rhs_lines, &line_matches), + aligned_lines_(&lhs_lines, &rhs_lines, &line_matches), vec![ (None, Some(11.into())), (Some(1.into()), Some(12.into())), @@ -910,7 +952,7 @@ mod tests { line_matches.insert(1.into(), 10.into()); assert_eq!( - aligned_lines(&lhs_lines, &rhs_lines, &line_matches), + aligned_lines_(&lhs_lines, &rhs_lines, &line_matches), vec![ (Some(1.into()), Some(11.into())), (Some(2.into()), Some(12.into())), @@ -927,7 +969,7 @@ mod tests { line_matches.insert(0.into(), 0.into()); assert_eq!( - aligned_lines(&lhs_lines, &rhs_lines, &line_matches), + aligned_lines_(&lhs_lines, &rhs_lines, &line_matches), vec![(Some(0.into()), Some(0.into()))] ); }