WIP

Nathan Sobo created

Change summary

zed/src/editor/buffer/mod.rs | 75 +++++++++++++++++++++++++++++++++++--
1 file changed, 71 insertions(+), 4 deletions(-)

Detailed changes

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::<FragmentIdRef, FragmentTextSummary>();
-        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)
+    }
+}