@@ -83,64 +83,6 @@ impl<'a> sum_tree::Dimension<'a, DiffHunkSummary> for HunkBufferEnd {
}
}
-// struct HunkIter<'a> {
-// index: usize,
-// patch: GitPatch<'a>,
-// }
-
-// impl<'a> HunkIter<'a> {
-// fn diff(head: &'a [u8], current: &'a [u8]) -> Option<Self> {
-// let mut options = GitOptions::default();
-// options.context_lines(0);
-// let patch = match GitPatch::from_buffers(head, None, current, None, Some(&mut options)) {
-// Ok(patch) => patch,
-// Err(_) => return None,
-// };
-
-// Some(HunkIter { index: 0, patch })
-// }
-
-// fn next(&mut self, buffer: &BufferSnapshot) -> Option<DiffHunk<Anchor>> {
-// if self.index >= self.patch.num_hunks() {
-// return None;
-// }
-
-// let (hunk, _) = match self.patch.hunk(self.index) {
-// Ok(it) => it,
-// Err(_) => return None,
-// };
-// let hunk_line_count = self.patch.num_lines_in_hunk(self.index).unwrap();
-
-// println!("{hunk:#?}");
-// for index in 0..hunk_line_count {
-// println!("{:?}", self.patch.line_in_hunk(self.index, index));
-// }
-
-// let new_start = hunk.new_start() - 1;
-// let new_end = new_start + hunk.new_lines();
-// let start_anchor = buffer.anchor_at(Point::new(new_start, 0), Bias::Left);
-// let end_anchor = buffer.anchor_at(Point::new(new_end, 0), Bias::Left);
-// let buffer_range = start_anchor..end_anchor;
-
-// //This is probably wrong? When does this trigger? Should buffer range also do this?
-// let head_range = if hunk.old_start() == 0 {
-// 0..0
-// } else {
-// let old_start = hunk.old_start() - 1;
-// let old_end = old_start + hunk.old_lines();
-// old_start..old_end
-// };
-
-// // let head_start_index = self.patch.line_in_hunk(self.index, 0)
-
-// self.index += 1;
-// Some(DiffHunk {
-// buffer_range,
-// head_range,
-// })
-// }
-// }
-
#[derive(Clone)]
pub struct BufferDiffSnapshot {
tree: SumTree<DiffHunk<Anchor>>,
@@ -187,221 +129,102 @@ pub struct BufferDiff {
impl BufferDiff {
pub fn new(head_text: &Option<String>, buffer: &text::BufferSnapshot) -> BufferDiff {
- let hunks = if let Some(head_text) = head_text {
- let buffer_string = buffer.as_rope().to_string();
- let buffer_bytes = buffer_string.as_bytes();
-
- let mut options = GitOptions::default();
- options.context_lines(0);
- let patch = match GitPatch::from_buffers(
- head_text.as_bytes(),
- None,
- buffer_bytes,
- None,
- Some(&mut options),
- ) {
- Ok(patch) => patch,
- Err(_) => todo!("This needs to be handled"),
- };
-
- let mut hunks = SumTree::<DiffHunk<Anchor>>::new();
- let mut delta = 0i64;
- for i in 0..patch.num_hunks() {
- let diff_line_item_count = patch.num_lines_in_hunk(i).unwrap();
-
- // if diff_line_item_count == 0 {
- // continue;
- // }
-
- // let calc_line_diff_hunk = || {
-
- // };
-
- // let first_line = patch.line_in_hunk(0).unwrap();
- // let mut hunk =
-
- for j in 0..diff_line_item_count {
- let line = patch.line_in_hunk(i, j).unwrap();
-
- let hunk = match line.origin_value() {
- libgit::DiffLineType::Addition => {
- let buffer_start = line.content_offset();
- let buffer_end = buffer_start as usize + line.content().len();
- let head_offset = (buffer_start - delta) as usize;
- delta += line.content().len() as i64;
- DiffHunk {
- buffer_range: buffer.anchor_before(buffer_start as usize)
- ..buffer.anchor_after(buffer_end),
- head_range: head_offset..head_offset,
- }
- }
- libgit::DiffLineType::Deletion => {
- let head_start = line.content_offset();
- let head_end = head_start as usize + line.content().len();
- let buffer_offset = (head_start + delta) as usize;
- delta -= line.content().len() as i64;
- DiffHunk {
- buffer_range: buffer.anchor_before(buffer_offset)
- ..buffer.anchor_after(buffer_offset),
- head_range: (head_start as usize)..head_end,
- }
- }
-
- libgit::DiffLineType::AddEOFNL => todo!(),
- libgit::DiffLineType::ContextEOFNL => todo!(),
- libgit::DiffLineType::DeleteEOFNL => todo!(),
- libgit::DiffLineType::Context => unreachable!(),
- libgit::DiffLineType::FileHeader => continue,
- libgit::DiffLineType::HunkHeader => continue,
- libgit::DiffLineType::Binary => continue,
- };
-
- let mut combined = false;
- hunks.update_last(
- |last_hunk| {
- if last_hunk.head_range.end == hunk.head_range.start {
- last_hunk.head_range.end = hunk.head_range.end;
- last_hunk.buffer_range.end = hunk.buffer_range.end;
- combined = true;
- }
- },
- buffer,
- );
- if !combined {
- hunks.push(hunk, buffer);
- }
- }
- }
-
- // let iter = HunkIter::diff(head_text.as_bytes(), buffer_bytes);
- // if let Some(mut iter) = iter {
- // let mut hunks = SumTree::new();
- // while let Some(hunk) = iter.next(buffer) {
- // hunks.push(hunk, buffer);
- // }
- // println!("========");
- // hunks
- // } else {
- // SumTree::new()
- // }
- hunks
- } else {
- SumTree::new()
+ let mut instance = BufferDiff {
+ last_update_version: buffer.version().clone(),
+ snapshot: BufferDiffSnapshot {
+ tree: SumTree::new(),
+ },
};
- BufferDiff {
- last_update_version: buffer.version().clone(),
- snapshot: BufferDiffSnapshot { tree: hunks },
+ if let Some(head_text) = head_text {
+ instance.update(head_text, buffer);
}
+
+ instance
}
pub fn snapshot(&self) -> BufferDiffSnapshot {
self.snapshot.clone()
}
- pub fn update(&mut self, head: &Rope, buffer: &text::BufferSnapshot) {
- // let expand_by = 20;
- // let combine_distance = 5;
-
- // struct EditRange {
- // head_start: u32,
- // head_end: u32,
- // buffer_start: u32,
- // buffer_end: u32,
- // }
-
- // let mut ranges = Vec::<EditRange>::new();
-
- // for edit in buffer.edits_since::<Point>(&self.last_update_version) {
- // //This bit is extremely wrong, this is not where these row lines should come from
- // let head_start = edit.old.start.row.saturating_sub(expand_by);
- // let head_end = (edit.old.end.row + expand_by).min(head.summary().lines.row + 1);
-
- // let buffer_start = edit.new.start.row.saturating_sub(expand_by);
- // let buffer_end = (edit.new.end.row + expand_by).min(buffer.row_count());
-
- // if let Some(last_range) = ranges.last_mut() {
- // let head_distance = last_range.head_end.abs_diff(head_end);
- // let buffer_distance = last_range.buffer_end.abs_diff(buffer_end);
-
- // if head_distance <= combine_distance || buffer_distance <= combine_distance {
- // last_range.head_start = last_range.head_start.min(head_start);
- // last_range.head_end = last_range.head_end.max(head_end);
-
- // last_range.buffer_start = last_range.buffer_start.min(buffer_start);
- // last_range.buffer_end = last_range.buffer_end.max(buffer_end);
- // } else {
- // ranges.push(EditRange {
- // head_start,
- // head_end,
- // buffer_start,
- // buffer_end,
- // });
- // }
- // } else {
- // ranges.push(EditRange {
- // head_start,
- // head_end,
- // buffer_start,
- // buffer_end,
- // });
- // }
- // }
-
- // self.last_update_version = buffer.version().clone();
-
- // let mut new_hunks = SumTree::new();
- // let mut cursor = self.snapshot.tree.cursor::<HunkHeadEnd>();
-
- // for range in ranges {
- // let head_range = range.head_start..range.head_end;
- // let head_slice = head.slice_rows(head_range.clone());
- // let head_str = head_slice.to_string();
-
- // let buffer_range = range.buffer_start..range.buffer_end;
- // let buffer_slice = buffer.as_rope().slice_rows(buffer_range.clone());
- // let buffer_str = buffer_slice.to_string();
-
- // println!("diffing head {:?}, buffer {:?}", head_range, buffer_range);
-
- // let mut iter = match HunkIter::diff(head_str.as_bytes(), buffer_str.as_bytes()) {
- // Some(iter) => iter,
- // None => continue,
- // };
-
- // while let Some(hunk) = iter.next(buffer) {
- // println!("hunk");
- // let prefix = cursor.slice(&HunkHeadEnd(hunk.head_range.end), Bias::Right, buffer);
- // println!("prefix len: {}", prefix.iter().count());
- // new_hunks.extend(prefix.iter().cloned(), buffer);
-
- // new_hunks.push(hunk.clone(), buffer);
-
- // cursor.seek(&HunkHeadEnd(hunk.head_range.end), Bias::Right, buffer);
- // println!("item: {:?}", cursor.item());
- // if let Some(item) = cursor.item() {
- // if item.head_range.end <= hunk.head_range.end {
- // println!("skipping");
- // cursor.next(buffer);
- // }
- // }
- // }
- // }
-
- // new_hunks.extend(
- // cursor
- // .suffix(buffer)
- // .iter()
- // .map(|i| {
- // println!("extending with {i:?}");
- // i
- // })
- // .cloned(),
- // buffer,
- // );
- // drop(cursor);
-
- // self.snapshot.tree = new_hunks;
+ pub fn update(&mut self, head_text: &str, buffer: &text::BufferSnapshot) {
+ let buffer_string = buffer.as_rope().to_string();
+ let buffer_bytes = buffer_string.as_bytes();
+
+ let mut options = GitOptions::default();
+ options.context_lines(0);
+ let patch = match GitPatch::from_buffers(
+ head_text.as_bytes(),
+ None,
+ buffer_bytes,
+ None,
+ Some(&mut options),
+ ) {
+ Ok(patch) => patch,
+ Err(_) => todo!("This needs to be handled"),
+ };
+
+ let mut hunks = SumTree::<DiffHunk<Anchor>>::new();
+ let mut delta = 0i64;
+ for hunk_index in 0..patch.num_hunks() {
+ for line_index in 0..patch.num_lines_in_hunk(hunk_index).unwrap() {
+ let line = patch.line_in_hunk(hunk_index, line_index).unwrap();
+
+ let hunk = match line.origin_value() {
+ libgit::DiffLineType::Addition => {
+ let buffer_start = line.content_offset();
+ let buffer_end = buffer_start as usize + line.content().len();
+ let head_offset = (buffer_start - delta) as usize;
+ delta += line.content().len() as i64;
+ DiffHunk {
+ buffer_range: buffer.anchor_before(buffer_start as usize)
+ ..buffer.anchor_after(buffer_end),
+ head_range: head_offset..head_offset,
+ }
+ }
+
+ libgit::DiffLineType::Deletion => {
+ let head_start = line.content_offset();
+ let head_end = head_start as usize + line.content().len();
+ let buffer_offset = (head_start + delta) as usize;
+ delta -= line.content().len() as i64;
+ DiffHunk {
+ buffer_range: buffer.anchor_before(buffer_offset)
+ ..buffer.anchor_after(buffer_offset),
+ head_range: (head_start as usize)..head_end,
+ }
+ }
+
+ libgit::DiffLineType::AddEOFNL => todo!(),
+ libgit::DiffLineType::ContextEOFNL => todo!(),
+ libgit::DiffLineType::DeleteEOFNL => todo!(),
+
+ libgit::DiffLineType::FileHeader => continue,
+ libgit::DiffLineType::HunkHeader => continue,
+ libgit::DiffLineType::Binary => continue,
+
+ //We specifically tell git to not give us context lines
+ libgit::DiffLineType::Context => unreachable!(),
+ };
+
+ let mut combined = false;
+ hunks.update_last(
+ |last_hunk| {
+ if last_hunk.head_range.end == hunk.head_range.start {
+ last_hunk.head_range.end = hunk.head_range.end;
+ last_hunk.buffer_range.end = hunk.buffer_range.end;
+ combined = true;
+ }
+ },
+ buffer,
+ );
+ if !combined {
+ hunks.push(hunk, buffer);
+ }
+ }
+ }
+
+ self.snapshot.tree = hunks;
}
}