From 507929cb790f78bce4c90f111d9caf4e876ca98e Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Fri, 25 Oct 2024 16:08:37 -0400 Subject: [PATCH] Add `editor: fold at level ` commands (#19750) Closes https://github.com/zed-industries/zed/issues/5142 Note that I only moved the cursor to the top of the file so it wouldn't jump - the commands work no matter where you are in the file. https://github.com/user-attachments/assets/78c74ca6-5c17-477c-b5d1-97c5665e44b0 Also, is VS Code doing this right thing here? or is it busted? https://github.com/user-attachments/assets/8c503b50-9671-4221-b9f8-1e692fe8cd9a Release Notes: - Added `editor: fold at level ` commands. macOS: `cmd-k, cmd-`, Linux: `ctrl-k, ctrl-`. --------- Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> --- assets/keymaps/default-linux.json | 9 +++++++ assets/keymaps/default-macos.json | 10 +++++++- crates/editor/src/actions.rs | 5 ++++ crates/editor/src/editor.rs | 41 ++++++++++++++++++++++++++----- crates/editor/src/element.rs | 1 + 5 files changed, 59 insertions(+), 7 deletions(-) diff --git a/assets/keymaps/default-linux.json b/assets/keymaps/default-linux.json index 9df8debb70ea98d9dea5a7fb40eadc5c1d3a05bf..4f55fa9772b4dbe058d1f096b06153285b773142 100644 --- a/assets/keymaps/default-linux.json +++ b/assets/keymaps/default-linux.json @@ -313,6 +313,15 @@ "ctrl-k ctrl-l": "editor::ToggleFold", "ctrl-k ctrl-[": "editor::FoldRecursive", "ctrl-k ctrl-]": "editor::UnfoldRecursive", + "ctrl-k ctrl-1": ["editor::FoldAtLevel", { "level": 1 }], + "ctrl-k ctrl-2": ["editor::FoldAtLevel", { "level": 2 }], + "ctrl-k ctrl-3": ["editor::FoldAtLevel", { "level": 3 }], + "ctrl-k ctrl-4": ["editor::FoldAtLevel", { "level": 4 }], + "ctrl-k ctrl-5": ["editor::FoldAtLevel", { "level": 5 }], + "ctrl-k ctrl-6": ["editor::FoldAtLevel", { "level": 6 }], + "ctrl-k ctrl-7": ["editor::FoldAtLevel", { "level": 7 }], + "ctrl-k ctrl-8": ["editor::FoldAtLevel", { "level": 8 }], + "ctrl-k ctrl-9": ["editor::FoldAtLevel", { "level": 9 }], "ctrl-k ctrl-0": "editor::FoldAll", "ctrl-k ctrl-j": "editor::UnfoldAll", "ctrl-space": "editor::ShowCompletions", diff --git a/assets/keymaps/default-macos.json b/assets/keymaps/default-macos.json index c0bad344ab621c9a3e6edc63d54057839b2ba92d..ade3ece1eda930dc0180387b001fdc90fc1a04e5 100644 --- a/assets/keymaps/default-macos.json +++ b/assets/keymaps/default-macos.json @@ -349,7 +349,15 @@ "alt-cmd-]": "editor::UnfoldLines", "cmd-k cmd-l": "editor::ToggleFold", "cmd-k cmd-[": "editor::FoldRecursive", - "cmd-k cmd-]": "editor::UnfoldRecursive", + "cmd-k cmd-1": ["editor::FoldAtLevel", { "level": 1 }], + "cmd-k cmd-2": ["editor::FoldAtLevel", { "level": 2 }], + "cmd-k cmd-3": ["editor::FoldAtLevel", { "level": 3 }], + "cmd-k cmd-4": ["editor::FoldAtLevel", { "level": 4 }], + "cmd-k cmd-5": ["editor::FoldAtLevel", { "level": 5 }], + "cmd-k cmd-6": ["editor::FoldAtLevel", { "level": 6 }], + "cmd-k cmd-7": ["editor::FoldAtLevel", { "level": 7 }], + "cmd-k cmd-8": ["editor::FoldAtLevel", { "level": 8 }], + "cmd-k cmd-9": ["editor::FoldAtLevel", { "level": 9 }], "cmd-k cmd-0": "editor::FoldAll", "cmd-k cmd-j": "editor::UnfoldAll", "ctrl-space": "editor::ShowCompletions", diff --git a/crates/editor/src/actions.rs b/crates/editor/src/actions.rs index b190283776eae2d48f5449cb7072128903e7cbf8..83379e13aed32ef24660f4cb58cce02d161b57c1 100644 --- a/crates/editor/src/actions.rs +++ b/crates/editor/src/actions.rs @@ -153,6 +153,10 @@ pub struct DeleteToPreviousWordStart { pub ignore_newlines: bool, } +#[derive(PartialEq, Clone, Deserialize, Default)] +pub struct FoldAtLevel { + pub level: u32, +} impl_actions!( editor, [ @@ -182,6 +186,7 @@ impl_actions!( ToggleCodeActions, ToggleComments, UnfoldAt, + FoldAtLevel ] ); diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index f3fb5cd3606c85b2b0b21bd6e39ad3a957076560..641ccc27151bd9a5a373266f68a3f29281790a04 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -10728,15 +10728,44 @@ impl Editor { self.fold_ranges(fold_ranges, true, cx); } + fn fold_at_level(&mut self, fold_at: &FoldAtLevel, cx: &mut ViewContext) { + let fold_at_level = fold_at.level; + let snapshot = self.buffer.read(cx).snapshot(cx); + let mut fold_ranges = Vec::new(); + let mut stack = vec![(0, snapshot.max_buffer_row().0, 1)]; + + while let Some((mut start_row, end_row, current_level)) = stack.pop() { + while start_row < end_row { + match self.snapshot(cx).foldable_range(MultiBufferRow(start_row)) { + Some(foldable_range) => { + let nested_start_row = foldable_range.0.start.row + 1; + let nested_end_row = foldable_range.0.end.row; + + if current_level == fold_at_level { + fold_ranges.push(foldable_range); + } + + if current_level <= fold_at_level { + stack.push((nested_start_row, nested_end_row, current_level + 1)); + } + + start_row = nested_end_row + 1; + } + None => start_row += 1, + } + } + } + + self.fold_ranges(fold_ranges, true, cx); + } + pub fn fold_all(&mut self, _: &actions::FoldAll, cx: &mut ViewContext) { let mut fold_ranges = Vec::new(); - let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); + let snapshot = self.buffer.read(cx).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)); + for row in 0..snapshot.max_buffer_row().0 { + if let Some(foldable_range) = self.snapshot(cx).foldable_range(MultiBufferRow(row)) { + fold_ranges.push(foldable_range); } } diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 12e9d74914aa43c14660d90991e36f58896723c7..2c3bed7eb784061b74eb03b9876dad0733af561b 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -336,6 +336,7 @@ 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_at_level); register_action(view, cx, Editor::fold_all); register_action(view, cx, Editor::fold_at); register_action(view, cx, Editor::fold_recursive);