From be954872d0f9f240cf1806ddad5107e2cc171f90 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 15 Jul 2021 10:11:24 +0200 Subject: [PATCH] Calculate an `old_lines` range in `Edits` iterator --- zed/src/editor/buffer.rs | 124 ++++++++++++++----------- zed/src/editor/display_map/fold_map.rs | 50 +++++----- zed/src/editor/display_map/wrap_map.rs | 3 +- 3 files changed, 96 insertions(+), 81 deletions(-) diff --git a/zed/src/editor/buffer.rs b/zed/src/editor/buffer.rs index c0ce0af2d7..f4a79bed98 100644 --- a/zed/src/editor/buffer.rs +++ b/zed/src/editor/buffer.rs @@ -372,28 +372,39 @@ impl UndoMap { } struct Edits<'a, F: Fn(&FragmentSummary) -> bool> { + visible_text: &'a Rope, deleted_text: &'a Rope, cursor: FilterCursor<'a, F, Fragment, FragmentTextSummary>, undos: &'a UndoMap, since: time::Global, - delta: isize, + old_offset: usize, + new_offset: usize, + old_point: Point, + new_point: Point, } #[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct Edit { - pub old_range: Range, - pub new_range: Range, - pub old_lines: Point, + pub old_bytes: Range, + pub new_bytes: Range, + pub old_lines: Range, } impl Edit { pub fn delta(&self) -> isize { - (self.new_range.end - self.new_range.start) as isize - - (self.old_range.end - self.old_range.start) as isize + self.inserted_bytes() as isize - self.deleted_bytes() as isize } - pub fn old_extent(&self) -> usize { - self.old_range.end - self.old_range.start + pub fn deleted_bytes(&self) -> usize { + self.old_bytes.end - self.old_bytes.start + } + + pub fn inserted_bytes(&self) -> usize { + self.new_bytes.end - self.new_bytes.start + } + + pub fn deleted_lines(&self) -> Point { + self.old_lines.end - self.old_lines.start } } @@ -776,25 +787,21 @@ impl Buffer { if let Some(syntax_tree) = self.syntax_tree.lock().as_mut() { let mut edited = false; let mut delta = 0_isize; - for Edit { - old_range, - new_range, - old_lines, - } in self.edits_since(syntax_tree.version.clone()) - { - let start_offset = (old_range.start as isize + delta) as usize; + for edit in self.edits_since(syntax_tree.version.clone()) { + let start_offset = (edit.old_bytes.start as isize + delta) as usize; let start_point = self.visible_text.to_point(start_offset); - let old_bytes = old_range.end - old_range.start; - let new_bytes = new_range.end - new_range.start; syntax_tree.tree.edit(&InputEdit { start_byte: start_offset, - old_end_byte: start_offset + old_bytes, - new_end_byte: start_offset + new_bytes, + old_end_byte: start_offset + edit.deleted_bytes(), + new_end_byte: start_offset + edit.inserted_bytes(), start_position: start_point.into(), - old_end_position: (start_point + old_lines).into(), - new_end_position: self.visible_text.to_point(start_offset + new_bytes).into(), + old_end_position: (start_point + edit.deleted_lines()).into(), + new_end_position: self + .visible_text + .to_point(start_offset + edit.inserted_bytes()) + .into(), }); - delta += new_bytes as isize - old_bytes as isize; + delta += edit.inserted_bytes() as isize - edit.deleted_bytes() as isize; edited = true; } syntax_tree.parsed &= !edited; @@ -1051,11 +1058,15 @@ impl Buffer { ); Edits { + visible_text: &self.visible_text, deleted_text: &self.deleted_text, cursor, undos: &self.undo_map, since, - delta: 0, + old_offset: 0, + new_offset: 0, + old_point: Point::zero(), + new_point: Point::zero(), } } @@ -2089,45 +2100,53 @@ impl<'a, F: Fn(&FragmentSummary) -> bool> Iterator for Edits<'a, F> { let mut change: Option = None; while let Some(fragment) = self.cursor.item() { - let new_offset = self.cursor.start().visible; - let old_offset = (new_offset as isize - self.delta) as usize; + let bytes = self.cursor.start().visible - self.new_offset; + let lines = self.visible_text.to_point(self.cursor.start().visible) - self.new_point; + self.old_offset += bytes; + self.old_point += &lines; + self.new_offset += bytes; + self.new_point += &lines; if !fragment.was_visible(&self.since, &self.undos) && fragment.visible { + let fragment_lines = + self.visible_text.to_point(self.new_offset + fragment.len) - self.new_point; if let Some(ref mut change) = change { - if change.new_range.end == new_offset { - change.new_range.end += fragment.len; - self.delta += fragment.len as isize; + if change.new_bytes.end == self.new_offset { + change.new_bytes.end += fragment.len; } else { break; } } else { change = Some(Edit { - old_range: old_offset..old_offset, - new_range: new_offset..new_offset + fragment.len, - old_lines: Point::zero(), + old_bytes: self.old_offset..self.old_offset, + new_bytes: self.new_offset..self.new_offset + fragment.len, + old_lines: self.old_point..self.old_point, }); - self.delta += fragment.len as isize; } + + self.new_offset += fragment.len; + self.new_point += &fragment_lines; } else if fragment.was_visible(&self.since, &self.undos) && !fragment.visible { let deleted_start = self.cursor.start().deleted; - let old_lines = self.deleted_text.to_point(deleted_start + fragment.len) + let fragment_lines = self.deleted_text.to_point(deleted_start + fragment.len) - self.deleted_text.to_point(deleted_start); if let Some(ref mut change) = change { - if change.new_range.end == new_offset { - change.old_range.end += fragment.len; - change.old_lines += &old_lines; - self.delta -= fragment.len as isize; + if change.new_bytes.end == self.new_offset { + change.old_bytes.end += fragment.len; + change.old_lines.end += &fragment_lines; } else { break; } } else { change = Some(Edit { - old_range: old_offset..old_offset + fragment.len, - new_range: new_offset..new_offset, - old_lines, + old_bytes: self.old_offset..self.old_offset + fragment.len, + new_bytes: self.new_offset..self.new_offset, + old_lines: self.old_point..self.old_point + &fragment_lines, }); - self.delta -= fragment.len as isize; } + + self.old_offset += fragment.len; + self.old_point += &fragment_lines; } self.cursor.next(&None); @@ -2898,19 +2917,16 @@ mod tests { ); let mut delta = 0_isize; - for Edit { - old_range, - new_range, - .. - } in edits - { - let old_len = old_range.end - old_range.start; - let new_len = new_range.end - new_range.start; - let old_start = (old_range.start as isize + delta) as usize; - let new_text: String = buffer.text_for_range(new_range).collect(); - old_buffer.edit(Some(old_start..old_start + old_len), new_text, cx); - - delta += new_len as isize - old_len as isize; + for edit in edits { + let old_start = (edit.old_bytes.start as isize + delta) as usize; + let new_text: String = + buffer.text_for_range(edit.new_bytes.clone()).collect(); + old_buffer.edit( + Some(old_start..old_start + edit.deleted_bytes()), + new_text, + cx, + ); + delta += edit.delta(); } assert_eq!(old_buffer.text(), buffer.text()); } diff --git a/zed/src/editor/display_map/fold_map.rs b/zed/src/editor/display_map/fold_map.rs index 1024dc545e..3b357970e5 100644 --- a/zed/src/editor/display_map/fold_map.rs +++ b/zed/src/editor/display_map/fold_map.rs @@ -106,8 +106,8 @@ impl FoldMap { let fold = Fold(buffer.anchor_after(range.start)..buffer.anchor_before(range.end)); folds.push(fold); edits.push(Edit { - old_range: range.clone(), - new_range: range.clone(), + old_bytes: range.clone(), + new_bytes: range.clone(), ..Default::default() }); } @@ -115,10 +115,10 @@ impl FoldMap { folds.sort_unstable_by(|a, b| sum_tree::SeekDimension::cmp(a, b, buffer)); edits.sort_unstable_by(|a, b| { - a.old_range + a.old_bytes .start - .cmp(&b.old_range.start) - .then_with(|| b.old_range.end.cmp(&a.old_range.end)) + .cmp(&b.old_bytes.start) + .then_with(|| b.old_bytes.end.cmp(&a.old_bytes.end)) }); self.folds = { @@ -151,8 +151,8 @@ impl FoldMap { while let Some(fold) = folds_cursor.item() { let offset_range = fold.0.start.to_offset(buffer)..fold.0.end.to_offset(buffer); edits.push(Edit { - old_range: offset_range.clone(), - new_range: offset_range, + old_bytes: offset_range.clone(), + new_bytes: offset_range, ..Default::default() }); fold_ixs_to_delete.push(*folds_cursor.start()); @@ -163,10 +163,10 @@ impl FoldMap { fold_ixs_to_delete.sort_unstable(); fold_ixs_to_delete.dedup(); edits.sort_unstable_by(|a, b| { - a.old_range + a.old_bytes .start - .cmp(&b.old_range.start) - .then_with(|| b.old_range.end.cmp(&a.old_range.end)) + .cmp(&b.old_bytes.start) + .then_with(|| b.old_bytes.end.cmp(&a.old_bytes.end)) }); self.folds = { @@ -278,28 +278,28 @@ impl FoldMap { cursor.seek(&0, Bias::Right, &()); while let Some(mut edit) = edits.next() { - new_transforms.push_tree(cursor.slice(&edit.old_range.start, Bias::Left, &()), &()); - edit.new_range.start -= edit.old_range.start - cursor.seek_start(); - edit.old_range.start = *cursor.seek_start(); + new_transforms.push_tree(cursor.slice(&edit.old_bytes.start, Bias::Left, &()), &()); + edit.new_bytes.start -= edit.old_bytes.start - cursor.seek_start(); + edit.old_bytes.start = *cursor.seek_start(); - cursor.seek(&edit.old_range.end, Bias::Right, &()); + cursor.seek(&edit.old_bytes.end, Bias::Right, &()); cursor.next(&()); let mut delta = edit.delta(); loop { - edit.old_range.end = *cursor.seek_start(); + edit.old_bytes.end = *cursor.seek_start(); if let Some(next_edit) = edits.peek() { - if next_edit.old_range.start > edit.old_range.end { + if next_edit.old_bytes.start > edit.old_bytes.end { break; } let next_edit = edits.next().unwrap(); delta += next_edit.delta(); - if next_edit.old_range.end >= edit.old_range.end { - edit.old_range.end = next_edit.old_range.end; - cursor.seek(&edit.old_range.end, Bias::Right, &()); + if next_edit.old_bytes.end >= edit.old_bytes.end { + edit.old_bytes.end = next_edit.old_bytes.end; + cursor.seek(&edit.old_bytes.end, Bias::Right, &()); cursor.next(&()); } } else { @@ -307,10 +307,10 @@ impl FoldMap { } } - edit.new_range.end = - ((edit.new_range.start + edit.old_extent()) as isize + delta) as usize; + edit.new_bytes.end = + ((edit.new_bytes.start + edit.deleted_bytes()) as isize + delta) as usize; - let anchor = buffer.anchor_before(edit.new_range.start); + let anchor = buffer.anchor_before(edit.new_bytes.start); let mut folds_cursor = self.folds.cursor::<_, ()>(); folds_cursor.seek(&Fold(anchor..Anchor::max()), Bias::Left, buffer); let mut folds = iter::from_fn(move || { @@ -324,7 +324,7 @@ impl FoldMap { while folds .peek() - .map_or(false, |fold| fold.start < edit.new_range.end) + .map_or(false, |fold| fold.start < edit.new_bytes.end) { let mut fold = folds.next().unwrap(); let sum = new_transforms.summary(); @@ -380,9 +380,9 @@ impl FoldMap { } let sum = new_transforms.summary(); - if sum.buffer.bytes < edit.new_range.end { + if sum.buffer.bytes < edit.new_bytes.end { let text_summary = - buffer.text_summary_for_range(sum.buffer.bytes..edit.new_range.end); + buffer.text_summary_for_range(sum.buffer.bytes..edit.new_bytes.end); new_transforms.push( Transform { summary: TransformSummary { diff --git a/zed/src/editor/display_map/wrap_map.rs b/zed/src/editor/display_map/wrap_map.rs index be8013ba4f..1fa5aa5e3a 100644 --- a/zed/src/editor/display_map/wrap_map.rs +++ b/zed/src/editor/display_map/wrap_map.rs @@ -117,9 +117,8 @@ impl BackgroundWrapper { { let mut old_cursor = self.snapshot.transforms.cursor::(); for edit in buffer.edits_since(self.snapshot.version.clone()) { - // TODO: old lines gives us an extent but we really want to park ourselves at the start of the line. new_transforms.push_tree( - old_cursor.slice(&Point::new(edit.old_lines.row, 0), Bias::Left, &()), + old_cursor.slice(&Point::new(edit.old_lines.start.row, 0), Bias::Left, &()), &(), ); }