diff --git a/crates/project/src/search.rs b/crates/project/src/search.rs index 71a0b70b81..08ff803598 100644 --- a/crates/project/src/search.rs +++ b/crates/project/src/search.rs @@ -13,24 +13,39 @@ use std::{ sync::Arc, }; +#[derive(Clone, Debug)] +pub struct SearchInputs { + query: Arc, + files_to_include: Vec, + files_to_exclude: Vec, +} + +impl SearchInputs { + pub fn as_str(&self) -> &str { + self.query.as_ref() + } + pub fn files_to_include(&self) -> &[PathMatcher] { + &self.files_to_include + } + pub fn files_to_exclude(&self) -> &[PathMatcher] { + &self.files_to_exclude + } +} #[derive(Clone, Debug)] pub enum SearchQuery { Text { search: Arc>, - query: Arc, whole_word: bool, case_sensitive: bool, - files_to_include: Vec, - files_to_exclude: Vec, + inner: SearchInputs, }, Regex { regex: Regex, - query: Arc, + multiline: bool, whole_word: bool, case_sensitive: bool, - files_to_include: Vec, - files_to_exclude: Vec, + inner: SearchInputs, }, } @@ -72,13 +87,16 @@ impl SearchQuery { .auto_configure(&[&query]) .ascii_case_insensitive(!case_sensitive) .build(&[&query]); + let inner = SearchInputs { + query: query.into(), + files_to_exclude, + files_to_include, + }; Self::Text { search: Arc::new(search), - query: Arc::from(query), whole_word, case_sensitive, - files_to_include, - files_to_exclude, + inner, } } @@ -104,14 +122,17 @@ impl SearchQuery { .case_insensitive(!case_sensitive) .multi_line(multiline) .build()?; + let inner = SearchInputs { + query: initial_query, + files_to_exclude, + files_to_include, + }; Ok(Self::Regex { regex, - query: initial_query, multiline, whole_word, case_sensitive, - files_to_include, - files_to_exclude, + inner, }) } @@ -267,10 +288,7 @@ impl SearchQuery { } pub fn as_str(&self) -> &str { - match self { - Self::Text { query, .. } => query.as_ref(), - Self::Regex { query, .. } => query.as_ref(), - } + self.as_inner().as_str() } pub fn whole_word(&self) -> bool { @@ -292,25 +310,11 @@ impl SearchQuery { } pub fn files_to_include(&self) -> &[PathMatcher] { - match self { - Self::Text { - files_to_include, .. - } => files_to_include, - Self::Regex { - files_to_include, .. - } => files_to_include, - } + self.as_inner().files_to_include() } pub fn files_to_exclude(&self) -> &[PathMatcher] { - match self { - Self::Text { - files_to_exclude, .. - } => files_to_exclude, - Self::Regex { - files_to_exclude, .. - } => files_to_exclude, - } + self.as_inner().files_to_exclude() } pub fn file_matches(&self, file_path: Option<&Path>) -> bool { @@ -329,6 +333,11 @@ impl SearchQuery { None => self.files_to_include().is_empty(), } } + pub fn as_inner(&self) -> &SearchInputs { + match self { + Self::Regex { inner, .. } | Self::Text { inner, .. } => inner, + } + } } fn deserialize_path_matches(glob_set: &str) -> anyhow::Result> { diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index 323c33bc56..6535c257e2 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -24,7 +24,7 @@ use gpui::{ use menu::Confirm; use postage::stream::Stream; use project::{ - search::{PathMatcher, SearchQuery}, + search::{PathMatcher, SearchInputs, SearchQuery}, Entry, Project, }; use semantic_index::SemanticIndex; @@ -177,10 +177,12 @@ impl ProjectSearch { } fn kill_search(&mut self) { + dbg!("Killing search"); self.active_query = None; self.match_ranges.clear(); self.pending_search = None; self.no_results = None; + dbg!("Killed search"); } fn search(&mut self, query: SearchQuery, cx: &mut ModelContext) { @@ -226,22 +228,22 @@ impl ProjectSearch { cx.notify(); } - fn semantic_search(&mut self, query: SearchQuery, cx: &mut ModelContext) { + fn semantic_search(&mut self, inputs: &SearchInputs, cx: &mut ModelContext) { let search = SemanticIndex::global(cx).map(|index| { index.update(cx, |semantic_index, cx| { semantic_index.search_project( self.project.clone(), - query.as_str().to_owned(), + inputs.as_str().to_owned(), 10, - query.files_to_include().to_vec(), - query.files_to_exclude().to_vec(), + inputs.files_to_include().to_vec(), + inputs.files_to_exclude().to_vec(), cx, ) }) }); self.search_id += 1; self.match_ranges.clear(); - self.search_history.add(query.as_str().to_string()); + self.search_history.add(inputs.as_str().to_string()); self.no_results = Some(true); self.pending_search = Some(cx.spawn(|this, mut cx| async move { let results = search?.await.log_err()?; @@ -682,6 +684,7 @@ impl ProjectSearchView { fn activate_search_mode(&mut self, mode: SearchMode, cx: &mut ViewContext) { let previous_mode = self.current_mode; + log::error!("Going from {previous_mode:?} to {:?}", mode); if previous_mode == mode { return; } @@ -690,6 +693,7 @@ impl ProjectSearchView { match mode { SearchMode::Semantic => { + dbg!("Matched on Semantic"); let has_permission = self.semantic_permissioned(cx); self.active_match_index = None; cx.spawn(|this, mut cx| async move { @@ -947,7 +951,7 @@ impl ProjectSearchView { if let Some(query) = self.build_search_query(cx) { self.model - .update(cx, |model, cx| model.semantic_search(query, cx)); + .update(cx, |model, cx| model.semantic_search(query.as_inner(), cx)); } } } @@ -986,33 +990,34 @@ impl ProjectSearchView { return None; } }; - if self.current_mode == SearchMode::Regex { - match SearchQuery::regex( - text, - self.search_options.contains(SearchOptions::WHOLE_WORD), - self.search_options.contains(SearchOptions::CASE_SENSITIVE), - included_files, - excluded_files, - ) { - Ok(query) => { - self.panels_with_errors.remove(&InputPanel::Query); - Some(query) - } - Err(_e) => { - self.panels_with_errors.insert(InputPanel::Query); - cx.notify(); - None + let current_mode = self.current_mode; + match current_mode { + SearchMode::Regex => { + match SearchQuery::regex( + text, + self.search_options.contains(SearchOptions::WHOLE_WORD), + self.search_options.contains(SearchOptions::CASE_SENSITIVE), + included_files, + excluded_files, + ) { + Ok(query) => { + self.panels_with_errors.remove(&InputPanel::Query); + Some(query) + } + Err(_e) => { + self.panels_with_errors.insert(InputPanel::Query); + cx.notify(); + None + } } } - } else { - debug_assert_ne!(self.current_mode, SearchMode::Semantic); - Some(SearchQuery::text( + _ => Some(SearchQuery::text( text, self.search_options.contains(SearchOptions::WHOLE_WORD), self.search_options.contains(SearchOptions::CASE_SENSITIVE), included_files, excluded_files, - )) + )), } } diff --git a/crates/terminal_view/src/terminal_view.rs b/crates/terminal_view/src/terminal_view.rs index b48597d901..4f891e678e 100644 --- a/crates/terminal_view/src/terminal_view.rs +++ b/crates/terminal_view/src/terminal_view.rs @@ -483,10 +483,8 @@ fn possible_open_targets( } pub fn regex_search_for_query(query: project::search::SearchQuery) -> Option { - let searcher = match query { - project::search::SearchQuery::Text { query, .. } => RegexSearch::new(&query), - project::search::SearchQuery::Regex { query, .. } => RegexSearch::new(&query), - }; + let query = query.as_str(); + let searcher = RegexSearch::new(&query); searcher.ok() } diff --git a/styles/src/style_tree/search.ts b/styles/src/style_tree/search.ts index b5259886b9..4c0df69804 100644 --- a/styles/src/style_tree/search.ts +++ b/styles/src/style_tree/search.ts @@ -2,7 +2,6 @@ import { with_opacity } from "../theme/color" import { background, border, foreground, text } from "./components" import { interactive, toggleable } from "../element" import { useTheme } from "../theme" -import { toggleable_icon_button } from "../component/icon_button" export default function search(): any { const theme = useTheme()