Compare anchors via their fragment and their offset within it

Max Brunsfeld , Nathan Sobo , and Antonio Scandurra created

Co-Authored-By: Nathan Sobo <nathan@zed.dev>
Co-Authored-By: Antonio Scandurra <me@as-cii.com>

Change summary

zed/src/editor/buffer.rs        | 23 ++++++++++++++++++-----
zed/src/editor/buffer/anchor.rs | 29 +++++++----------------------
2 files changed, 25 insertions(+), 27 deletions(-)

Detailed changes

zed/src/editor/buffer.rs 🔗

@@ -2030,22 +2030,28 @@ impl Buffer {
         }
     }
 
-    fn fragment_ix_for_anchor(&self, anchor: &Anchor) -> usize {
+    fn fragment_ix_for_anchor(&self, anchor: &Anchor) -> (usize, usize) {
         match anchor {
-            Anchor::Start => 0,
-            Anchor::End => self.fragments.extent::<FragmentCount>(&None).0,
+            Anchor::Start => (0, 0),
+            Anchor::End => (
+                self.fragments.extent::<FragmentCount>(&None).0,
+                self.fragments.last().map_or(0, |f| f.visible_len()),
+            ),
             Anchor::Middle {
                 offset,
                 bias,
                 version,
             } => {
-                let mut cursor = self.fragments.cursor::<VersionedOffset, FragmentCount>();
+                let mut cursor = self
+                    .fragments
+                    .cursor::<VersionedOffset, (VersionedOffset, FragmentCount)>();
                 cursor.seek(
                     &VersionedOffset::Offset(*offset),
                     bias.to_seek_bias(),
                     &Some(version.clone()),
                 );
-                cursor.start().0
+                let count = cursor.start().1;
+                (count.0, offset - cursor.start().0.offset())
             }
         }
     }
@@ -2666,6 +2672,13 @@ impl<'a> sum_tree::Dimension<'a, FragmentSummary> for (VersionedOffset, usize) {
     }
 }
 
+impl<'a> sum_tree::Dimension<'a, FragmentSummary> for (VersionedOffset, FragmentCount) {
+    fn add_summary(&mut self, summary: &'a FragmentSummary, cx: &Option<time::Global>) {
+        self.0.add_summary(summary, cx);
+        self.1 .0 += summary.count;
+    }
+}
+
 #[derive(Copy, Clone, Default, Debug, Eq, PartialEq, Ord, PartialOrd)]
 struct FragmentCount(usize);
 

zed/src/editor/buffer/anchor.rs 🔗

@@ -1,4 +1,4 @@
-use super::{Buffer, ToOffset};
+use super::Buffer;
 use crate::{sum_tree, time};
 use anyhow::Result;
 use std::{cmp::Ordering, ops::Range};
@@ -61,30 +61,15 @@ impl Anchor {
             (Anchor::End, _) | (_, Anchor::Start) => Ordering::Greater,
             (
                 Anchor::Middle {
-                    offset: self_offset,
-                    bias: self_bias,
-                    ..
+                    bias: self_bias, ..
                 },
                 Anchor::Middle {
-                    offset: other_offset,
-                    bias: other_bias,
-                    ..
+                    bias: other_bias, ..
                 },
-            ) => {
-                dbg!(
-                    self,
-                    other,
-                    self_offset,
-                    other_offset,
-                    buffer.fragment_ix_for_anchor(self),
-                    buffer.fragment_ix_for_anchor(other)
-                );
-                buffer
-                    .fragment_ix_for_anchor(self)
-                    .cmp(&buffer.fragment_ix_for_anchor(other))
-                    .then_with(|| self_offset.cmp(&other_offset))
-                    .then_with(|| self_bias.cmp(other_bias))
-            }
+            ) => buffer
+                .fragment_ix_for_anchor(self)
+                .cmp(&buffer.fragment_ix_for_anchor(other))
+                .then_with(|| self_bias.cmp(&other_bias)),
         })
     }