Detailed changes
@@ -310,6 +310,11 @@
"ctrl-shift-\\": "editor::MoveToEnclosingBracket",
"ctrl-shift-[": "editor::Fold",
"ctrl-shift-]": "editor::UnfoldLines",
+ "ctrl-k ctrl-l": "editor::ToggleFold",
+ "ctrl-k ctrl-[": "editor::FoldRecursive",
+ "ctrl-k ctrl-]": "editor::UnfoldRecursive",
+ "ctrl-k ctrl-0": "editor::FoldAll",
+ "ctrl-k ctrl-j": "editor::UnfoldAll",
"ctrl-space": "editor::ShowCompletions",
"ctrl-.": "editor::ToggleCodeActions",
"alt-ctrl-r": "editor::RevealInFileManager",
@@ -347,6 +347,11 @@
"cmd-shift-\\": "editor::MoveToEnclosingBracket",
"alt-cmd-[": "editor::Fold",
"alt-cmd-]": "editor::UnfoldLines",
+ "cmd-k cmd-l": "editor::ToggleFold",
+ "cmd-k cmd-[": "editor::FoldRecursive",
+ "cmd-k cmd-]": "editor::UnfoldRecursive",
+ "cmd-k cmd-0": "editor::FoldAll",
+ "cmd-k cmd-j": "editor::UnfoldAll",
"ctrl-space": "editor::ShowCompletions",
"cmd-.": "editor::ToggleCodeActions",
"alt-cmd-r": "editor::RevealInFileManager",
@@ -132,9 +132,15 @@
"z z": "editor::ScrollCursorCenter",
"z .": ["workspace::SendKeystrokes", "z z ^"],
"z b": "editor::ScrollCursorBottom",
+ "z a": "editor::ToggleFold",
+ "z A": "editor::ToggleFoldRecursive",
"z c": "editor::Fold",
+ "z C": "editor::FoldRecursive",
"z o": "editor::UnfoldLines",
+ "z O": "editor::UnfoldRecursive",
"z f": "editor::FoldSelectedRanges",
+ "z M": "editor::FoldAll",
+ "z R": "editor::UnfoldAll",
"shift-z shift-q": ["pane::CloseActiveItem", { "saveIntent": "skip" }],
"shift-z shift-z": ["pane::CloseActiveItem", { "saveIntent": "saveAll" }],
// Count support
@@ -230,7 +230,11 @@ gpui::actions!(
ExpandMacroRecursively,
FindAllReferences,
Fold,
+ FoldAll,
+ FoldRecursive,
FoldSelectedRanges,
+ ToggleFold,
+ ToggleFoldRecursive,
Format,
GoToDeclaration,
GoToDeclarationSplit,
@@ -340,7 +344,9 @@ gpui::actions!(
Transpose,
Undo,
UndoSelection,
+ UnfoldAll,
UnfoldLines,
+ UnfoldRecursive,
UniqueLinesCaseInsensitive,
UniqueLinesCaseSensitive,
]
@@ -10551,17 +10551,79 @@ impl Editor {
}
}
- pub fn fold(&mut self, _: &actions::Fold, cx: &mut ViewContext<Self>) {
- let mut fold_ranges = Vec::new();
+ pub fn toggle_fold(&mut self, _: &actions::ToggleFold, cx: &mut ViewContext<Self>) {
+ let selection = self.selections.newest::<Point>(cx);
+
+ let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
+ let range = if selection.is_empty() {
+ let point = selection.head().to_display_point(&display_map);
+ let start = DisplayPoint::new(point.row(), 0).to_point(&display_map);
+ let end = DisplayPoint::new(point.row(), display_map.line_len(point.row()))
+ .to_point(&display_map);
+ start..end
+ } else {
+ selection.range()
+ };
+ if display_map.folds_in_range(range).next().is_some() {
+ self.unfold_lines(&Default::default(), cx)
+ } else {
+ self.fold(&Default::default(), cx)
+ }
+ }
+
+ pub fn toggle_fold_recursive(
+ &mut self,
+ _: &actions::ToggleFoldRecursive,
+ cx: &mut ViewContext<Self>,
+ ) {
+ let selection = self.selections.newest::<Point>(cx);
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
+ let range = if selection.is_empty() {
+ let point = selection.head().to_display_point(&display_map);
+ let start = DisplayPoint::new(point.row(), 0).to_point(&display_map);
+ let end = DisplayPoint::new(point.row(), display_map.line_len(point.row()))
+ .to_point(&display_map);
+ start..end
+ } else {
+ selection.range()
+ };
+ if display_map.folds_in_range(range).next().is_some() {
+ self.unfold_recursive(&Default::default(), cx)
+ } else {
+ self.fold_recursive(&Default::default(), cx)
+ }
+ }
+ pub fn fold(&mut self, _: &actions::Fold, cx: &mut ViewContext<Self>) {
+ let mut fold_ranges = Vec::new();
+ let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
let selections = self.selections.all_adjusted(cx);
+
for selection in selections {
let range = selection.range().sorted();
let buffer_start_row = range.start.row;
- for row in (0..=range.end.row).rev() {
+ if range.start.row != range.end.row {
+ let mut found = false;
+ let mut row = range.start.row;
+ while row <= range.end.row {
+ if let Some((foldable_range, fold_text)) =
+ { display_map.foldable_range(MultiBufferRow(row)) }
+ {
+ found = true;
+ row = foldable_range.end.row + 1;
+ fold_ranges.push((foldable_range, fold_text));
+ } else {
+ row += 1
+ }
+ }
+ if found {
+ continue;
+ }
+ }
+
+ for row in (0..=range.start.row).rev() {
if let Some((foldable_range, fold_text)) =
display_map.foldable_range(MultiBufferRow(row))
{
@@ -10578,6 +10640,61 @@ impl Editor {
self.fold_ranges(fold_ranges, true, cx);
}
+ pub fn fold_all(&mut self, _: &actions::FoldAll, cx: &mut ViewContext<Self>) {
+ let mut fold_ranges = Vec::new();
+ let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
+
+ for row in 0..display_map.max_buffer_row().0 {
+ if let Some((foldable_range, fold_text)) =
+ display_map.foldable_range(MultiBufferRow(row))
+ {
+ fold_ranges.push((foldable_range, fold_text));
+ }
+ }
+
+ self.fold_ranges(fold_ranges, true, cx);
+ }
+
+ pub fn fold_recursive(&mut self, _: &actions::FoldRecursive, cx: &mut ViewContext<Self>) {
+ let mut fold_ranges = Vec::new();
+ let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
+ let selections = self.selections.all_adjusted(cx);
+
+ for selection in selections {
+ let range = selection.range().sorted();
+ let buffer_start_row = range.start.row;
+
+ if range.start.row != range.end.row {
+ let mut found = false;
+ for row in range.start.row..=range.end.row {
+ if let Some((foldable_range, fold_text)) =
+ { display_map.foldable_range(MultiBufferRow(row)) }
+ {
+ found = true;
+ fold_ranges.push((foldable_range, fold_text));
+ }
+ }
+ if found {
+ continue;
+ }
+ }
+
+ for row in (0..=range.start.row).rev() {
+ if let Some((foldable_range, fold_text)) =
+ display_map.foldable_range(MultiBufferRow(row))
+ {
+ if foldable_range.end.row >= buffer_start_row {
+ fold_ranges.push((foldable_range, fold_text));
+ } else {
+ break;
+ }
+ }
+ }
+ }
+
+ self.fold_ranges(fold_ranges, true, cx);
+ }
+
pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
let buffer_row = fold_at.buffer_row;
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
@@ -10612,6 +10729,24 @@ impl Editor {
self.unfold_ranges(ranges, true, true, cx);
}
+ pub fn unfold_recursive(&mut self, _: &UnfoldRecursive, cx: &mut ViewContext<Self>) {
+ let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
+ let selections = self.selections.all::<Point>(cx);
+ let ranges = selections
+ .iter()
+ .map(|s| {
+ let mut range = s.display_range(&display_map).sorted();
+ *range.start.column_mut() = 0;
+ *range.end.column_mut() = display_map.line_len(range.end.row());
+ let start = range.start.to_point(&display_map);
+ let end = range.end.to_point(&display_map);
+ start..end
+ })
+ .collect::<Vec<_>>();
+
+ self.unfold_ranges(ranges, true, true, cx);
+ }
+
pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
@@ -10630,6 +10765,16 @@ impl Editor {
self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
}
+ pub fn unfold_all(&mut self, _: &actions::UnfoldAll, cx: &mut ViewContext<Self>) {
+ let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
+ self.unfold_ranges(
+ [Point::zero()..display_map.max_point().to_point(&display_map)],
+ true,
+ true,
+ cx,
+ );
+ }
+
pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
let selections = self.selections.all::<Point>(cx);
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
@@ -852,7 +852,7 @@ fn test_fold_action(cx: &mut TestAppContext) {
_ = view.update(cx, |view, cx| {
view.change_selections(None, cx, |s| {
s.select_display_ranges([
- DisplayPoint::new(DisplayRow(8), 0)..DisplayPoint::new(DisplayRow(12), 0)
+ DisplayPoint::new(DisplayRow(7), 0)..DisplayPoint::new(DisplayRow(12), 0)
]);
});
view.fold(&Fold, cx);
@@ -940,7 +940,7 @@ fn test_fold_action_whitespace_sensitive_language(cx: &mut TestAppContext) {
_ = view.update(cx, |view, cx| {
view.change_selections(None, cx, |s| {
s.select_display_ranges([
- DisplayPoint::new(DisplayRow(7), 0)..DisplayPoint::new(DisplayRow(10), 0)
+ DisplayPoint::new(DisplayRow(6), 0)..DisplayPoint::new(DisplayRow(10), 0)
]);
});
view.fold(&Fold, cx);
@@ -1022,7 +1022,7 @@ fn test_fold_action_multiple_line_breaks(cx: &mut TestAppContext) {
_ = view.update(cx, |view, cx| {
view.change_selections(None, cx, |s| {
s.select_display_ranges([
- DisplayPoint::new(DisplayRow(7), 0)..DisplayPoint::new(DisplayRow(11), 0)
+ DisplayPoint::new(DisplayRow(6), 0)..DisplayPoint::new(DisplayRow(11), 0)
]);
});
view.fold(&Fold, cx);
@@ -335,8 +335,14 @@ impl EditorElement {
register_action(view, cx, Editor::open_url);
register_action(view, cx, Editor::open_file);
register_action(view, cx, Editor::fold);
+ register_action(view, cx, Editor::fold_all);
register_action(view, cx, Editor::fold_at);
+ register_action(view, cx, Editor::fold_recursive);
+ register_action(view, cx, Editor::toggle_fold);
+ register_action(view, cx, Editor::toggle_fold_recursive);
register_action(view, cx, Editor::unfold_lines);
+ register_action(view, cx, Editor::unfold_recursive);
+ register_action(view, cx, Editor::unfold_all);
register_action(view, cx, Editor::unfold_at);
register_action(view, cx, Editor::fold_selected_ranges);
register_action(view, cx, Editor::show_completions);