From c7796331542f4355a392073e56807e1f74b532a4 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 29 Jul 2021 10:43:09 -0600 Subject: [PATCH] Make unfolding inclusive If the range *touches* the fold, we unfold. This was needed to fix the behavior for unfolding at the current selection position. Previously, there was some kind of translation issue that was allowing us to accidentally work the way we wanted without this. Co-Authored-By: Antonio Scandurra --- zed/src/editor.rs | 17 +++++++---------- zed/src/editor/display_map/fold_map.rs | 15 +++++++++++---- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/zed/src/editor.rs b/zed/src/editor.rs index 7977cba56ed2997f997b2e3c4050f39593ebe0a1..c36d0dad6c3e7df601ece37abdad5bf64cf992c2 100644 --- a/zed/src/editor.rs +++ b/zed/src/editor.rs @@ -1020,11 +1020,8 @@ impl Editor { // Cut the text from the selected rows and paste it at the start of the previous line. if display_rows.start != 0 { let start = Point::new(buffer_rows.start, 0).to_offset(buffer); - let end = Point::new( - buffer_rows.end - 1, - buffer.line_len(buffer_rows.end - 1), - ) - .to_offset(buffer); + let end = Point::new(buffer_rows.end - 1, buffer.line_len(buffer_rows.end - 1)) + .to_offset(buffer); let prev_row_display_start = DisplayPoint::new(display_rows.start - 1, 0); let prev_row_buffer_start = display_map.prev_row_boundary(prev_row_display_start).1; @@ -3842,25 +3839,25 @@ mod tests { view.update(cx, |view, cx| { view.split_selection_into_lines(&(), cx); - assert_eq!(view.text(cx), "aa…bbb\nccc…eeee\nfffff\nggggg\n…i"); + assert_eq!(view.text(cx), "aaaaa\nbbbbb\nccc…eeee\nfffff\nggggg\n…i"); assert_eq!( view.selection_ranges(cx), [ DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1), DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2), - DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0), - DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4) + DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0), + DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4) ] ); }); view.update(cx, |view, cx| { - view.select_display_ranges(&[DisplayPoint::new(4, 0)..DisplayPoint::new(0, 1)], cx) + view.select_display_ranges(&[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)], cx) .unwrap(); view.split_selection_into_lines(&(), cx); assert_eq!( view.text(cx), - "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\n…i" + "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii" ); assert_eq!( view.selection_ranges(cx), diff --git a/zed/src/editor/display_map/fold_map.rs b/zed/src/editor/display_map/fold_map.rs index bdc5523150fecd7920d03403d38326f250b5127a..b8ab39cce169e86c5ea4e83588d42aceaf005b8f 100644 --- a/zed/src/editor/display_map/fold_map.rs +++ b/zed/src/editor/display_map/fold_map.rs @@ -154,7 +154,7 @@ impl<'a> FoldMapWriter<'a> { let buffer = self.0.buffer.read(cx).snapshot(); for range in ranges.into_iter() { // Remove intersecting folds and add their ranges to edits that are passed to apply_edits. - let mut folds_cursor = intersecting_folds(&buffer, &self.0.folds, range); + let mut folds_cursor = intersecting_folds(&buffer, &self.0.folds, range, true); while let Some(fold) = folds_cursor.item() { let offset_range = fold.0.start.to_offset(&buffer)..fold.0.end.to_offset(&buffer); edits.push(buffer::Edit { @@ -590,7 +590,7 @@ impl Snapshot { where T: ToOffset, { - let mut folds = intersecting_folds(&self.buffer_snapshot, &self.folds, range); + let mut folds = intersecting_folds(&self.buffer_snapshot, &self.folds, range, false); iter::from_fn(move || { let item = folds.item().map(|f| &f.0); folds.next(&self.buffer_snapshot); @@ -722,6 +722,7 @@ fn intersecting_folds<'a, T>( buffer: &'a buffer::Snapshot, folds: &'a SumTree, range: Range, + inclusive: bool, ) -> FilterCursor<'a, impl 'a + Fn(&FoldSummary) -> bool, Fold, usize> where T: ToOffset, @@ -730,8 +731,14 @@ where let end = buffer.anchor_after(range.end.to_offset(buffer)); folds.filter::<_, usize>( move |summary| { - start.cmp(&summary.max_end, buffer).unwrap() == Ordering::Less - && end.cmp(&summary.min_start, buffer).unwrap() == Ordering::Greater + let start_cmp = start.cmp(&summary.max_end, buffer).unwrap(); + let end_cmp = end.cmp(&summary.min_start, buffer).unwrap(); + + if inclusive { + start_cmp <= Ordering::Equal && end_cmp >= Ordering::Equal + } else { + start_cmp == Ordering::Less && end_cmp == Ordering::Greater + } }, buffer, )