From f96e4ba84f096b78ecd88abe4880c2ba345ed22f Mon Sep 17 00:00:00 2001 From: Tristan Hume Date: Mon, 24 Jun 2024 23:26:47 -0400 Subject: [PATCH] Add "Select Enclosing Symbol" command (#13435) I use this for a much faster workflow with inline assist when using fast models. Release Notes: - Added "Select Enclosing Symbol" command based on tree-sitter outline. Useful in combination with inline assist to rewrite a function. --- assets/keymaps/default-linux.json | 3 +- assets/keymaps/default-macos.json | 3 +- crates/editor/src/actions.rs | 1 + crates/editor/src/editor.rs | 52 +++++++++++++++++++++++++++++++ crates/editor/src/element.rs | 1 + 5 files changed, 58 insertions(+), 2 deletions(-) diff --git a/assets/keymaps/default-linux.json b/assets/keymaps/default-linux.json index e9253990ca..f9e1d13b51 100644 --- a/assets/keymaps/default-linux.json +++ b/assets/keymaps/default-linux.json @@ -152,7 +152,8 @@ // "focus": false // } // ], - "ctrl->": "assistant::QuoteSelection" + "ctrl->": "assistant::QuoteSelection", + "ctrl-alt-e": "editor::SelectEnclosingSymbol" } }, { diff --git a/assets/keymaps/default-macos.json b/assets/keymaps/default-macos.json index 21d1f983b5..7a5f1b2f1f 100644 --- a/assets/keymaps/default-macos.json +++ b/assets/keymaps/default-macos.json @@ -188,7 +188,8 @@ "focus": false } ], - "cmd->": "assistant::QuoteSelection" + "cmd->": "assistant::QuoteSelection", + "cmd-alt-e": "editor::SelectEnclosingSymbol" } }, { diff --git a/crates/editor/src/actions.rs b/crates/editor/src/actions.rs index 22b2f02d5c..293d9da719 100644 --- a/crates/editor/src/actions.rs +++ b/crates/editor/src/actions.rs @@ -268,6 +268,7 @@ gpui::actions!( SelectAllMatches, SelectDown, SelectLargerSyntaxNode, + SelectEnclosingSymbol, SelectLeft, SelectLine, SelectRight, diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 43c061818f..ffda62eecd 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -8226,6 +8226,58 @@ impl Editor { }); } + pub fn select_enclosing_symbol( + &mut self, + _: &SelectEnclosingSymbol, + cx: &mut ViewContext, + ) { + let buffer = self.buffer.read(cx).snapshot(cx); + let old_selections = self.selections.all::(cx).into_boxed_slice(); + + fn update_selection( + selection: &Selection, + buffer_snap: &MultiBufferSnapshot, + ) -> Option> { + let cursor = selection.head(); + let (_buffer_id, symbols) = buffer_snap.symbols_containing(cursor, None)?; + for symbol in symbols.iter().rev() { + let start = symbol.range.start.to_offset(&buffer_snap); + let end = symbol.range.end.to_offset(&buffer_snap); + let new_range = start..end; + if start < selection.start || end > selection.end { + return Some(Selection { + id: selection.id, + start: new_range.start, + end: new_range.end, + goal: SelectionGoal::None, + reversed: selection.reversed, + }); + } + } + None + } + + let mut selected_larger_symbol = false; + let new_selections = old_selections + .iter() + .map(|selection| match update_selection(selection, &buffer) { + Some(new_selection) => { + if new_selection.range() != selection.range() { + selected_larger_symbol = true; + } + new_selection + } + None => selection.clone(), + }) + .collect::>(); + + if selected_larger_symbol { + self.change_selections(Some(Autoscroll::fit()), cx, |s| { + s.select(new_selections); + }); + } + } + pub fn select_larger_syntax_node( &mut self, _: &SelectLargerSyntaxNode, diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index d7ea58c782..17b0a4ae58 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -276,6 +276,7 @@ impl EditorElement { register_action(view, cx, Editor::toggle_comments); register_action(view, cx, Editor::select_larger_syntax_node); register_action(view, cx, Editor::select_smaller_syntax_node); + register_action(view, cx, Editor::select_enclosing_symbol); register_action(view, cx, Editor::move_to_enclosing_bracket); register_action(view, cx, Editor::undo_selection); register_action(view, cx, Editor::redo_selection);