diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 329082e6751ab3a95a6fa42a0dc73b5d2f1e7ec4..bdfcef01ae06bbf13d5e07544d60e20674808c03 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -18126,6 +18126,13 @@ impl Editor { let mut to_fold = Vec::new(); let mut stack = vec![(0, snapshot.max_row().0, 1)]; + let row_ranges_to_keep: Vec> = self + .selections + .all::(cx) + .into_iter() + .map(|sel| sel.start.row..sel.end.row) + .collect(); + while let Some((mut start_row, end_row, current_level)) = stack.pop() { while start_row < end_row { match self @@ -18139,7 +18146,13 @@ impl Editor { if current_level < fold_at_level { stack.push((nested_start_row, nested_end_row, current_level + 1)); } else if current_level == fold_at_level { - to_fold.push(crease); + // Fold iff there is no selection completely contained within the fold region + if !row_ranges_to_keep.iter().any(|selection| { + selection.end >= nested_start_row + && selection.start <= nested_end_row + }) { + to_fold.push(crease); + } } start_row = nested_end_row + 1; @@ -18846,7 +18859,12 @@ impl Editor { ) { self.hide_mouse_cursor(HideMouseCursorOrigin::TypingAction, cx); let snapshot = self.snapshot(window, cx); - let hunks = snapshot.hunks_for_ranges(self.selections.ranges(cx)); + let hunks = snapshot.hunks_for_ranges( + self.selections + .all(cx) + .into_iter() + .map(|selection| selection.range()), + ); let mut ranges_by_buffer = HashMap::default(); self.transact(window, cx, |editor, _window, cx| { for hunk in hunks { diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index c01e585023d1eb49c1656c182117ad5cbf573087..a4ba25c5f16c7b82cc9ba3ef6a691287ed92e72e 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -1256,6 +1256,63 @@ fn test_fold_at_level(cx: &mut TestAppContext) { editor.display_text(cx), editor.buffer.read(cx).read(cx).text() ); + let (_, positions) = marked_text_ranges( + &" + class Foo: + # Hello! + + def a(): + print(1) + + def b(): + p«riˇ»nt(2) + + + class Bar: + # World! + + def a(): + «ˇprint(1) + + def b(): + print(2)» + + + " + .unindent(), + true, + ); + + editor.change_selections(SelectionEffects::default(), window, cx, |s| { + s.select_ranges(positions) + }); + + editor.fold_at_level(&FoldAtLevel(2), window, cx); + assert_eq!( + editor.display_text(cx), + " + class Foo: + # Hello! + + def a():⋯ + + def b(): + print(2) + + + class Bar: + # World! + + def a(): + print(1) + + def b(): + print(2) + + + " + .unindent(), + ); }); } diff --git a/crates/editor/src/selections_collection.rs b/crates/editor/src/selections_collection.rs index 517a9dc6391caa9c60b366a229c721daaeae8533..67f19810109698214339f48aaa59afe10be7c1b7 100644 --- a/crates/editor/src/selections_collection.rs +++ b/crates/editor/src/selections_collection.rs @@ -332,6 +332,9 @@ impl SelectionsCollection { self.all(cx).last().unwrap().clone() } + /// Returns a list of (potentially backwards!) ranges representing the selections. + /// Useful for test assertions, but prefer `.all()` instead. + #[cfg(any(test, feature = "test-support"))] pub fn ranges>( &self, cx: &mut App,