Allow toggling search options via the command palette

Antonio Scandurra created

Change summary

assets/keymaps/default.json         | 21 ++------------
crates/search/src/buffer_search.rs  | 41 +++++++++++++++-------------
crates/search/src/project_search.rs | 43 ++++++++++++++++--------------
crates/search/src/search.rs         | 30 ++++++++++++++-------
4 files changed, 68 insertions(+), 67 deletions(-)

Detailed changes

assets/keymaps/default.json 🔗

@@ -147,24 +147,9 @@
             "cmd-f": "project_search::ToggleFocus",
             "cmd-g": "search::SelectNextMatch",
             "cmd-shift-G": "search::SelectPrevMatch",
-            "alt-cmd-c": [
-                "search::ToggleSearchOption",
-                {
-                    "option": "CaseSensitive"
-                }
-            ],
-            "alt-cmd-w": [
-                "search::ToggleSearchOption",
-                {
-                    "option": "WholeWord"
-                }
-            ],
-            "alt-cmd-r": [
-                "search::ToggleSearchOption",
-                {
-                    "option": "Regex"
-                }
-            ]
+            "alt-cmd-c": "search::ToggleCaseSensitive",
+            "alt-cmd-w": "search::ToggleWholeWord",
+            "alt-cmd-r": "search::ToggleRegex"
         }
     },
     {

crates/search/src/buffer_search.rs 🔗

@@ -1,11 +1,12 @@
 use crate::{
     active_match_index, match_index_for_direction, query_suggestion_for_editor, Direction,
-    SearchOption, SelectNextMatch, SelectPrevMatch, ToggleSearchOption,
+    SearchOption, SelectNextMatch, SelectPrevMatch, ToggleCaseSensitive, ToggleRegex,
+    ToggleWholeWord,
 };
 use collections::HashMap;
 use editor::{Anchor, Autoscroll, Editor};
 use gpui::{
-    actions, elements::*, impl_actions, platform::CursorStyle, AppContext, Entity,
+    actions, elements::*, impl_actions, platform::CursorStyle, Action, AppContext, Entity,
     MutableAppContext, RenderContext, Subscription, Task, View, ViewContext, ViewHandle,
     WeakViewHandle,
 };
@@ -32,26 +33,28 @@ pub fn init(cx: &mut MutableAppContext) {
     cx.add_action(BufferSearchBar::deploy);
     cx.add_action(BufferSearchBar::dismiss);
     cx.add_action(BufferSearchBar::focus_editor);
-    cx.add_action(
-        |pane: &mut Pane,
-         ToggleSearchOption { option }: &ToggleSearchOption,
-         cx: &mut ViewContext<Pane>| {
-            if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::<BufferSearchBar>() {
-                if search_bar.update(cx, |search_bar, cx| search_bar.show(false, false, cx)) {
-                    search_bar.update(cx, |search_bar, cx| {
-                        search_bar.toggle_search_option(*option, cx);
-                    });
-                    return;
-                }
-            }
-            cx.propagate_action();
-        },
-    );
     cx.add_action(BufferSearchBar::select_next_match);
     cx.add_action(BufferSearchBar::select_prev_match);
     cx.add_action(BufferSearchBar::select_next_match_on_pane);
     cx.add_action(BufferSearchBar::select_prev_match_on_pane);
     cx.add_action(BufferSearchBar::handle_editor_cancel);
+    add_toggle_option_action::<ToggleCaseSensitive>(SearchOption::CaseSensitive, cx);
+    add_toggle_option_action::<ToggleWholeWord>(SearchOption::WholeWord, cx);
+    add_toggle_option_action::<ToggleRegex>(SearchOption::Regex, cx);
+}
+
+fn add_toggle_option_action<A: Action>(option: SearchOption, cx: &mut MutableAppContext) {
+    cx.add_action(move |pane: &mut Pane, _: &A, cx: &mut ViewContext<Pane>| {
+        if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::<BufferSearchBar>() {
+            if search_bar.update(cx, |search_bar, cx| search_bar.show(false, false, cx)) {
+                search_bar.update(cx, |search_bar, cx| {
+                    search_bar.toggle_search_option(option, cx);
+                });
+                return;
+            }
+        }
+        cx.propagate_action();
+    });
 }
 
 pub struct BufferSearchBar {
@@ -282,12 +285,12 @@ impl BufferSearchBar {
                 .with_style(style.container)
                 .boxed()
         })
-        .on_click(move |_, _, cx| cx.dispatch_action(ToggleSearchOption { option }))
+        .on_click(move |_, _, cx| cx.dispatch_any_action(option.to_toggle_action()))
         .with_cursor_style(CursorStyle::PointingHand)
         .with_tooltip::<Self, _>(
             option as usize,
             format!("Toggle {}", option.label()),
-            Some(Box::new(ToggleSearchOption { option })),
+            Some(option.to_toggle_action()),
             tooltip_style,
             cx,
         )

crates/search/src/project_search.rs 🔗

@@ -1,13 +1,14 @@
 use crate::{
     active_match_index, match_index_for_direction, query_suggestion_for_editor, Direction,
-    SearchOption, SelectNextMatch, SelectPrevMatch, ToggleSearchOption,
+    SearchOption, SelectNextMatch, SelectPrevMatch, ToggleCaseSensitive, ToggleRegex,
+    ToggleWholeWord,
 };
 use collections::HashMap;
 use editor::{Anchor, Autoscroll, Editor, MultiBuffer, SelectAll};
 use gpui::{
-    actions, elements::*, platform::CursorStyle, AppContext, ElementBox, Entity, ModelContext,
-    ModelHandle, MutableAppContext, RenderContext, Subscription, Task, View, ViewContext,
-    ViewHandle, WeakModelHandle, WeakViewHandle,
+    actions, elements::*, platform::CursorStyle, Action, AppContext, ElementBox, Entity,
+    ModelContext, ModelHandle, MutableAppContext, RenderContext, Subscription, Task, View,
+    ViewContext, ViewHandle, WeakModelHandle, WeakViewHandle,
 };
 use menu::Confirm;
 use project::{search::SearchQuery, Project};
@@ -38,21 +39,23 @@ pub fn init(cx: &mut MutableAppContext) {
     cx.add_action(ProjectSearchBar::select_next_match);
     cx.add_action(ProjectSearchBar::select_prev_match);
     cx.add_action(ProjectSearchBar::toggle_focus);
-    cx.add_action(
-        |pane: &mut Pane,
-         ToggleSearchOption { option }: &ToggleSearchOption,
-         cx: &mut ViewContext<Pane>| {
-            if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::<ProjectSearchBar>() {
-                if search_bar.update(cx, |search_bar, cx| {
-                    search_bar.toggle_search_option(*option, cx)
-                }) {
-                    return;
-                }
-            }
-            cx.propagate_action();
-        },
-    );
     cx.capture_action(ProjectSearchBar::tab);
+    add_toggle_option_action::<ToggleCaseSensitive>(SearchOption::CaseSensitive, cx);
+    add_toggle_option_action::<ToggleWholeWord>(SearchOption::WholeWord, cx);
+    add_toggle_option_action::<ToggleRegex>(SearchOption::Regex, cx);
+}
+
+fn add_toggle_option_action<A: Action>(option: SearchOption, cx: &mut MutableAppContext) {
+    cx.add_action(move |pane: &mut Pane, _: &A, cx: &mut ViewContext<Pane>| {
+        if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::<ProjectSearchBar>() {
+            if search_bar.update(cx, |search_bar, cx| {
+                search_bar.toggle_search_option(option, cx)
+            }) {
+                return;
+            }
+        }
+        cx.propagate_action();
+    });
 }
 
 struct ProjectSearch {
@@ -731,12 +734,12 @@ impl ProjectSearchBar {
                 .with_style(style.container)
                 .boxed()
         })
-        .on_click(move |_, _, cx| cx.dispatch_action(ToggleSearchOption { option }))
+        .on_click(move |_, _, cx| cx.dispatch_any_action(option.to_toggle_action()))
         .with_cursor_style(CursorStyle::PointingHand)
         .with_tooltip::<Self, _>(
             option as usize,
             format!("Toggle {}", option.label()),
-            Some(Box::new(ToggleSearchOption { option })),
+            Some(option.to_toggle_action()),
             tooltip_style,
             cx,
         )

crates/search/src/search.rs 🔗

@@ -1,8 +1,7 @@
 pub use buffer_search::BufferSearchBar;
 use editor::{display_map::ToDisplayPoint, Anchor, Bias, Editor, MultiBufferSnapshot};
-use gpui::{actions, impl_actions, MutableAppContext, ViewHandle};
+use gpui::{actions, Action, MutableAppContext, ViewHandle};
 pub use project_search::{ProjectSearchBar, ProjectSearchView};
-use serde::Deserialize;
 use std::{
     cmp::{self, Ordering},
     ops::Range,
@@ -16,15 +15,18 @@ pub fn init(cx: &mut MutableAppContext) {
     project_search::init(cx);
 }
 
-#[derive(Clone, PartialEq, Deserialize)]
-pub struct ToggleSearchOption {
-    pub option: SearchOption,
-}
-
-actions!(search, [SelectNextMatch, SelectPrevMatch]);
-impl_actions!(search, [ToggleSearchOption]);
+actions!(
+    search,
+    [
+        ToggleWholeWord,
+        ToggleCaseSensitive,
+        ToggleRegex,
+        SelectNextMatch,
+        SelectPrevMatch
+    ]
+);
 
-#[derive(Clone, Copy, PartialEq, Deserialize)]
+#[derive(Clone, Copy, PartialEq)]
 pub enum SearchOption {
     WholeWord,
     CaseSensitive,
@@ -39,6 +41,14 @@ impl SearchOption {
             SearchOption::Regex => "Use Regular Expression",
         }
     }
+
+    pub fn to_toggle_action(&self) -> Box<dyn Action> {
+        match self {
+            SearchOption::WholeWord => Box::new(ToggleWholeWord),
+            SearchOption::CaseSensitive => Box::new(ToggleCaseSensitive),
+            SearchOption::Regex => Box::new(ToggleRegex),
+        }
+    }
 }
 
 #[derive(Clone, Copy, PartialEq, Eq)]