Allow customizing whether `FoldMap::unfold` treats ranges as inclusive

Antonio Scandurra created

Change summary

crates/editor/src/display_map.rs          |  5 +++--
crates/editor/src/display_map/fold_map.rs |  5 +++--
crates/editor/src/editor.rs               | 22 ++++++++++++++--------
3 files changed, 20 insertions(+), 12 deletions(-)

Detailed changes

crates/editor/src/display_map.rs 🔗

@@ -114,6 +114,7 @@ impl DisplayMap {
     pub fn unfold<T: ToOffset>(
         &mut self,
         ranges: impl IntoIterator<Item = Range<T>>,
+        inclusive: bool,
         cx: &mut ModelContext<Self>,
     ) {
         let snapshot = self.buffer.read(cx).snapshot(cx);
@@ -124,7 +125,7 @@ impl DisplayMap {
             .wrap_map
             .update(cx, |map, cx| map.sync(snapshot, edits, cx));
         self.block_map.read(snapshot, edits);
-        let (snapshot, edits) = fold_map.unfold(ranges);
+        let (snapshot, edits) = fold_map.unfold(ranges, inclusive);
         let (snapshot, edits) = self.tab_map.sync(snapshot, edits);
         let (snapshot, edits) = self
             .wrap_map
@@ -629,7 +630,7 @@ mod tests {
                     if rng.gen() && fold_count > 0 {
                         log::info!("unfolding ranges: {:?}", ranges);
                         map.update(cx, |map, cx| {
-                            map.unfold(ranges, cx);
+                            map.unfold(ranges, true, cx);
                         });
                     } else {
                         log::info!("folding ranges: {:?}", ranges);

crates/editor/src/display_map/fold_map.rs 🔗

@@ -140,13 +140,14 @@ impl<'a> FoldMapWriter<'a> {
     pub fn unfold<T: ToOffset>(
         &mut self,
         ranges: impl IntoIterator<Item = Range<T>>,
+        inclusive: bool,
     ) -> (FoldSnapshot, Vec<FoldEdit>) {
         let mut edits = Vec::new();
         let mut fold_ixs_to_delete = Vec::new();
         let buffer = self.0.buffer.lock().clone();
         for range in ranges.into_iter() {
             // Remove intersecting folds and add their ranges to edits that are passed to sync.
-            let mut folds_cursor = intersecting_folds(&buffer, &self.0.folds, range, true);
+            let mut folds_cursor = intersecting_folds(&buffer, &self.0.folds, range, inclusive);
             while let Some(fold) = folds_cursor.item() {
                 let offset_range = fold.0.start.to_offset(&buffer)..fold.0.end.to_offset(&buffer);
                 if offset_range.end > offset_range.start {
@@ -1282,7 +1283,7 @@ mod tests {
         assert_eq!(snapshot4.text(), "123a…c123456eee");
 
         let (mut writer, _, _) = map.write(buffer_snapshot.clone(), vec![]);
-        writer.unfold(Some(Point::new(0, 4)..Point::new(0, 5)));
+        writer.unfold(Some(Point::new(0, 4)..Point::new(0, 5)), true);
         let (snapshot5, _) = map.read(buffer_snapshot.clone(), vec![]);
         assert_eq!(snapshot5.text(), "123aaaaa\nbbbbbb\nccc123456eee");
     }

crates/editor/src/editor.rs 🔗

@@ -3123,7 +3123,7 @@ impl Editor {
         }
 
         self.start_transaction(cx);
-        self.unfold_ranges(unfold_ranges, cx);
+        self.unfold_ranges(unfold_ranges, true, cx);
         self.buffer.update(cx, |buffer, cx| {
             for (range, text) in edits {
                 buffer.edit([range], text, cx);
@@ -3226,7 +3226,7 @@ impl Editor {
         }
 
         self.start_transaction(cx);
-        self.unfold_ranges(unfold_ranges, cx);
+        self.unfold_ranges(unfold_ranges, true, cx);
         self.buffer.update(cx, |buffer, cx| {
             for (range, text) in edits {
                 buffer.edit([range], text, cx);
@@ -3748,7 +3748,7 @@ impl Editor {
                 to_unfold.push(selection.start..selection.end);
             }
         }
-        self.unfold_ranges(to_unfold, cx);
+        self.unfold_ranges(to_unfold, true, cx);
         self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
     }
 
@@ -5202,7 +5202,7 @@ impl Editor {
                 start..end
             })
             .collect::<Vec<_>>();
-        self.unfold_ranges(ranges, cx);
+        self.unfold_ranges(ranges, true, cx);
     }
 
     fn is_line_foldable(&self, display_map: &DisplaySnapshot, display_row: u32) -> bool {
@@ -5253,7 +5253,7 @@ impl Editor {
         self.fold_ranges(ranges, cx);
     }
 
-    fn fold_ranges<T: ToOffset>(
+    pub fn fold_ranges<T: ToOffset>(
         &mut self,
         ranges: impl IntoIterator<Item = Range<T>>,
         cx: &mut ViewContext<Self>,
@@ -5266,10 +5266,16 @@ impl Editor {
         }
     }
 
-    fn unfold_ranges<T: ToOffset>(&mut self, ranges: Vec<Range<T>>, cx: &mut ViewContext<Self>) {
-        if !ranges.is_empty() {
+    pub fn unfold_ranges<T: ToOffset>(
+        &mut self,
+        ranges: impl IntoIterator<Item = Range<T>>,
+        inclusive: bool,
+        cx: &mut ViewContext<Self>,
+    ) {
+        let mut ranges = ranges.into_iter().peekable();
+        if ranges.peek().is_some() {
             self.display_map
-                .update(cx, |map, cx| map.unfold(ranges, cx));
+                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
             self.request_autoscroll(Autoscroll::Fit, cx);
             cx.notify();
         }