diff --git a/zed/src/editor/buffer/mod.rs b/zed/src/editor/buffer/mod.rs index 5538f6474f5ef21d0e4d134537ed33bf120dde24..633d0e8a525ab1972518d174eb7475030fc915a6 100644 --- a/zed/src/editor/buffer/mod.rs +++ b/zed/src/editor/buffer/mod.rs @@ -1020,14 +1020,16 @@ impl Buffer { let old_visible_text = self.visible_text.clone(); let old_deleted_text = self.deleted_text.clone(); + let mut builder = RopeBuilder::new(old_visible_text.cursor(0), new_visible_text.cursor(0)); let mut fragments_cursor = old_fragments.cursor::(); - let mut visible_text_cursor = old_visible_text.cursor(0); - let mut deleted_text_cursor = old_deleted_text.cursor(0); let mut new_fragments = fragments_cursor.slice(&FragmentIdRef::new(&start_fragment_id), SeekBias::Left, &()); - let mut new_visible_text = visible_text_cursor.slice(fragments_cursor.start().visible); - let mut new_deleted_text = deleted_text_cursor.slice(fragments_cursor.start().deleted); + + builder.keep_to( + new_fragments.summary().text.visible, + new_fragments.summary().text.deleted, + ); let start_fragment = fragments_cursor.item().unwrap(); if start_offset == start_fragment.range_in_insertion.end { @@ -3509,3 +3511,68 @@ mod tests { lengths } } + +struct RopeBuilder<'a> { + visible_delta: isize, + deleted_delta: isize, + old_visible_cursor: rope::Cursor<'a>, + old_deleted_cursor: rope::Cursor<'a>, + new_visible: Rope, + new_deleted: Rope, +} + +impl<'a> RopeBuilder<'a> { + fn new(old_visible_cursor: rope::Cursor<'a>, old_deleted_cursor: rope::Cursor<'a>) -> Self { + Self { + visible_delta: 0, + deleted_delta: 0, + old_visible_cursor, + old_deleted_cursor, + new_visible: Rope::new(), + new_deleted: Rope::new(), + } + } + + fn keep_to(&mut self, sum: FragmentTextSummary) { + self.new_visible.append( + self.old_visible_cursor + .slice((sum.visible as isize + self.visible_delta) as usize), + ); + self.new_deleted.append( + self.old_deleted_cursor + .slice((sum.deleted as isize + self.deleted_delta) as usize), + ); + } + + fn delete_to(&mut self, offset: usize) { + let deleted = self + .old_visible_cursor + .slice((offset as isize + self.visible_delta) as usize); + let deleted_len = deleted.len(); + self.new_deleted.append(deleted); + self.visible_delta += deleted_len as isize; + self.deleted_delta -= deleted_len as isize; + } + + fn restore_to(&mut self, offset: usize) { + let restored = self + .old_deleted_cursor + .slice((offset as isize + self.deleted_delta) as usize); + let restored_len = restored.len(); + self.new_visible.append(restored); + self.visible_delta -= restored_len as isize; + self.deleted_delta += restored_len as isize; + } + + fn insert(&mut self, text: &str) { + let old_len = self.new_visible.len(); + self.new_visible.push(text); + self.visible_delta -= (self.new_visible.len() - old_len) as isize; + } + + fn finish(self) -> (Rope, Rope) { + self.new_visible.append(self.old_visible_cursor.suffix()); + self.new_deleted.append(self.old_deleted_cursor.suffix()); + (self.new_visible, self.new_deleted) + } +}