More cleanups

Lukas Wirth created

Change summary

crates/search/src/buffer_search.rs  | 165 ++++++++++++++----------------
crates/search/src/project_search.rs |  93 +++++++---------
2 files changed, 117 insertions(+), 141 deletions(-)

Detailed changes

crates/search/src/buffer_search.rs 🔗

@@ -17,9 +17,9 @@ use editor::{
 };
 use futures::channel::oneshot;
 use gpui::{
-    Action, App, ClickEvent, Context, Entity, EventEmitter, FocusHandle, Focusable,
-    InteractiveElement as _, IntoElement, KeyContext, ParentElement as _, Render, ScrollHandle,
-    Styled, Subscription, Task, Window, actions, div,
+    Action, App, ClickEvent, Context, Entity, EventEmitter, Focusable, InteractiveElement as _,
+    IntoElement, KeyContext, ParentElement as _, Render, ScrollHandle, Styled, Subscription, Task,
+    Window, actions, div,
 };
 use language::{Language, LanguageRegistry};
 use project::{
@@ -147,7 +147,14 @@ impl Render for BufferSearchBar {
         let hide_inline_icons = self.editor_needed_width
             > self.editor_scroll_handle.bounds().size.width - window.rem_size() * 6.;
 
-        let supported_options = self.supported_options(cx);
+        let workspace::searchable::SearchOptions {
+            case,
+            word,
+            regex,
+            replacement,
+            selection,
+            find_in_results,
+        } = self.supported_options(cx);
 
         if self.query_editor.update(cx, |query_editor, _cx| {
             query_editor.placeholder_text().is_none()
@@ -182,20 +189,16 @@ impl Render for BufferSearchBar {
                 }
             })
             .unwrap_or_else(|| "0/0".to_string());
-        let should_show_replace_input = self.replace_enabled && supported_options.replacement;
+        let should_show_replace_input = self.replace_enabled && replacement;
         let in_replace = self.replacement_editor.focus_handle(cx).is_focused(window);
 
-        let mut key_context = KeyContext::new_with_defaults();
-        key_context.add("BufferSearchBar");
-        if in_replace {
-            key_context.add("in_replace");
-        }
+        let theme_colors = cx.theme().colors();
         let query_border = if self.query_error.is_some() {
             Color::Error.color(cx)
         } else {
-            cx.theme().colors().border
+            theme_colors.border
         };
-        let replacement_border = cx.theme().colors().border;
+        let replacement_border = theme_colors.border;
 
         let container_width = window.viewport_size().width;
         let input_width = SearchInputWidth::calc_width(container_width);
@@ -211,27 +214,27 @@ impl Render for BufferSearchBar {
                 div.child(
                     h_flex()
                         .gap_1()
-                        .when(supported_options.case, |div| {
-                            div.child(self.render_search_option_button(
-                                SearchOptions::CASE_SENSITIVE,
+                        .when(case, |div| {
+                            div.child(SearchOptions::CASE_SENSITIVE.as_button(
+                                self.search_options.contains(SearchOptions::CASE_SENSITIVE),
                                 focus_handle.clone(),
                                 cx.listener(|this, _, window, cx| {
                                     this.toggle_case_sensitive(&ToggleCaseSensitive, window, cx)
                                 }),
                             ))
                         })
-                        .when(supported_options.word, |div| {
-                            div.child(self.render_search_option_button(
-                                SearchOptions::WHOLE_WORD,
+                        .when(word, |div| {
+                            div.child(SearchOptions::WHOLE_WORD.as_button(
+                                self.search_options.contains(SearchOptions::WHOLE_WORD),
                                 focus_handle.clone(),
                                 cx.listener(|this, _, window, cx| {
                                     this.toggle_whole_word(&ToggleWholeWord, window, cx)
                                 }),
                             ))
                         })
-                        .when(supported_options.regex, |div| {
-                            div.child(self.render_search_option_button(
-                                SearchOptions::REGEX,
+                        .when(regex, |div| {
+                            div.child(SearchOptions::REGEX.as_button(
+                                self.search_options.contains(SearchOptions::REGEX),
                                 focus_handle.clone(),
                                 cx.listener(|this, _, window, cx| {
                                     this.toggle_regex(&ToggleRegex, window, cx)
@@ -244,7 +247,7 @@ impl Render for BufferSearchBar {
         let mode_column = h_flex()
             .gap_1()
             .min_w_64()
-            .when(supported_options.replacement, |this| {
+            .when(replacement, |this| {
                 this.child(toggle_replace_button(
                     "buffer-search-bar-toggle-replace-button",
                     focus_handle.clone(),
@@ -254,7 +257,7 @@ impl Render for BufferSearchBar {
                     }),
                 ))
             })
-            .when(supported_options.selection, |this| {
+            .when(selection, |this| {
                 this.child(
                     IconButton::new(
                         "buffer-search-bar-toggle-search-selection-button",
@@ -283,13 +286,13 @@ impl Render for BufferSearchBar {
                     }),
                 )
             })
-            .when(!supported_options.find_in_results, |el| {
+            .when(!find_in_results, |el| {
                 let query_focus = self.query_editor.focus_handle(cx);
                 let matches_column = h_flex()
                     .pl_2()
                     .ml_1()
                     .border_l_1()
-                    .border_color(cx.theme().colors().border_variant)
+                    .border_color(theme_colors.border_variant)
                     .child(render_action_button(
                         "buffer-search-nav-button",
                         ui::IconName::ChevronLeft,
@@ -304,27 +307,17 @@ impl Render for BufferSearchBar {
                         self.active_match_index.is_some(),
                         "Select Next Match",
                         &SelectNextMatch,
-                        query_focus,
+                        query_focus.clone(),
                     ));
-                el.child(
-                    IconButton::new("select-all", ui::IconName::SelectAll)
-                        .on_click(|_, window, cx| {
-                            window.dispatch_action(SelectAllMatches.boxed_clone(), cx)
-                        })
-                        .shape(IconButtonShape::Square)
-                        .tooltip({
-                            let focus_handle = focus_handle.clone();
-                            move |window, cx| {
-                                Tooltip::for_action_in(
-                                    "Select All Matches",
-                                    &SelectAllMatches,
-                                    &focus_handle,
-                                    window,
-                                    cx,
-                                )
-                            }
-                        }),
-                )
+
+                el.child(render_action_button(
+                    "buffer-search-nav-button",
+                    IconName::SelectAll,
+                    true,
+                    "Select All Matches",
+                    &SelectAllMatches,
+                    query_focus,
+                ))
                 .child(matches_column)
                 .when(!narrow_mode, |this| {
                     this.child(h_flex().ml_2().min_w(rems_from_px(40.)).child(
@@ -338,22 +331,20 @@ impl Render for BufferSearchBar {
                     ))
                 })
             })
-            .when(supported_options.find_in_results, |el| {
-                el.child(
-                    IconButton::new(SharedString::from("Close"), IconName::Close)
-                        .shape(IconButtonShape::Square)
-                        .tooltip(move |window, cx| {
-                            Tooltip::for_action("Close Search Bar", &Dismiss, window, cx)
-                        })
-                        .on_click(cx.listener(|this, _: &ClickEvent, window, cx| {
-                            this.dismiss(&Dismiss, window, cx)
-                        })),
-                )
+            .when(find_in_results, |el| {
+                el.child(render_action_button(
+                    "buffer-search",
+                    IconName::Close,
+                    true,
+                    "Close Search Bar",
+                    &Dismiss,
+                    focus_handle.clone(),
+                ))
             });
 
         let search_line = h_flex()
             .gap_2()
-            .when(supported_options.find_in_results, |el| {
+            .when(find_in_results, |el| {
                 el.child(Label::new("Find in results").color(Color::Hint))
             })
             .child(query_column)
@@ -390,6 +381,12 @@ impl Render for BufferSearchBar {
                     .child(replace_actions)
             });
 
+        let mut key_context = KeyContext::new_with_defaults();
+        key_context.add("BufferSearchBar");
+        if in_replace {
+            key_context.add("in_replace");
+        }
+
         let query_error_line = self.query_error.as_ref().map(|error| {
             Label::new(error)
                 .size(LabelSize::Small)
@@ -398,6 +395,21 @@ impl Render for BufferSearchBar {
                 .ml_2()
         });
 
+        let search_line =
+            h_flex()
+                .relative()
+                .child(search_line)
+                .when(!narrow_mode && !find_in_results, |div| {
+                    div.child(h_flex().absolute().right_0().child(render_action_button(
+                        "buffer-search",
+                        IconName::Close,
+                        true,
+                        "Close Search Bar",
+                        &Dismiss,
+                        focus_handle.clone(),
+                    )))
+                    .w_full()
+                });
         v_flex()
             .id("buffer_search")
             .gap_2()
@@ -416,43 +428,26 @@ impl Render for BufferSearchBar {
                     active_searchable_item.relay_action(Box::new(ToggleOutline), window, cx);
                 }
             }))
-            .when(self.supported_options(cx).replacement, |this| {
+            .when(replacement, |this| {
                 this.on_action(cx.listener(Self::toggle_replace))
                     .when(in_replace, |this| {
                         this.on_action(cx.listener(Self::replace_next))
                             .on_action(cx.listener(Self::replace_all))
                     })
             })
-            .when(self.supported_options(cx).case, |this| {
+            .when(case, |this| {
                 this.on_action(cx.listener(Self::toggle_case_sensitive))
             })
-            .when(self.supported_options(cx).word, |this| {
+            .when(word, |this| {
                 this.on_action(cx.listener(Self::toggle_whole_word))
             })
-            .when(self.supported_options(cx).regex, |this| {
+            .when(regex, |this| {
                 this.on_action(cx.listener(Self::toggle_regex))
             })
-            .when(self.supported_options(cx).selection, |this| {
+            .when(selection, |this| {
                 this.on_action(cx.listener(Self::toggle_selection))
             })
-            .child(h_flex().relative().child(search_line.w_full()).when(
-                !narrow_mode && !supported_options.find_in_results,
-                |div| {
-                    div.child(
-                        h_flex().absolute().right_0().child(
-                            IconButton::new(SharedString::from("Close"), IconName::Close)
-                                .shape(IconButtonShape::Square)
-                                .tooltip(move |window, cx| {
-                                    Tooltip::for_action("Close Search Bar", &Dismiss, window, cx)
-                                })
-                                .on_click(cx.listener(|this, _: &ClickEvent, window, cx| {
-                                    this.dismiss(&Dismiss, window, cx)
-                                })),
-                        ),
-                    )
-                    .w_full()
-                },
-            ))
+            .child(search_line)
             .children(query_error_line)
             .children(replace_line)
     }
@@ -882,16 +877,6 @@ impl BufferSearchBar {
         self.update_matches(!updated, window, cx)
     }
 
-    fn render_search_option_button<Action: Fn(&ClickEvent, &mut Window, &mut App) + 'static>(
-        &self,
-        option: SearchOptions,
-        focus_handle: FocusHandle,
-        action: Action,
-    ) -> impl IntoElement + use<Action> {
-        let is_active = self.search_options.contains(option);
-        option.as_button(is_active, focus_handle, action)
-    }
-
     pub fn focus_editor(&mut self, _: &FocusEditor, window: &mut Window, cx: &mut Context<Self>) {
         if let Some(active_editor) = self.active_searchable_item.as_ref() {
             let handle = active_editor.item_focus_handle(cx);

crates/search/src/project_search.rs 🔗

@@ -2130,6 +2130,45 @@ impl Render for ProjectSearchBar {
         });
 
         let filter_line = search.filters_enabled.then(|| {
+            let include = input_base_styles(BaseStyle::MultipleInputs, InputPanel::Include)
+                .on_action(cx.listener(|this, action, window, cx| {
+                    this.previous_history_query(action, window, cx)
+                }))
+                .on_action(cx.listener(|this, action, window, cx| {
+                    this.next_history_query(action, window, cx)
+                }))
+                .child(render_text_input(&search.included_files_editor, None, cx));
+            let exclude = input_base_styles(BaseStyle::MultipleInputs, InputPanel::Exclude)
+                .on_action(cx.listener(|this, action, window, cx| {
+                    this.previous_history_query(action, window, cx)
+                }))
+                .on_action(cx.listener(|this, action, window, cx| {
+                    this.next_history_query(action, window, cx)
+                }))
+                .child(render_text_input(&search.excluded_files_editor, None, cx));
+            let mode_column = h_flex()
+                .gap_1()
+                .min_w_64()
+                .child(
+                    IconButton::new("project-search-opened-only", IconName::FolderSearch)
+                        .shape(IconButtonShape::Square)
+                        .toggle_state(self.is_opened_only_enabled(cx))
+                        .tooltip(Tooltip::text("Only Search Open Files"))
+                        .on_click(cx.listener(|this, _, window, cx| {
+                            this.toggle_opened_only(window, cx);
+                        })),
+                )
+                .child(
+                    SearchOptions::INCLUDE_IGNORED.as_button(
+                        search
+                            .search_options
+                            .contains(SearchOptions::INCLUDE_IGNORED),
+                        focus_handle.clone(),
+                        cx.listener(|this, _, window, cx| {
+                            this.toggle_search_option(SearchOptions::INCLUDE_IGNORED, window, cx);
+                        }),
+                    ),
+                );
             h_flex()
                 .w_full()
                 .gap_2()
@@ -2137,62 +2176,14 @@ impl Render for ProjectSearchBar {
                     h_flex()
                         .gap_2()
                         .w(input_width)
-                        .child(
-                            input_base_styles(BaseStyle::MultipleInputs, InputPanel::Include)
-                                .on_action(cx.listener(|this, action, window, cx| {
-                                    this.previous_history_query(action, window, cx)
-                                }))
-                                .on_action(cx.listener(|this, action, window, cx| {
-                                    this.next_history_query(action, window, cx)
-                                }))
-                                .child(render_text_input(&search.included_files_editor, None, cx)),
-                        )
-                        .child(
-                            input_base_styles(BaseStyle::MultipleInputs, InputPanel::Exclude)
-                                .on_action(cx.listener(|this, action, window, cx| {
-                                    this.previous_history_query(action, window, cx)
-                                }))
-                                .on_action(cx.listener(|this, action, window, cx| {
-                                    this.next_history_query(action, window, cx)
-                                }))
-                                .child(render_text_input(&search.excluded_files_editor, None, cx)),
-                        ),
-                )
-                .child(
-                    h_flex()
-                        .min_w_64()
-                        .gap_1()
-                        .child(
-                            IconButton::new("project-search-opened-only", IconName::FolderSearch)
-                                .shape(IconButtonShape::Square)
-                                .toggle_state(self.is_opened_only_enabled(cx))
-                                .tooltip(Tooltip::text("Only Search Open Files"))
-                                .on_click(cx.listener(|this, _, window, cx| {
-                                    this.toggle_opened_only(window, cx);
-                                })),
-                        )
-                        .child(
-                            SearchOptions::INCLUDE_IGNORED.as_button(
-                                search
-                                    .search_options
-                                    .contains(SearchOptions::INCLUDE_IGNORED),
-                                focus_handle.clone(),
-                                cx.listener(|this, _, window, cx| {
-                                    this.toggle_search_option(
-                                        SearchOptions::INCLUDE_IGNORED,
-                                        window,
-                                        cx,
-                                    );
-                                }),
-                            ),
-                        ),
+                        .child(include)
+                        .child(exclude),
                 )
+                .child(mode_column)
         });
 
         let mut key_context = KeyContext::default();
-
         key_context.add("ProjectSearchBar");
-
         if search
             .replacement_editor
             .focus_handle(cx)