Keep folds at cursor open for "fold at level" (#39396)
Closes #39308 Also fixes a possible bug in `apply_selected_diff_hunks()` caused by reversed selections. Release Notes: - Fixed "editor: fold at level" closing regions containing selections Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
This commit is contained in:
co-authored by
Conrad Irwin
parent
fd8bae9b72
commit
9aeb617a89
@@ -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<Range<u32>> = self
|
||||
.selections
|
||||
.all::<Point>(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 {
|
||||
|
||||
@@ -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(),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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<D: TextDimension + Ord + Sub<D, Output = D>>(
|
||||
&self,
|
||||
cx: &mut App,
|
||||
|
||||
Reference in New Issue
Block a user