This PR changes ways the Find/Replace functionality in the Buffer/Project Search is accessible via shortcuts. It makes those panels work the same way as in VS Code and Sublime Text. The details are described in the issue: [Make Find/Replace easier to use](https://github.com/zed-industries/zed/issues/9142) There's a difficulty with the Linux keybindings: VS Code uses on MacOS (this PR replicates it): | Action | Buffer Search | Project Search | | --- | --- | --- | | Find | `cmd-f` | `cmd-shift-f` | | Replace | `cmd-alt-f` | `cmd-shift-h` | VS Code uses on Linux (this PR replicates all but one): | Action | Buffer Search | Project Search | | --- | --- | --- | | Find | `ctrl-f` | `ctrl-shift-f` | | Replace | `ctrl-h` ❗ | `ctrl-shift-h` | The problem is that `ctrl-h` is already taken by the `editor::Backspace` action in Zed on Linux. There's two options here: 1. Change keybinding for `editor::Backspace` on Linux to something else, and use `ctrl-h` for the "replace in buffer" action. 2. Use some other keybinding on Linux in Zed. This PR introduces `ctrl-r` for this purpose, though I'm not sure it's the best choice. What do you think? fixes #9142 Release Notes: - Improved access to "Find/Replace in Buffer" and "Find/Replace in Files" via shortcuts (#9142). Optionally, include screenshots / media showcasing your addition that can be included in the release notes. - N/A
Unified · Split
| @@ -28,7 +28,7 @@ · 27 unmodified lines | |||
| 28 | "ctrl-0": "zed::ResetBufferFontSize", | 28 | "ctrl-0": "zed::ResetBufferFontSize", |
| 29 | "ctrl-,": "zed::OpenSettings", | 29 | "ctrl-,": "zed::OpenSettings", |
| 30 | "ctrl-q": "zed::Quit", | 30 | "ctrl-q": "zed::Quit", |
| 31 | "ctrl-h": "zed::Hide", | 31 | "alt-f9": "zed::Hide", |
| 32 | "f11": "zed::ToggleFullScreen" | 32 | "f11": "zed::ToggleFullScreen" |
| 33 | } | 33 | } |
| 34 | }, | 34 | }, |
| @@ -38,7 +38,6 @@ · 3 unmodified lines | |||
| 38 | "escape": "editor::Cancel", | 38 | "escape": "editor::Cancel", |
| 39 | "backspace": "editor::Backspace", | 39 | "backspace": "editor::Backspace", |
| 40 | "shift-backspace": "editor::Backspace", | 40 | "shift-backspace": "editor::Backspace", |
| 41 | "ctrl-h": "editor::Backspace", | ||
| 42 | "delete": "editor::Delete", | 41 | "delete": "editor::Delete", |
| 43 | "ctrl-d": "editor::Delete", | 42 | "ctrl-d": "editor::Delete", |
| 44 | "tab": "editor::Tab", | 43 | "tab": "editor::Tab", |
| @@ -150,10 +149,11 @@ · 105 unmodified lines | |||
| 150 | "ctrl-shift-enter": "editor::NewlineBelow", | 149 | "ctrl-shift-enter": "editor::NewlineBelow", |
| 151 | "ctrl-enter": "editor::NewlineAbove", | 150 | "ctrl-enter": "editor::NewlineAbove", |
| 152 | "alt-z": "editor::ToggleSoftWrap", | 151 | "alt-z": "editor::ToggleSoftWrap", |
| 153 | "ctrl-f": [ | 152 | "ctrl-f": "buffer_search::Deploy", |
| 153 | "ctrl-h": [ | ||
| 154 | "buffer_search::Deploy", | 154 | "buffer_search::Deploy", |
| 155 | { | 155 | { |
| 156 | "focus": true | 156 | "replace_enabled": true |
| 157 | } | 157 | } |
| 158 | ], | 158 | ], |
| 159 | // "cmd-e": [ | 159 | // "cmd-e": [ |
| @@ -212,7 +212,9 @@ · 52 unmodified lines | |||
| 212 | "enter": "search::SelectNextMatch", | 212 | "enter": "search::SelectNextMatch", |
| 213 | "shift-enter": "search::SelectPrevMatch", | 213 | "shift-enter": "search::SelectPrevMatch", |
| 214 | "alt-enter": "search::SelectAllMatches", | 214 | "alt-enter": "search::SelectAllMatches", |
| 215 | "alt-tab": "search::CycleMode" | 215 | "alt-tab": "search::CycleMode", |
| 216 | "ctrl-f": "search::FocusSearch", | ||
| 217 | "ctrl-h": "search::ToggleReplace" | ||
| 216 | } | 218 | } |
| 217 | }, | 219 | }, |
| 218 | { | 220 | { |
| @@ -234,6 +236,7 @@ · 15 unmodified lines | |||
| 234 | "bindings": { | 236 | "bindings": { |
| 235 | "escape": "project_search::ToggleFocus", | 237 | "escape": "project_search::ToggleFocus", |
| 236 | "alt-tab": "search::CycleMode", | 238 | "alt-tab": "search::CycleMode", |
| 239 | "ctrl-shift-f": "search::FocusSearch", | ||
| 237 | "ctrl-shift-h": "search::ToggleReplace", | 240 | "ctrl-shift-h": "search::ToggleReplace", |
| 238 | "alt-ctrl-g": "search::ActivateRegexMode", | 241 | "alt-ctrl-g": "search::ActivateRegexMode", |
| 239 | "alt-ctrl-x": "search::ActivateTextMode" | 242 | "alt-ctrl-x": "search::ActivateTextMode" |
| @@ -419,6 +422,12 @@ · 179 unmodified lines | |||
| 419 | "ctrl-j": "workspace::ToggleBottomDock", | 422 | "ctrl-j": "workspace::ToggleBottomDock", |
| 420 | "ctrl-alt-y": "workspace::CloseAllDocks", | 423 | "ctrl-alt-y": "workspace::CloseAllDocks", |
| 421 | "ctrl-shift-f": "pane::DeploySearch", | 424 | "ctrl-shift-f": "pane::DeploySearch", |
| 425 | "ctrl-shift-h": [ | ||
| 426 | "pane::DeploySearch", | ||
| 427 | { | ||
| 428 | "replace_enabled": true | ||
| 429 | } | ||
| 430 | ], | ||
| 422 | "ctrl-k ctrl-s": "zed::OpenKeymap", | 431 | "ctrl-k ctrl-s": "zed::OpenKeymap", |
| 423 | "ctrl-k ctrl-t": "theme_selector::Toggle", | 432 | "ctrl-k ctrl-t": "theme_selector::Toggle", |
| 424 | "ctrl-shift-t": "project_symbols::Toggle", | 433 | "ctrl-shift-t": "project_symbols::Toggle", |
| @@ -170,10 +170,11 @@ · 169 unmodified lines | |||
| 170 | "cmd-shift-enter": "editor::NewlineAbove", | 170 | "cmd-shift-enter": "editor::NewlineAbove", |
| 171 | "cmd-enter": "editor::NewlineBelow", | 171 | "cmd-enter": "editor::NewlineBelow", |
| 172 | "alt-z": "editor::ToggleSoftWrap", | 172 | "alt-z": "editor::ToggleSoftWrap", |
| 173 | "cmd-f": [ | 173 | "cmd-f": "buffer_search::Deploy", |
| 174 | "cmd-alt-f": [ | ||
| 174 | "buffer_search::Deploy", | 175 | "buffer_search::Deploy", |
| 175 | { | 176 | { |
| 176 | "focus": true | 177 | "replace_enabled": true |
| 177 | } | 178 | } |
| 178 | ], | 179 | ], |
| 179 | "cmd-e": [ | 180 | "cmd-e": [ |
| @@ -232,7 +233,9 @@ · 52 unmodified lines | |||
| 232 | "enter": "search::SelectNextMatch", | 233 | "enter": "search::SelectNextMatch", |
| 233 | "shift-enter": "search::SelectPrevMatch", | 234 | "shift-enter": "search::SelectPrevMatch", |
| 234 | "alt-enter": "search::SelectAllMatches", | 235 | "alt-enter": "search::SelectAllMatches", |
| 235 | "alt-tab": "search::CycleMode" | 236 | "alt-tab": "search::CycleMode", |
| 237 | "cmd-f": "search::FocusSearch", | ||
| 238 | "cmd-alt-f": "search::ToggleReplace" | ||
| 236 | } | 239 | } |
| 237 | }, | 240 | }, |
| 238 | { | 241 | { |
| @@ -254,6 +257,7 @@ · 15 unmodified lines | |||
| 254 | "bindings": { | 257 | "bindings": { |
| 255 | "escape": "project_search::ToggleFocus", | 258 | "escape": "project_search::ToggleFocus", |
| 256 | "alt-tab": "search::CycleMode", | 259 | "alt-tab": "search::CycleMode", |
| 260 | "cmd-shift-f": "search::FocusSearch", | ||
| 257 | "cmd-shift-h": "search::ToggleReplace", | 261 | "cmd-shift-h": "search::ToggleReplace", |
| 258 | "alt-cmd-g": "search::ActivateRegexMode", | 262 | "alt-cmd-g": "search::ActivateRegexMode", |
| 259 | "alt-cmd-x": "search::ActivateTextMode" | 263 | "alt-cmd-x": "search::ActivateTextMode" |
| @@ -436,6 +440,12 @@ · 176 unmodified lines | |||
| 436 | "cmd-j": "workspace::ToggleBottomDock", | 440 | "cmd-j": "workspace::ToggleBottomDock", |
| 437 | "alt-cmd-y": "workspace::CloseAllDocks", | 441 | "alt-cmd-y": "workspace::CloseAllDocks", |
| 438 | "cmd-shift-f": "pane::DeploySearch", | 442 | "cmd-shift-f": "pane::DeploySearch", |
| 443 | "cmd-shift-h": [ | ||
| 444 | "pane::DeploySearch", | ||
| 445 | { | ||
| 446 | "replace_enabled": true | ||
| 447 | } | ||
| 448 | ], | ||
| 439 | "cmd-k cmd-s": "zed::OpenKeymap", | 449 | "cmd-k cmd-s": "zed::OpenKeymap", |
| 440 | "cmd-k cmd-t": "theme_selector::Toggle", | 450 | "cmd-k cmd-t": "theme_selector::Toggle", |
| 441 | "cmd-t": "project_symbols::Toggle", | 451 | "cmd-t": "project_symbols::Toggle", |
| @@ -91,13 +91,13 @@ impl Render for QuickActionBar { · 90 unmodified lines | |||
| 91 | "toggle buffer search", | 91 | "toggle buffer search", |
| 92 | IconName::MagnifyingGlass, | 92 | IconName::MagnifyingGlass, |
| 93 | !self.buffer_search_bar.read(cx).is_dismissed(), | 93 | !self.buffer_search_bar.read(cx).is_dismissed(), |
| 94 | Box::new(buffer_search::Deploy { focus: false }), | 94 | Box::new(buffer_search::Deploy::find()), |
| 95 | "Buffer Search", | 95 | "Buffer Search", |
| 96 | { | 96 | { |
| 97 | let buffer_search_bar = self.buffer_search_bar.clone(); | 97 | let buffer_search_bar = self.buffer_search_bar.clone(); |
| 98 | move |_, cx| { | 98 | move |_, cx| { |
| 99 | buffer_search_bar.update(cx, |search_bar, cx| { | 99 | buffer_search_bar.update(cx, |search_bar, cx| { |
| 100 | search_bar.toggle(&buffer_search::Deploy { focus: true }, cx) | 100 | search_bar.toggle(&buffer_search::Deploy::find(), cx) |
| 101 | }); | 101 | }); |
| 102 | } | 102 | } |
| 103 | }, | 103 | }, |
| @@ -3,9 +3,9 @@ mod registrar; · 2 unmodified lines | |||
| 3 | use crate::{ | 3 | use crate::{ |
| 4 | mode::{next_mode, SearchMode}, | 4 | mode::{next_mode, SearchMode}, |
| 5 | search_bar::render_nav_button, | 5 | search_bar::render_nav_button, |
| 6 | ActivateRegexMode, ActivateTextMode, CycleMode, NextHistoryQuery, PreviousHistoryQuery, | 6 | ActivateRegexMode, ActivateTextMode, CycleMode, FocusSearch, NextHistoryQuery, |
| 7 | ReplaceAll, ReplaceNext, SearchOptions, SelectAllMatches, SelectNextMatch, SelectPrevMatch, | 7 | PreviousHistoryQuery, ReplaceAll, ReplaceNext, SearchOptions, SelectAllMatches, |
| 8 | ToggleCaseSensitive, ToggleReplace, ToggleWholeWord, | 8 | SelectNextMatch, SelectPrevMatch, ToggleCaseSensitive, ToggleReplace, ToggleWholeWord, |
| 9 | }; | 9 | }; |
| 10 | use any_vec::AnyVec; | 10 | use any_vec::AnyVec; |
| 11 | use collections::HashMap; | 11 | use collections::HashMap; |
| @@ -44,15 +44,31 @@ const MIN_INPUT_WIDTH_REMS: f32 = 15.; · 32 unmodified lines | |||
| 44 | const MAX_INPUT_WIDTH_REMS: f32 = 30.; | 44 | const MAX_INPUT_WIDTH_REMS: f32 = 30.; |
| 45 | const MAX_BUFFER_SEARCH_HISTORY_SIZE: usize = 50; | 45 | const MAX_BUFFER_SEARCH_HISTORY_SIZE: usize = 50; |
| 46 | 46 | ||
| 47 | const fn true_value() -> bool { | ||
| 48 | true | ||
| 49 | } | ||
| 50 | |||
| 47 | #[derive(PartialEq, Clone, Deserialize)] | 51 | #[derive(PartialEq, Clone, Deserialize)] |
| 48 | pub struct Deploy { | 52 | pub struct Deploy { |
| 53 | #[serde(default = "true_value")] | ||
| 49 | pub focus: bool, | 54 | pub focus: bool, |
| 55 | #[serde(default)] | ||
| 56 | pub replace_enabled: bool, | ||
| 50 | } | 57 | } |
| 51 | 58 | ||
| 52 | impl_actions!(buffer_search, [Deploy]); | 59 | impl_actions!(buffer_search, [Deploy]); |
| 53 | 60 | ||
| 54 | actions!(buffer_search, [Dismiss, FocusEditor]); | 61 | actions!(buffer_search, [Dismiss, FocusEditor]); |
| 55 | 62 | ||
| 63 | impl Deploy { | ||
| 64 | pub fn find() -> Self { | ||
| 65 | Self { | ||
| 66 | focus: true, | ||
| 67 | replace_enabled: false, | ||
| 68 | } | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 56 | pub enum Event { | 72 | pub enum Event { |
| 57 | UpdateLocation, | 73 | UpdateLocation, |
| 58 | } | 74 | } |
| @@ -470,6 +486,9 @@ impl ToolbarItemView for BufferSearchBar { · 411 unmodified lines | |||
| 470 | 486 | ||
| 471 | impl BufferSearchBar { | 487 | impl BufferSearchBar { |
| 472 | pub fn register(registrar: &mut impl SearchActionsRegistrar) { | 488 | pub fn register(registrar: &mut impl SearchActionsRegistrar) { |
| 489 | registrar.register_handler(ForDeployed(|this, _: &FocusSearch, cx| { | ||
| 490 | this.query_editor.focus_handle(cx).focus(cx); | ||
| 491 | })); | ||
| 473 | registrar.register_handler(ForDeployed(|this, action: &ToggleCaseSensitive, cx| { | 492 | registrar.register_handler(ForDeployed(|this, action: &ToggleCaseSensitive, cx| { |
| 474 | if this.supported_options().case { | 493 | if this.supported_options().case { |
| 475 | this.toggle_case_sensitive(action, cx); | 494 | this.toggle_case_sensitive(action, cx); |
| @@ -583,9 +602,17 @@ impl BufferSearchBar { · 107 unmodified lines | |||
| 583 | pub fn deploy(&mut self, deploy: &Deploy, cx: &mut ViewContext<Self>) -> bool { | 602 | pub fn deploy(&mut self, deploy: &Deploy, cx: &mut ViewContext<Self>) -> bool { |
| 584 | if self.show(cx) { | 603 | if self.show(cx) { |
| 585 | self.search_suggested(cx); | 604 | self.search_suggested(cx); |
| 605 | self.replace_enabled = deploy.replace_enabled; | ||
| 586 | if deploy.focus { | 606 | if deploy.focus { |
| 587 | self.select_query(cx); | 607 | let mut handle = self.query_editor.focus_handle(cx).clone(); |
| 588 | let handle = self.query_editor.focus_handle(cx); | 608 | let mut select_query = true; |
| 609 | if deploy.replace_enabled && handle.is_focused(cx) { | ||
| 610 | handle = self.replacement_editor.focus_handle(cx).clone(); | ||
| 611 | select_query = false; | ||
| 612 | }; | ||
| 613 | if select_query { | ||
| 614 | self.select_query(cx); | ||
| 615 | } | ||
| 589 | cx.focus(&handle); | 616 | cx.focus(&handle); |
| 590 | } | 617 | } |
| 591 | return true; | 618 | return true; |
| @@ -1,7 +1,8 @@ | |||
| 1 | use crate::{ | 1 | use crate::{ |
| 2 | mode::SearchMode, ActivateRegexMode, ActivateTextMode, CycleMode, NextHistoryQuery, | 2 | mode::SearchMode, ActivateRegexMode, ActivateTextMode, CycleMode, FocusSearch, |
| 3 | PreviousHistoryQuery, ReplaceAll, ReplaceNext, SearchOptions, SelectNextMatch, SelectPrevMatch, | 3 | NextHistoryQuery, PreviousHistoryQuery, ReplaceAll, ReplaceNext, SearchOptions, |
| 4 | ToggleCaseSensitive, ToggleIncludeIgnored, ToggleReplace, ToggleWholeWord, | 4 | SelectNextMatch, SelectPrevMatch, ToggleCaseSensitive, ToggleIncludeIgnored, ToggleReplace, |
| 5 | ToggleWholeWord, | ||
| 5 | }; | 6 | }; |
| 6 | use anyhow::Context as _; | 7 | use anyhow::Context as _; |
| 7 | use collections::{HashMap, HashSet}; | 8 | use collections::{HashMap, HashSet}; |
| @@ -60,6 +61,9 @@ const SEARCH_CONTEXT: u32 = 2; · 52 unmodified lines | |||
| 60 | pub fn init(cx: &mut AppContext) { | 61 | pub fn init(cx: &mut AppContext) { |
| 61 | cx.set_global(ActiveSettings::default()); | 62 | cx.set_global(ActiveSettings::default()); |
| 62 | cx.observe_new_views(|workspace: &mut Workspace, _cx| { | 63 | cx.observe_new_views(|workspace: &mut Workspace, _cx| { |
| 64 | register_workspace_action(workspace, move |search_bar, _: &FocusSearch, cx| { | ||
| 65 | search_bar.focus_search(cx); | ||
| 66 | }); | ||
| 63 | register_workspace_action(workspace, move |search_bar, _: &ToggleFilters, cx| { | 67 | register_workspace_action(workspace, move |search_bar, _: &ToggleFilters, cx| { |
| 64 | search_bar.toggle_filters(cx); | 68 | search_bar.toggle_filters(cx); |
| 65 | }); | 69 | }); |
| @@ -797,7 +801,7 @@ impl ProjectSearchView { · 731 unmodified lines | |||
| 797 | // If no search exists in the workspace, create a new one. | 801 | // If no search exists in the workspace, create a new one. |
| 798 | fn deploy_search( | 802 | fn deploy_search( |
| 799 | workspace: &mut Workspace, | 803 | workspace: &mut Workspace, |
| 800 | _: &workspace::DeploySearch, | 804 | action: &workspace::DeploySearch, |
| 801 | cx: &mut ViewContext<Workspace>, | 805 | cx: &mut ViewContext<Workspace>, |
| 802 | ) { | 806 | ) { |
| 803 | let existing = workspace | 807 | let existing = workspace |
| @@ -806,7 +810,7 @@ impl ProjectSearchView { · 2 unmodified lines | |||
| 806 | .items() | 810 | .items() |
| 807 | .find_map(|item| item.downcast::<ProjectSearchView>()); | 811 | .find_map(|item| item.downcast::<ProjectSearchView>()); |
| 808 | 812 | ||
| 809 | Self::existing_or_new_search(workspace, existing, cx) | 813 | Self::existing_or_new_search(workspace, existing, action, cx); |
| 810 | } | 814 | } |
| 811 | 815 | ||
| 812 | fn search_in_new(workspace: &mut Workspace, _: &SearchInNew, cx: &mut ViewContext<Workspace>) { | 816 | fn search_in_new(workspace: &mut Workspace, _: &SearchInNew, cx: &mut ViewContext<Workspace>) { |
| @@ -846,12 +850,13 @@ impl ProjectSearchView { · 33 unmodified lines | |||
| 846 | _: &workspace::NewSearch, | 850 | _: &workspace::NewSearch, |
| 847 | cx: &mut ViewContext<Workspace>, | 851 | cx: &mut ViewContext<Workspace>, |
| 848 | ) { | 852 | ) { |
| 849 | Self::existing_or_new_search(workspace, None, cx) | 853 | Self::existing_or_new_search(workspace, None, &DeploySearch::find(), cx) |
| 850 | } | 854 | } |
| 851 | 855 | ||
| 852 | fn existing_or_new_search( | 856 | fn existing_or_new_search( |
| 853 | workspace: &mut Workspace, | 857 | workspace: &mut Workspace, |
| 854 | existing: Option<View<ProjectSearchView>>, | 858 | existing: Option<View<ProjectSearchView>>, |
| 859 | action: &workspace::DeploySearch, | ||
| 855 | cx: &mut ViewContext<Workspace>, | 860 | cx: &mut ViewContext<Workspace>, |
| 856 | ) { | 861 | ) { |
| 857 | let query = workspace.active_item(cx).and_then(|item| { | 862 | let query = workspace.active_item(cx).and_then(|item| { |
| @@ -887,6 +892,7 @@ impl ProjectSearchView { · 29 unmodified lines | |||
| 887 | }; | 892 | }; |
| 888 | 893 | ||
| 889 | search.update(cx, |search, cx| { | 894 | search.update(cx, |search, cx| { |
| 895 | search.replace_enabled = action.replace_enabled; | ||
| 890 | if let Some(query) = query { | 896 | if let Some(query) = query { |
| 891 | search.set_query(&query, cx); | 897 | search.set_query(&query, cx); |
| 892 | } | 898 | } |
| @@ -1172,6 +1178,14 @@ impl ProjectSearchBar { · 279 unmodified lines | |||
| 1172 | self.cycle_field(Direction::Prev, cx); | 1178 | self.cycle_field(Direction::Prev, cx); |
| 1173 | } | 1179 | } |
| 1174 | 1180 | ||
| 1181 | fn focus_search(&mut self, cx: &mut ViewContext<Self>) { | ||
| 1182 | if let Some(search_view) = self.active_project_search.as_ref() { | ||
| 1183 | search_view.update(cx, |search_view, cx| { | ||
| 1184 | search_view.query_editor.focus_handle(cx).focus(cx); | ||
| 1185 | }); | ||
| 1186 | } | ||
| 1187 | } | ||
| 1188 | |||
| 1175 | fn cycle_field(&mut self, direction: Direction, cx: &mut ViewContext<Self>) { | 1189 | fn cycle_field(&mut self, direction: Direction, cx: &mut ViewContext<Self>) { |
| 1176 | let active_project_search = match &self.active_project_search { | 1190 | let active_project_search = match &self.active_project_search { |
| 1177 | Some(active_project_search) => active_project_search, | 1191 | Some(active_project_search) => active_project_search, |
| @@ -2011,7 +2025,7 @@ pub mod tests { · 833 unmodified lines | |||
| 2011 | .update(cx, |toolbar, cx| toolbar.add_item(search_bar, cx)) | 2025 | .update(cx, |toolbar, cx| toolbar.add_item(search_bar, cx)) |
| 2012 | }); | 2026 | }); |
| 2013 | 2027 | ||
| 2014 | ProjectSearchView::deploy_search(workspace, &workspace::DeploySearch, cx) | 2028 | ProjectSearchView::deploy_search(workspace, &workspace::DeploySearch::find(), cx) |
| 2015 | }) | 2029 | }) |
| 2016 | .unwrap(); | 2030 | .unwrap(); |
| 2017 | 2031 | ||
| @@ -2160,7 +2174,7 @@ pub mod tests { · 142 unmodified lines | |||
| 2160 | 2174 | ||
| 2161 | workspace | 2175 | workspace |
| 2162 | .update(cx, |workspace, cx| { | 2176 | .update(cx, |workspace, cx| { |
| 2163 | ProjectSearchView::deploy_search(workspace, &workspace::DeploySearch, cx) | 2177 | ProjectSearchView::deploy_search(workspace, &workspace::DeploySearch::find(), cx) |
| 2164 | }) | 2178 | }) |
| 2165 | .unwrap(); | 2179 | .unwrap(); |
| 2166 | window.update(cx, |_, cx| { | 2180 | window.update(cx, |_, cx| { |
| @@ -3259,7 +3273,7 @@ pub mod tests { · 1092 unmodified lines | |||
| 3259 | .unwrap(); | 3273 | .unwrap(); |
| 3260 | 3274 | ||
| 3261 | // Deploy a new search | 3275 | // Deploy a new search |
| 3262 | cx.dispatch_action(window.into(), DeploySearch); | 3276 | cx.dispatch_action(window.into(), DeploySearch::find()); |
| 3263 | 3277 | ||
| 3264 | // Both panes should now have a project search in them | 3278 | // Both panes should now have a project search in them |
| 3265 | window | 3279 | window |
| @@ -3284,7 +3298,7 @@ pub mod tests { · 18 unmodified lines | |||
| 3284 | .unwrap(); | 3298 | .unwrap(); |
| 3285 | 3299 | ||
| 3286 | // Deploy a new search | 3300 | // Deploy a new search |
| 3287 | cx.dispatch_action(window.into(), DeploySearch); | 3301 | cx.dispatch_action(window.into(), DeploySearch::find()); |
| 3288 | 3302 | ||
| 3289 | // The project search view should now be focused in the second pane | 3303 | // The project search view should now be focused in the second pane |
| 3290 | // And the number of items should be unchanged. | 3304 | // And the number of items should be unchanged. |
| @@ -22,6 +22,7 @@ actions!( · 21 unmodified lines | |||
| 22 | search, | 22 | search, |
| 23 | [ | 23 | [ |
| 24 | CycleMode, | 24 | CycleMode, |
| 25 | FocusSearch, | ||
| 25 | ToggleWholeWord, | 26 | ToggleWholeWord, |
| 26 | ToggleCaseSensitive, | 27 | ToggleCaseSensitive, |
| 27 | ToggleIncludeIgnored, | 28 | ToggleIncludeIgnored, |
| @@ -86,6 +86,12 @@ pub struct RevealInProjectPanel { · 85 unmodified lines | |||
| 86 | pub entry_id: Option<u64>, | 86 | pub entry_id: Option<u64>, |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | #[derive(PartialEq, Clone, Deserialize)] | ||
| 90 | pub struct DeploySearch { | ||
| 91 | #[serde(default)] | ||
| 92 | pub replace_enabled: bool, | ||
| 93 | } | ||
| 94 | |||
| 89 | impl_actions!( | 95 | impl_actions!( |
| 90 | pane, | 96 | pane, |
| 91 | [ | 97 | [ |
| @@ -93,7 +99,8 @@ impl_actions!( · 1 unmodified line | |||
| 93 | CloseActiveItem, | 99 | CloseActiveItem, |
| 94 | CloseInactiveItems, | 100 | CloseInactiveItems, |
| 95 | ActivateItem, | 101 | ActivateItem, |
| 96 | RevealInProjectPanel | 102 | RevealInProjectPanel, |
| 103 | DeploySearch, | ||
| 97 | ] | 104 | ] |
| 98 | ); | 105 | ); |
| 99 | 106 | ||
| @@ -107,7 +114,6 @@ actions!( · 7 unmodified lines | |||
| 107 | CloseItemsToTheLeft, | 114 | CloseItemsToTheLeft, |
| 108 | CloseItemsToTheRight, | 115 | CloseItemsToTheRight, |
| 109 | GoBack, | 116 | GoBack, |
| 110 | DeploySearch, | ||
| 111 | GoForward, | 117 | GoForward, |
| 112 | ReopenClosedItem, | 118 | ReopenClosedItem, |
| 113 | SplitLeft, | 119 | SplitLeft, |
| @@ -117,6 +123,14 @@ actions!( · 3 unmodified lines | |||
| 117 | ] | 123 | ] |
| 118 | ); | 124 | ); |
| 119 | 125 | ||
| 126 | impl DeploySearch { | ||
| 127 | pub fn find() -> Self { | ||
| 128 | Self { | ||
| 129 | replace_enabled: false, | ||
| 130 | } | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 120 | const MAX_NAVIGATION_HISTORY_LEN: usize = 1024; | 134 | const MAX_NAVIGATION_HISTORY_LEN: usize = 1024; |
| 121 | 135 | ||
| 122 | pub enum Event { | 136 | pub enum Event { |
| @@ -67,7 +67,7 @@ pub fn app_menus() -> Vec<Menu<'static>> { · 66 unmodified lines | |||
| 67 | MenuItem::os_action("Copy", editor::actions::Copy, OsAction::Copy), | 67 | MenuItem::os_action("Copy", editor::actions::Copy, OsAction::Copy), |
| 68 | MenuItem::os_action("Paste", editor::actions::Paste, OsAction::Paste), | 68 | MenuItem::os_action("Paste", editor::actions::Paste, OsAction::Paste), |
| 69 | MenuItem::separator(), | 69 | MenuItem::separator(), |
| 70 | MenuItem::action("Find", search::buffer_search::Deploy { focus: true }), | 70 | MenuItem::action("Find", search::buffer_search::Deploy::find()), |
| 71 | MenuItem::action("Find In Project", workspace::NewSearch), | 71 | MenuItem::action("Find In Project", workspace::NewSearch), |
| 72 | MenuItem::separator(), | 72 | MenuItem::separator(), |
| 73 | MenuItem::action( | 73 | MenuItem::action( |