From 0e31d13a1ed01742349a54cd94711dbbef943f60 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Tue, 9 May 2023 20:09:15 +0300 Subject: [PATCH] Rework tab and escape key handling in search panel Fixes https://linear.app/zed-industries/issue/Z-1238/focus-the-results-multibuffer-in-project-search-on-esc and adds a tab shortcut for project search inputs co-authored-by: Julia --- assets/keymaps/default.json | 12 +++++++ crates/search/src/project_search.rs | 56 ++++++++++++++++++++++------- 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/assets/keymaps/default.json b/assets/keymaps/default.json index b89940a751..d2fd4107e4 100644 --- a/assets/keymaps/default.json +++ b/assets/keymaps/default.json @@ -199,6 +199,18 @@ "shift-enter": "search::SelectPrevMatch" } }, + { + "context": "ProjectSearchBar > Editor", + "bindings": { + "escape": "project_search::ToggleFocus" + } + }, + { + "context": "ProjectSearchView > Editor", + "bindings": { + "escape": "project_search::ToggleFocus" + } + }, { "context": "Pane", "bindings": { diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index ff7f0611c5..2a6ffca7ca 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -34,7 +34,7 @@ use workspace::{ ItemNavHistory, Pane, ToolbarItemLocation, ToolbarItemView, Workspace, WorkspaceId, }; -actions!(project_search, [SearchInNew, ToggleFocus]); +actions!(project_search, [SearchInNew, ToggleFocus, NextField]); #[derive(Default)] struct ActiveSearches(HashMap, WeakViewHandle>); @@ -48,6 +48,7 @@ pub fn init(cx: &mut AppContext) { cx.add_action(ProjectSearchBar::select_prev_match); cx.add_action(ProjectSearchBar::toggle_focus); cx.capture_action(ProjectSearchBar::tab); + cx.capture_action(ProjectSearchBar::tab_previous); add_toggle_option_action::(SearchOption::CaseSensitive, cx); add_toggle_option_action::(SearchOption::WholeWord, cx); add_toggle_option_action::(SearchOption::Regex, cx); @@ -789,19 +790,50 @@ impl ProjectSearchBar { } fn tab(&mut self, _: &editor::Tab, cx: &mut ViewContext) { - if let Some(search_view) = self.active_project_search.as_ref() { - search_view.update(cx, |search_view, cx| { - if search_view.query_editor.is_focused(cx) { - if !search_view.model.read(cx).match_ranges.is_empty() { - search_view.focus_results_editor(cx); - } - } else { + self.cycle_field(Direction::Next, cx); + } + + fn tab_previous(&mut self, _: &editor::TabPrev, cx: &mut ViewContext) { + self.cycle_field(Direction::Prev, cx); + } + + fn cycle_field(&mut self, direction: Direction, cx: &mut ViewContext) { + let active_project_search = match &self.active_project_search { + Some(active_project_search) => active_project_search, + + None => { + cx.propagate_action(); + return; + } + }; + + active_project_search.update(cx, |project_view, cx| { + let views = &[ + &project_view.query_editor, + &project_view.included_files_editor, + &project_view.excluded_files_editor, + ]; + + let current_index = match views + .iter() + .enumerate() + .find(|(_, view)| view.is_focused(cx)) + { + Some((index, _)) => index, + + None => { cx.propagate_action(); + return; } - }); - } else { - cx.propagate_action(); - } + }; + + let new_index = match direction { + Direction::Next => (current_index + 1) % views.len(), + Direction::Prev if current_index == 0 => views.len() - 1, + Direction::Prev => (current_index - 1) % views.len(), + }; + cx.focus(views[new_index]); + }); } fn toggle_search_option(&mut self, option: SearchOption, cx: &mut ViewContext) -> bool {