diff --git a/Cargo.lock b/Cargo.lock index 42649b137f..5017c42b6f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14568,6 +14568,7 @@ dependencies = [ "client", "collections", "editor", + "fancy-regex 0.14.0", "futures 0.3.31", "gpui", "language", diff --git a/crates/search/Cargo.toml b/crates/search/Cargo.toml index 613f229d4d..20a69694dd 100644 --- a/crates/search/Cargo.toml +++ b/crates/search/Cargo.toml @@ -42,6 +42,7 @@ util.workspace = true workspace.workspace = true zed_actions.workspace = true workspace-hack.workspace = true +fancy-regex.workspace = true [dev-dependencies] client = { workspace = true, features = ["test-support"] } diff --git a/crates/search/src/buffer_search.rs b/crates/search/src/buffer_search.rs index ad412e556a..591981818f 100644 --- a/crates/search/src/buffer_search.rs +++ b/crates/search/src/buffer_search.rs @@ -13,6 +13,7 @@ use editor::{ DisplayPoint, Editor, EditorSettings, actions::{Backtab, Tab}, }; +use fancy_regex::Regex; use futures::channel::oneshot; use gpui::{ Action, App, ClickEvent, Context, Entity, EventEmitter, Focusable, InteractiveElement as _, @@ -45,6 +46,11 @@ pub use registrar::DivRegistrar; use registrar::{ForDeployed, ForDismissed, SearchActionsRegistrar, WithResults}; const MAX_BUFFER_SEARCH_HISTORY_SIZE: usize = 50; + +/// Array of supported pattern items and their corresponding search options and +/// value. +/// When any of the patterns is present in the search query, the corresponding +/// search option, and value, is applied. static PATTERN_ITEMS: [(&str, &SearchOptions, bool); 2] = [ ("\\c", &SearchOptions::CASE_SENSITIVE, false), ("\\C", &SearchOptions::CASE_SENSITIVE, true), @@ -126,6 +132,7 @@ pub struct BufferSearchBar { editor_scroll_handle: ScrollHandle, editor_needed_width: Pixels, regex_language: Option>, + pattern_items_regex: Regex, } impl BufferSearchBar { @@ -647,6 +654,15 @@ impl BufferSearchBar { .detach_and_log_err(cx); } + let pattern_items_regex = Regex::new( + &PATTERN_ITEMS + .iter() + .map(|(pattern, _, _)| fancy_regex::escape(pattern)) + .collect::>() + .join("|"), + ) + .unwrap(); + Self { query_editor, query_editor_focused: false, @@ -674,6 +690,7 @@ impl BufferSearchBar { editor_scroll_handle: ScrollHandle::new(), editor_needed_width: px(0.), regex_language: None, + pattern_items_regex, } } @@ -821,13 +838,9 @@ impl BufferSearchBar { /// Returns the sanitized query string with pattern items removed. pub fn query(&self, cx: &App) -> String { - // TODO: Probably replace this with a regex (\\[cC])? I assume - // performance is going to be not so great with a big list of pattern - // items. - PATTERN_ITEMS.iter().fold( - self.query_editor.read(cx).text(cx), - |string, (pattern, _, _)| string.replace(pattern, ""), - ) + self.pattern_items_regex + .replace_all(&self.raw_query(cx), "") + .into_owned() } pub fn replacement(&self, cx: &mut App) -> String {