Report the end of the current row rather than the start of the next

Nathan Sobo and Antonio Scandurra created

Co-Authored-By: Antonio Scandurra <me@as-cii.com>

Change summary

zed/src/editor/buffer.rs      | 26 +++++++++++++++++++-------
zed/src/editor/display_map.rs | 25 +++++++++----------------
2 files changed, 28 insertions(+), 23 deletions(-)

Detailed changes

zed/src/editor/buffer.rs 🔗

@@ -1013,13 +1013,7 @@ impl Buffer {
     }
 
     pub fn line_len(&self, row: u32) -> u32 {
-        let row_start_offset = Point::new(row, 0).to_offset(self);
-        let row_end_offset = if row >= self.max_point().row {
-            self.len()
-        } else {
-            Point::new(row + 1, 0).to_offset(self) - 1
-        };
-        (row_end_offset - row_start_offset) as u32
+        self.content().line_len(row)
     }
 
     pub fn max_point(&self) -> Point {
@@ -1955,6 +1949,10 @@ impl Snapshot {
         self.visible_text.len()
     }
 
+    pub fn line_len(&self, row: u32) -> u32 {
+        self.content().line_len(row)
+    }
+
     pub fn text(&self) -> Rope {
         self.visible_text.clone()
     }
@@ -2087,10 +2085,24 @@ impl<'a> From<&'a Content<'a>> for Content<'a> {
 }
 
 impl<'a> Content<'a> {
+    fn max_point(&self) -> Point {
+        self.visible_text.max_point()
+    }
+
     fn len(&self) -> usize {
         self.fragments.extent::<usize>(&None)
     }
 
+    fn line_len(&self, row: u32) -> u32 {
+        let row_start_offset = Point::new(row, 0).to_offset(self);
+        let row_end_offset = if row >= self.max_point().row {
+            self.len()
+        } else {
+            Point::new(row + 1, 0).to_offset(self) - 1
+        };
+        (row_end_offset - row_start_offset) as u32
+    }
+
     fn summary_for_anchor(&self, anchor: &Anchor) -> TextSummary {
         let cx = Some(anchor.version.clone());
         let mut cursor = self.fragments.cursor::<VersionedOffset, usize>();

zed/src/editor/display_map.rs 🔗

@@ -118,10 +118,9 @@ impl DisplayMapSnapshot {
     }
 
     pub fn prev_row_boundary(&self, mut display_point: DisplayPoint) -> (DisplayPoint, Point) {
-        let mut point;
         loop {
             *display_point.column_mut() = 0;
-            point = display_point.to_buffer_point(self, Bias::Left);
+            let mut point = display_point.to_buffer_point(self, Bias::Left);
             point.column = 0;
             let next_display_point = point.to_display_point(self, Bias::Left);
             if next_display_point == display_point {
@@ -132,19 +131,10 @@ impl DisplayMapSnapshot {
     }
 
     pub fn next_row_boundary(&self, mut display_point: DisplayPoint) -> (DisplayPoint, Point) {
-        let max_point = self.max_point();
-        let mut point;
         loop {
-            *display_point.row_mut() += 1;
-            *display_point.column_mut() = 0;
-            point = display_point.to_buffer_point(self, Bias::Right);
-            if display_point >= max_point {
-                return (max_point, point);
-            }
-            if point.column > 0 {
-                point.row += 1;
-                point.column = 0;
-            }
+            *display_point.column_mut() = self.line_len(display_point.row());
+            let mut point = display_point.to_buffer_point(self, Bias::Right);
+            point.column = self.buffer_snapshot.line_len(point.row);
             let next_display_point = point.to_display_point(self, Bias::Right);
             if next_display_point == display_point {
                 return (display_point, point);
@@ -441,8 +431,11 @@ mod tests {
                 assert_eq!(prev_buffer_bound.column, 0);
                 assert_eq!(prev_display_bound.column(), 0);
                 if next_display_bound < snapshot.max_point() {
-                    assert_eq!(next_buffer_bound.column, 0);
-                    assert_eq!(next_display_bound.column(), 0);
+                    assert_eq!(
+                        buffer
+                            .read_with(&cx, |buffer, _| buffer.chars_at(next_buffer_bound).next()),
+                        Some('\n')
+                    )
                 }
 
                 assert_eq!(