diff --git a/crates/editor/src/actions.rs b/crates/editor/src/actions.rs index 70ec8ea00f..e12bdf7a07 100644 --- a/crates/editor/src/actions.rs +++ b/crates/editor/src/actions.rs @@ -410,6 +410,8 @@ actions!( ToggleFold, /// Toggles recursive folding at the current position. ToggleFoldRecursive, + /// Toggles all folds in a buffer or all excerpts in multibuffer. + ToggleFoldAll, /// Formats the entire document. Format, /// Formats only the selected text. diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index a25a96cdab..5065564fdb 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -17075,6 +17075,46 @@ impl Editor { } } + pub fn toggle_fold_all( + &mut self, + _: &actions::ToggleFoldAll, + window: &mut Window, + cx: &mut Context, + ) { + if self.buffer.read(cx).is_singleton() { + let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); + let has_folds = display_map + .folds_in_range(0..display_map.buffer_snapshot.len()) + .next() + .is_some(); + + if has_folds { + self.unfold_all(&actions::UnfoldAll, window, cx); + } else { + self.fold_all(&actions::FoldAll, window, cx); + } + } else { + let buffer_ids = self.buffer.read(cx).excerpt_buffer_ids(); + let should_unfold = buffer_ids + .iter() + .any(|buffer_id| self.is_buffer_folded(*buffer_id, cx)); + + self.toggle_fold_multiple_buffers = cx.spawn_in(window, async move |editor, cx| { + editor + .update_in(cx, |editor, _, cx| { + for buffer_id in buffer_ids { + if should_unfold { + editor.unfold_buffer(buffer_id, cx); + } else { + editor.fold_buffer(buffer_id, cx); + } + } + }) + .ok(); + }); + } + } + fn fold_at_level( &mut self, fold_at: &FoldAtLevel, diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 8355fa1d66..f9a31cffb1 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -9,7 +9,7 @@ use crate::{ LineUp, MAX_LINE_LEN, MINIMAP_FONT_SIZE, MULTI_BUFFER_EXCERPT_HEADER_HEIGHT, OpenExcerpts, PageDown, PageUp, PhantomBreakpointIndicator, Point, RowExt, RowRangeExt, SelectPhase, SelectedTextHighlight, Selection, SelectionDragState, SoftWrap, StickyHeaderExcerpt, ToPoint, - ToggleFold, + ToggleFold, ToggleFoldAll, code_context_menus::{CodeActionsMenu, MENU_ASIDE_MAX_WIDTH, MENU_ASIDE_MIN_WIDTH, MENU_GAP}, display_map::{ Block, BlockContext, BlockStyle, ChunkRendererId, DisplaySnapshot, EditorMargins, @@ -416,6 +416,7 @@ impl EditorElement { register_action(editor, window, Editor::fold_recursive); register_action(editor, window, Editor::toggle_fold); register_action(editor, window, Editor::toggle_fold_recursive); + register_action(editor, window, Editor::toggle_fold_all); register_action(editor, window, Editor::unfold_lines); register_action(editor, window, Editor::unfold_recursive); register_action(editor, window, Editor::unfold_all); @@ -3620,24 +3621,37 @@ impl EditorElement { .tooltip({ let focus_handle = focus_handle.clone(); move |window, cx| { - Tooltip::for_action_in( + Tooltip::with_meta_in( "Toggle Excerpt Fold", - &ToggleFold, + Some(&ToggleFold), + "Alt+click to toggle all", &focus_handle, window, cx, ) } }) - .on_click(move |_, _, cx| { - if is_folded { + .on_click(move |event, window, cx| { + if event.modifiers().alt { + // Alt+click toggles all buffers editor.update(cx, |editor, cx| { - editor.unfold_buffer(buffer_id, cx); + editor.toggle_fold_all( + &ToggleFoldAll, + window, + cx, + ); }); } else { - editor.update(cx, |editor, cx| { - editor.fold_buffer(buffer_id, cx); - }); + // Regular click toggles single buffer + if is_folded { + editor.update(cx, |editor, cx| { + editor.unfold_buffer(buffer_id, cx); + }); + } else { + editor.update(cx, |editor, cx| { + editor.fold_buffer(buffer_id, cx); + }); + } } }), ),