Get wrapping randomized test passing with wrap width as small as 0

Antonio Scandurra and Nathan Sobo created

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

Change summary

zed/src/editor/display_map/line_wrapper.rs | 14 +++++++++-----
zed/src/editor/display_map/tab_map.rs      |  2 +-
zed/src/editor/display_map/wrap_map.rs     | 16 +++++++++++++---
3 files changed, 23 insertions(+), 9 deletions(-)

Detailed changes

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

@@ -39,11 +39,15 @@ impl LineWrapper {
 
     pub fn wrap_line_without_shaping(&self, line: &str, wrap_width: f32) -> Vec<usize> {
         let mut width = 0.0;
-        let mut result = Vec::new();
+        let mut boundaries = Vec::new();
         let mut last_boundary_ix = 0;
         let mut last_boundary_width = 0.0;
         let mut prev_c = '\0';
         for (ix, c) in line.char_indices() {
+            if c == '\n' {
+                break;
+            }
+
             if self.is_boundary(prev_c, c) {
                 last_boundary_ix = ix;
                 last_boundary_width = width;
@@ -51,19 +55,19 @@ impl LineWrapper {
 
             let char_width = self.width_for_char(c);
             width += char_width;
-            if width > wrap_width {
+            if width > wrap_width && ix > *boundaries.last().unwrap_or(&0) {
                 if last_boundary_ix > 0 {
-                    result.push(last_boundary_ix);
+                    boundaries.push(last_boundary_ix);
                     width -= last_boundary_width;
                     last_boundary_ix = 0;
                 } else {
-                    result.push(ix);
+                    boundaries.push(ix);
                     width = char_width;
                 }
             }
             prev_c = c;
         }
-        result
+        boundaries
     }
 
     fn is_boundary(&self, prev: char, next: char) -> bool {

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

@@ -150,7 +150,7 @@ impl Snapshot {
         let input_start = self.input.to_output_offset(input_start);
         let input_end = self
             .input
-            .to_output_offset(self.to_input_point(range.end, Bias::Left).0);
+            .to_output_offset(self.to_input_point(range.end, Bias::Right).0);
         HighlightedChunks {
             fold_chunks: self.input.highlighted_chunks(input_start..input_end),
             column: expanded_char_column,

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

@@ -787,7 +787,7 @@ mod tests {
             let mut rng = StdRng::seed_from_u64(seed);
             let font_cache = cx.font_cache().clone();
             let font_system = cx.platform().fonts();
-            let wrap_width = rng.gen_range(100.0..=1000.0);
+            let wrap_width = rng.gen_range(0.0..=1000.0);
             let settings = Settings {
                 tab_size: rng.gen_range(1..=4),
                 buffer_font_family: font_cache.load_family(&["Helvetica"]).unwrap(),
@@ -800,11 +800,15 @@ mod tests {
             let buffer = cx.add_model(|cx| {
                 let len = rng.gen_range(0..10);
                 let text = RandomCharIter::new(&mut rng).take(len).collect::<String>();
-                log::info!("Initial buffer text: {:?} (len: {})", text, text.len());
                 Buffer::new(0, text, cx)
             });
             let (fold_map, folds_snapshot) = cx.read(|cx| FoldMap::new(buffer.clone(), cx));
             let (tab_map, tabs_snapshot) = TabMap::new(folds_snapshot.clone(), settings.tab_size);
+            log::info!(
+                "Unwrapped text (unexpanded tabs): {:?}",
+                folds_snapshot.text()
+            );
+            log::info!("Unwrapped text (expanded tabs): {:?}", tabs_snapshot.text());
             let wrap_map = cx.read(|cx| {
                 WrapMap::new(
                     tabs_snapshot.clone(),
@@ -825,18 +829,23 @@ mod tests {
 
             let snapshot = cx.read(|cx| wrap_map.sync(tabs_snapshot, Vec::new(), cx));
             let actual_text = snapshot.text();
-
             assert_eq!(
                 actual_text, expected_text,
                 "unwrapped text is: {:?}",
                 unwrapped_text
             );
+            log::info!("Wrapped text: {:?}", actual_text);
 
             let mut interpolated_snapshot = snapshot.clone();
             for _i in 0..operations {
                 buffer.update(&mut cx, |buffer, cx| buffer.randomly_mutate(&mut rng, cx));
                 let (folds_snapshot, edits) = cx.read(|cx| fold_map.read(cx));
+                log::info!(
+                    "Unwrapped text (unexpanded tabs): {:?}",
+                    folds_snapshot.text()
+                );
                 let (tabs_snapshot, edits) = tab_map.sync(folds_snapshot, edits);
+                log::info!("Unwrapped text (expanded tabs): {:?}", tabs_snapshot.text());
                 interpolated_snapshot.interpolate(tabs_snapshot.clone(), &edits);
                 interpolated_snapshot.check_invariants(&mut rng);
 
@@ -857,6 +866,7 @@ mod tests {
                     "unwrapped text is: {:?}",
                     unwrapped_text
                 );
+                log::info!("New wrapped text: {:?}", actual_text);
 
                 interpolated_snapshot = snapshot.clone();
             }