Fix `WrapMap::clip_point` at the end of a soft-wrapped line

Antonio Scandurra and Nathan Sobo created

If that's the case and `Bias` is `Left` we clip to the last
character of the soft-wrapped line.

Co-Authored-By: Nathan Sobo <nathan@zed.dev>

Change summary

zed/src/editor/display_map.rs          |  8 ++++++++
zed/src/editor/display_map/wrap_map.rs | 11 ++++++++++-
2 files changed, 18 insertions(+), 1 deletion(-)

Detailed changes

zed/src/editor/display_map.rs 🔗

@@ -369,6 +369,14 @@ mod tests {
                 .collect::<String>(),
             " two \nthree four \nfive\nsix seven \neight"
         );
+        assert_eq!(
+            snapshot.clip_point(DisplayPoint::new(0, 8), Bias::Left),
+            DisplayPoint::new(0, 7)
+        );
+        assert_eq!(
+            snapshot.clip_point(DisplayPoint::new(0, 8), Bias::Right),
+            DisplayPoint::new(1, 0)
+        );
 
         buffer.update(&mut cx, |buffer, cx| {
             let ix = buffer.text().find("seven").unwrap();

zed/src/editor/display_map/wrap_map.rs 🔗

@@ -208,7 +208,16 @@ impl Snapshot {
         OutputPoint(cursor.sum_start().0 + (point.0 - cursor.seek_start().0))
     }
 
-    pub fn clip_point(&self, point: OutputPoint, bias: Bias) -> OutputPoint {
+    pub fn clip_point(&self, mut point: OutputPoint, bias: Bias) -> OutputPoint {
+        if bias == Bias::Left {
+            let mut cursor = self.transforms.cursor::<OutputPoint, ()>();
+            cursor.seek(&point, Bias::Right, &());
+            let transform = cursor.item().expect("invalid point");
+            if !transform.is_isomorphic() {
+                *point.column_mut() -= 1;
+            }
+        }
+
         self.to_output_point(self.input.clip_point(self.to_input_point(point), bias))
     }
 }