wip

Max Brunsfeld created

Change summary

zed/src/editor/buffer.rs | 327 +++++++++++++++++++++++------------------
1 file changed, 186 insertions(+), 141 deletions(-)

Detailed changes

zed/src/editor/buffer.rs 🔗

@@ -341,6 +341,7 @@ struct Fragment {
     id: FragmentId,
     insertion: Arc<Insertion>,
     range_in_insertion: Range<usize>,
+    len: usize,
     deletions: HashSet<time::Local>,
     max_undos: time::Global,
     visible: bool,
@@ -399,11 +400,8 @@ pub enum Operation {
 #[derive(Clone, Debug, Eq, PartialEq)]
 pub struct EditOperation {
     id: time::Local,
-    start_id: time::Local,
-    start_offset: usize,
-    end_id: time::Local,
-    end_offset: usize,
-    version_in_range: time::Global,
+    version: time::Global,
+    ranges: Vec<Range<usize>>,
     new_text: Option<String>,
 }
 
@@ -1130,12 +1128,9 @@ impl Buffer {
             } => {
                 if !self.version.observed(edit.id) {
                     self.apply_edit(
-                        edit.start_id,
-                        edit.start_offset,
-                        edit.end_id,
-                        edit.end_offset,
+                        edit.version,
+                        edit.ranges,
                         edit.new_text.as_deref(),
-                        &edit.version_in_range,
                         edit.id,
                         lamport_timestamp,
                     )?;
@@ -1172,148 +1167,73 @@ impl Buffer {
 
     fn apply_edit(
         &mut self,
-        start_id: time::Local,
-        start_offset: usize,
-        end_id: time::Local,
-        end_offset: usize,
+        version: time::Global,
+        ranges: Vec<Range<usize>>,
         mut new_text: Option<&str>,
-        version_in_range: &time::Global,
         local_timestamp: time::Local,
         lamport_timestamp: time::Lamport,
     ) -> Result<()> {
-        let start_fragment_id = self.resolve_fragment_id(start_id, start_offset)?;
-        let end_fragment_id = self.resolve_fragment_id(end_id, end_offset)?;
-
-        let mut old_visible_text = Rope::new();
-        let mut old_deleted_text = Rope::new();
-        let mut old_fragments = SumTree::new();
-        mem::swap(&mut old_visible_text, &mut self.visible_text);
-        mem::swap(&mut old_deleted_text, &mut self.deleted_text);
-        mem::swap(&mut old_fragments, &mut self.fragments);
+        let mut old_visible_text = mem::take(&mut self.visible_text);
+        let mut old_deleted_text = mem::take(&mut self.deleted_text);
+        let mut old_fragments = mem::take(&mut self.fragments);
+        let mut old_fragments = old_fragments.cursor::<VersionedOffset, VersionedOffset>();
 
-        let mut fragments_cursor = old_fragments.cursor::<FragmentIdRef, FragmentTextSummary>();
+        let version = Some(version);
 
-        let mut new_fragments = fragments_cursor.slice(
-            &FragmentIdRef::new(&start_fragment_id),
-            SeekBias::Left,
-            &None,
-        );
+        let mut new_fragments = SumTree::new();
         let mut new_ropes =
             RopeBuilder::new(old_visible_text.cursor(0), old_deleted_text.cursor(0));
-        new_ropes.push_tree(new_fragments.summary().text);
-
-        let start_fragment = fragments_cursor.item().unwrap();
-        if start_offset == start_fragment.range_in_insertion.end {
-            let fragment = fragments_cursor.item().unwrap().clone();
-            new_ropes.push_fragment(&fragment, fragment.visible);
-            new_fragments.push(fragment, &None);
-            fragments_cursor.next(&None);
-        }
-
-        while let Some(fragment) = fragments_cursor.item() {
-            if new_text.is_none() && fragment.id > end_fragment_id {
-                break;
-            }
-
-            let mut fragment = fragment.clone();
-
-            if fragment.id == start_fragment_id || fragment.id == end_fragment_id {
-                let split_start = if start_fragment_id == fragment.id {
-                    start_offset
-                } else {
-                    fragment.range_in_insertion.start
-                };
-                let split_end = if end_fragment_id == fragment.id {
-                    end_offset
-                } else {
-                    fragment.range_in_insertion.end
-                };
-                let (before_range, within_range, after_range) = self.split_fragment(
-                    fragments_cursor.prev_item().as_ref().unwrap(),
-                    &fragment,
-                    split_start..split_end,
-                );
-                let insertion = if let Some(new_text) = new_text {
-                    let prev_fragment = fragments_cursor.prev_item();
-                    Some(self.build_fragment_to_insert(
-                        before_range.as_ref().or(prev_fragment).unwrap(),
-                        within_range.as_ref().or(after_range.as_ref()),
-                        new_text,
-                        local_timestamp,
-                        lamport_timestamp,
-                    ))
-                } else {
-                    None
-                };
-                if let Some(fragment) = before_range {
-                    new_ropes.push_fragment(&fragment, fragment.visible);
-                    new_fragments.push(fragment, &None);
-                }
-                if let Some(fragment) = insertion {
-                    new_ropes.push_str(new_text.take().unwrap());
-                    new_fragments.push(fragment, &None);
-                }
-                if let Some(mut fragment) = within_range {
-                    let fragment_was_visible = fragment.visible;
-                    if fragment.was_visible(&version_in_range, &self.undo_map) {
-                        fragment.deletions.insert(local_timestamp);
-                        if fragment.visible {
-                            fragment.visible = false;
-                        }
-                    }
+        let mut pending_fragment = None;
+        let mut pending_fragment_start_offset = 0;
+
+        for range in ranges {
+            let preceding_fragments = old_fragments.slice(
+                &VersionedOffset::Offset(range.start),
+                SeekBias::Right,
+                &version,
+            );
+            new_fragments.push_tree(preceding_fragments, &None);
+            new_ropes.push_tree(new_fragments.summary().text);
 
-                    new_ropes.push_fragment(&fragment, fragment_was_visible);
-                    new_fragments.push(fragment, &None);
-                }
-                if let Some(fragment) = after_range {
-                    new_ropes.push_fragment(&fragment, fragment.visible);
-                    new_fragments.push(fragment, &None);
-                }
+            let mut fragment_start_offset = old_fragments.start().offset();
+            let mut fragment_end_offset = old_fragments.end(&version).offset();
+            let mut fragment = if let Some(fragment) = old_fragments.item() {
+                fragment.clone()
             } else {
-                if new_text.is_some() && lamport_timestamp > fragment.insertion.lamport_timestamp {
-                    let new_text = new_text.take().unwrap();
-                    let fragment = self.build_fragment_to_insert(
-                        fragments_cursor.prev_item().as_ref().unwrap(),
-                        Some(&fragment),
-                        new_text,
-                        local_timestamp,
-                        lamport_timestamp,
-                    );
-                    new_ropes.push_str(new_text);
-                    new_fragments.push(fragment, &None);
-                }
+                todo!()
+            };
 
-                let fragment_was_visible = fragment.visible;
-                if fragment.id < end_fragment_id
-                    && fragment.was_visible(&version_in_range, &self.undo_map)
-                {
-                    fragment.deletions.insert(local_timestamp);
-                    if fragment.visible {
-                        fragment.visible = false;
-                    }
-                }
+            if fragment_start_offset < range.start {
+                let prefix_fragment = Fragment {
+                    len: range.start - fragment_start_offset,
+                    visible: fragment.visible,
+                    deletions: fragment.deletions.clone(),
+                    max_undos: fragment.max_undos.clone(),
+
+                    // TODO - remove
+                    id: fragment.id.clone(),
+                    insertion: fragment.insertion.clone(),
+                    range_in_insertion: Default::default(),
+                };
 
-                new_ropes.push_fragment(&fragment, fragment_was_visible);
-                new_fragments.push(fragment, &None);
+                new_ropes.push_fragment(&prefix_fragment, prefix_fragment.visible);
+                new_fragments.push(prefix_fragment, &None);
+                fragment.len -= prefix_fragment.len;
             }
 
-            fragments_cursor.next(&None);
-        }
+            let suffix_fragment = if fragment_end_offset > range.end {
+                fragment.visible = false;
 
-        if let Some(new_text) = new_text {
-            let fragment = self.build_fragment_to_insert(
-                fragments_cursor.prev_item().as_ref().unwrap(),
-                None,
-                new_text,
-                local_timestamp,
-                lamport_timestamp,
-            );
-            new_ropes.push_str(new_text);
-            new_fragments.push(fragment, &None);
+                //
+
+                Some(Fragment {});
+            } else {
+                None
+            };
         }
 
         let (visible_text, deleted_text) = new_ropes.finish();
-        new_fragments.push_tree(fragments_cursor.suffix(&None), &None);
+        new_fragments.push_tree(old_fragments.suffix(&None), &None);
 
         self.fragments = new_fragments;
         self.visible_text = visible_text;
@@ -1323,6 +1243,134 @@ impl Buffer {
         Ok(())
     }
 
+    //     let mut new_fragments = fragments_cursor.slice(
+    //     &VersionedOffset::Offset(range.start),
+    //     SeekBias::Left,
+    //     &version_cx,
+    // );
+    // new_ropes.push_tree(new_fragments.summary().text);
+
+    // if range.start == fragments_cursor.end(&version_cx).offset() {
+    //     let fragment = fragments_cursor.item().unwrap().clone();
+    //     new_ropes.push_fragment(&fragment, fragment.visible);
+    //     new_fragments.push(fragment, &None);
+    //     fragments_cursor.next(&None);
+    // }
+
+    // while let Some(fragment) = fragments_cursor.item() {
+    //     let fragment_start_offset = fragments_cursor.start().offset();
+    //     let fragment_end_offset = fragments_cursor.end(&version_cx).offset();
+
+    //     if new_text.is_none() && fragment_start_offset > range.end {
+    //         break;
+    //     }
+
+    //     if fragment_start_offset
+
+    // if cursor_start_offset < range.start || cursor_end_offset > range.end {
+    //     let split_start = if start_fragment_id == fragment.id {
+    //         start_offset
+    //     } else {
+    //         fragment.range_in_insertion.start
+    //     };
+    //     let split_end = if end_fragment_id == fragment.id {
+    //         end_offset
+    //     } else {
+    //         fragment.range_in_insertion.end
+    //     };
+    //     let (before_range, within_range, after_range) = self.split_fragment(
+    //         fragments_cursor.prev_item().as_ref().unwrap(),
+    //         &fragment,
+    //         split_start..split_end,
+    //     );
+    //     let insertion = if let Some(new_text) = new_text {
+    //         let prev_fragment = fragments_cursor.prev_item();
+    //         Some(self.build_fragment_to_insert(
+    //             before_range.as_ref().or(prev_fragment).unwrap(),
+    //             within_range.as_ref().or(after_range.as_ref()),
+    //             new_text,
+    //             local_timestamp,
+    //             lamport_timestamp,
+    //         ))
+    //     } else {
+    //         None
+    //     };
+    //     if let Some(fragment) = before_range {
+    //         new_ropes.push_fragment(&fragment, fragment.visible);
+    //         new_fragments.push(fragment, &None);
+    //     }
+    //     if let Some(fragment) = insertion {
+    //         new_ropes.push_str(new_text.take().unwrap());
+    //         new_fragments.push(fragment, &None);
+    //     }
+    //     if let Some(mut fragment) = within_range {
+    //         let fragment_was_visible = fragment.visible;
+    //         if fragment.was_visible(&version_in_range, &self.undo_map) {
+    //             fragment.deletions.insert(local_timestamp);
+    //             if fragment.visible {
+    //                 fragment.visible = false;
+    //             }
+    //         }
+    //         new_ropes.push_fragment(&fragment, fragment_was_visible);
+    //         new_fragments.push(fragment, &None);
+    //     }
+    //     if let Some(fragment) = after_range {
+    //         new_ropes.push_fragment(&fragment, fragment.visible);
+    //         new_fragments.push(fragment, &None);
+    //     }
+    // } else {
+    //     if new_text.is_some() && lamport_timestamp > fragment.insertion.lamport_timestamp {
+    //         let new_text = new_text.take().unwrap();
+    //         let fragment = self.build_fragment_to_insert(
+    //             fragments_cursor.prev_item().as_ref().unwrap(),
+    //             Some(&fragment),
+    //             new_text,
+    //             local_timestamp,
+    //             lamport_timestamp,
+    //         );
+    //         new_ropes.push_str(new_text);
+    //         new_fragments.push(fragment, &None);
+    //     }
+
+    //     let fragment_was_visible = fragment.visible;
+    //     if fragment.id < end_fragment_id
+    //         && fragment.was_visible(&version_in_range, &self.undo_map)
+    //     {
+    //         fragment.deletions.insert(local_timestamp);
+    //         if fragment.visible {
+    //             fragment.visible = false;
+    //         }
+    //     }
+
+    //     new_ropes.push_fragment(&fragment, fragment_was_visible);
+    //     new_fragments.push(fragment, &None);
+    // }
+    // fragments_cursor.next(&None);
+    // }
+
+    // if let Some(new_text) = new_text {
+    //     let fragment = self.build_fragment_to_insert(
+    //         fragments_cursor.prev_item().as_ref().unwrap(),
+    //         None,
+    //         new_text,
+    //         local_timestamp,
+    //         lamport_timestamp,
+    //     );
+    //     new_ropes.push_str(new_text);
+    //     new_fragments.push(fragment, &None);
+    // }
+
+    // let (visible_text, deleted_text) = new_ropes.finish();
+    // new_fragments.push_tree(fragments_cursor.suffix(&None), &None);
+
+    // self.fragments = new_fragments;
+    // self.visible_text = visible_text;
+    // self.deleted_text = deleted_text;
+    // self.local_clock.observe(local_timestamp);
+    // self.lamport_clock.observe(lamport_timestamp);
+    // Ok(())
+    // }
+
     pub fn undo(&mut self, mut cx: Option<&mut ModelContext<Self>>) -> Vec<Operation> {
         let was_dirty = self.is_dirty();
         let old_version = self.version.clone();
@@ -1548,6 +1596,7 @@ impl Buffer {
             return Vec::new();
         }
 
+        let version = &self.version;
         let mut ops = Vec::with_capacity(old_ranges.size_hint().0);
 
         let mut old_fragments = SumTree::new();
@@ -1682,11 +1731,8 @@ impl Buffer {
                     ops.push(Operation::Edit {
                         edit: EditOperation {
                             id: local_timestamp,
-                            start_id: start_id.unwrap(),
-                            start_offset: start_offset.unwrap(),
-                            end_id: end_id.unwrap(),
-                            end_offset: end_offset.unwrap(),
-                            version_in_range,
+                            version,
+                            range,
                             new_text: new_text.clone(),
                         },
                         lamport_timestamp,
@@ -2047,8 +2093,7 @@ impl Buffer {
                     &Some(version.clone()),
                 );
                 let full_offset = cursor.start().1;
-                let visible_offset = cursor.start().0.offset();
-                full_offset.0 + offset - visible_offset
+                full_offset.0 + offset - cursor.start().0.offset()
             }
         }
     }