Hook up new hunk merging logic

pull/70/head
Wilfred Hughes 2021-10-31 16:43:32 +07:00
parent 61d2767bbe
commit 46d96a5c9c
4 changed files with 88 additions and 21 deletions

@ -194,13 +194,16 @@ fn after_with_opposites(
res
}
pub fn add_context(
pub fn calculate_context(
lines: &[(Option<LineNumber>, Option<LineNumber>)],
lhs_mps: &[MatchedPos],
rhs_mps: &[MatchedPos],
max_lhs_src_line: LineNumber,
max_rhs_src_line: LineNumber,
) -> Vec<(Option<LineNumber>, Option<LineNumber>)> {
) -> (
Vec<(Option<LineNumber>, Option<LineNumber>)>,
Vec<(Option<LineNumber>, Option<LineNumber>)>,
) {
let opposite_to_lhs = opposite_positions(lhs_mps);
let opposite_to_rhs = opposite_positions(rhs_mps);
@ -214,9 +217,9 @@ pub fn add_context(
let padded_lines = pad_before(rhs_line);
flip_tuples(&before_with_opposites(&padded_lines, &opposite_to_rhs))
}
(None, None) => return vec![],
(None, None) => return (vec![], vec![]),
},
None => return vec![],
None => return (vec![], vec![]),
};
let mut after_lines = match lines.last() {
@ -253,11 +256,24 @@ pub fn add_context(
max_rhs_src_line,
))
}
(None, None) => return vec![],
(None, None) => return (vec![], vec![]),
},
None => return vec![],
None => return (vec![], vec![]),
};
(before_lines, after_lines)
}
pub fn add_context(
lines: &[(Option<LineNumber>, Option<LineNumber>)],
lhs_mps: &[MatchedPos],
rhs_mps: &[MatchedPos],
max_lhs_src_line: LineNumber,
max_rhs_src_line: LineNumber,
) -> Vec<(Option<LineNumber>, Option<LineNumber>)> {
let (mut before_lines, mut after_lines) =
calculate_context(lines, lhs_mps, rhs_mps, max_lhs_src_line, max_rhs_src_line);
let mut res: Vec<(Option<LineNumber>, Option<LineNumber>)> = vec![];
res.append(&mut before_lines);
res.extend(lines.iter());

@ -6,13 +6,13 @@ const MAX_DISTANCE: usize = 3;
use std::collections::{HashMap, HashSet};
use crate::{
context::{add_context, calculate_context},
lines::{compare_matched_pos, LineNumber},
syntax::{zip_pad_shorter, MatchKind, MatchedPos},
};
#[derive(Debug, Clone)]
pub struct Hunk {
// TODO: consider having a lhs_changed_lines and rhs_changed_lines instead.
pub lines: Vec<(Option<LineNumber>, Option<LineNumber>)>,
}
@ -468,20 +468,29 @@ fn compact_gaps(
res
}
fn aligned_lines_from_hunk(
pub fn aligned_lines_from_hunk(
hunk: &Hunk,
lhs_mps: &[MatchedPos],
rhs_mps: &[MatchedPos],
max_lhs_src_line: LineNumber,
max_rhs_src_line: LineNumber,
matched_rhs_lines: &HashMap<LineNumber, HashSet<LineNumber>>,
) -> Vec<(Option<LineNumber>, Option<LineNumber>)> {
let hunk_lines: Vec<(Option<LineNumber>, Option<LineNumber>)> = hunk.lines.clone();
let prev_context: Vec<(Option<LineNumber>, Option<LineNumber>)> = todo!();
let after_context: Vec<(Option<LineNumber>, Option<LineNumber>)> = todo!();
let (before_context, after_context) = calculate_context(
&hunk_lines,
lhs_mps,
rhs_mps,
max_lhs_src_line,
max_rhs_src_line,
);
let (start_pair, prev_context) = split_last_pair(prev_context);
let (end_pair, after_context) = split_last_pair(prev_context);
let (start_pair, before_context) = split_last_pair(before_context);
let (end_pair, after_context) = split_first_pair(after_context);
let mut res = vec![];
res.extend(prev_context);
res.extend(before_context);
if let (Some(start_pair), Some(end_pair)) = (start_pair, end_pair) {
// Fill lines between.
let aligned_between = fill_aligned(start_pair, end_pair, matched_rhs_lines);

@ -9,13 +9,13 @@ use std::{
use crate::{
context::add_context,
hunks::{extract_lines, Hunk},
hunks::{aligned_lines_from_hunk, extract_lines, Hunk},
lines::{
codepoint_len, enforce_exact_length, enforce_max_length, format_line_num, LineGroup,
LineNumber,
},
style::{self, apply_colors, header},
syntax::{aligned_lines, MatchedPos},
syntax::{aligned_lines, zip_repeat_shorter, MatchKind, MatchedPos},
};
const SPACER: &str = " ";
@ -375,6 +375,42 @@ fn merge_adjacent(
res
}
// TODO: this duplicates context::opposite_positions.
fn opposite_positions(mps: &[MatchedPos]) -> HashMap<LineNumber, HashSet<LineNumber>> {
let mut res: HashMap<LineNumber, HashSet<LineNumber>> = HashMap::new();
for mp in mps {
match &mp.kind {
MatchKind::Unchanged {
self_pos,
opposite_pos,
..
} => {
for (self_span, opposite_span) in zip_repeat_shorter(&self_pos.0, &opposite_pos.0) {
let opposite_lines = res.entry(self_span.line).or_insert_with(HashSet::new);
opposite_lines.insert(opposite_span.line);
}
for (self_span, opposite_span) in zip_repeat_shorter(&self_pos.1, &opposite_pos.1) {
let opposite_lines = res.entry(self_span.line).or_insert_with(HashSet::new);
opposite_lines.insert(opposite_span.line);
}
}
MatchKind::UnchangedCommentPart {
opposite_pos,
self_pos,
} => {
let opposite_lines = res.entry(self_pos.line).or_insert_with(HashSet::new);
for opposite_span in opposite_pos {
opposite_lines.insert(opposite_span.line);
}
}
MatchKind::Novel { .. } | MatchKind::ChangedCommentPart { .. } => {}
}
}
res
}
pub fn display_hunks(
hunks: &[Hunk],
display_path: &str,
@ -415,11 +451,17 @@ pub fn display_hunks(
for (i, hunk) in hunks.iter().enumerate() {
out_lines.push(style::header(display_path, i + 1, hunks.len(), lang_name));
let lines = extract_lines(hunk);
let contextual_lines =
add_context(&lines, lhs_mps, rhs_mps, max_lhs_src_line, max_rhs_src_line);
for (lhs_line_num, rhs_line_num) in contextual_lines {
let matched_rhs_lines = opposite_positions(lhs_mps);
let aligned_lines = aligned_lines_from_hunk(
hunk,
lhs_mps,
rhs_mps,
max_lhs_src_line,
max_rhs_src_line,
&matched_rhs_lines,
);
for (lhs_line_num, rhs_line_num) in aligned_lines {
let lhs_line = match lhs_line_num {
Some(lhs_line_num) => lhs_colored_lines[lhs_line_num.0].clone(),
None => " ".repeat(lhs_content_width),

@ -856,7 +856,7 @@ pub fn zip_pad_shorter<Tx: Copy, Ty: Copy>(
/// Zip `lhs` with `rhs`, but repeat the last item from the shorter
/// slice.
fn zip_repeat_shorter<Tx: Copy, Ty: Copy>(lhs: &[Tx], rhs: &[Ty]) -> Vec<(Tx, Ty)> {
pub fn zip_repeat_shorter<Tx: Copy, Ty: Copy>(lhs: &[Tx], rhs: &[Ty]) -> Vec<(Tx, Ty)> {
let lhs_last: Tx = match lhs.last() {
Some(last) => *last,
None => return vec![],