diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 3b38824bdac0e4c9c98a1da5612f5235d1373a1d..ad182b2f6cdf1686dad0afedc3726b554c188103 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -4014,20 +4014,28 @@ impl Project { } else { None }; - let searcher = match client { - Some((client, remote_id)) => project_search::Search::remote( + let searcher = if query.is_opened_only() { + project_search::Search::open_buffers_only( self.buffer_store.clone(), self.worktree_store.clone(), project_search::Search::MAX_SEARCH_RESULT_FILES + 1, - (client, remote_id, self.remotely_created_models.clone()), - ), - None => project_search::Search::local( - self.fs.clone(), - self.buffer_store.clone(), - self.worktree_store.clone(), - project_search::Search::MAX_SEARCH_RESULT_FILES + 1, - cx, - ), + ) + } else { + match client { + Some((client, remote_id)) => project_search::Search::remote( + self.buffer_store.clone(), + self.worktree_store.clone(), + project_search::Search::MAX_SEARCH_RESULT_FILES + 1, + (client, remote_id, self.remotely_created_models.clone()), + ), + None => project_search::Search::local( + self.fs.clone(), + self.buffer_store.clone(), + self.worktree_store.clone(), + project_search::Search::MAX_SEARCH_RESULT_FILES + 1, + cx, + ), + } }; searcher.into_results(query, cx) } diff --git a/crates/project/src/project_search.rs b/crates/project/src/project_search.rs index 762f45780bf8550e218d2c6028ac16027d3feca7..f5da339c8cec8f847afe65622450627b7866ccc1 100644 --- a/crates/project/src/project_search.rs +++ b/crates/project/src/project_search.rs @@ -23,7 +23,7 @@ use smol::{ }; use text::BufferId; -use util::{ResultExt, maybe}; +use util::{ResultExt, maybe, paths::compare_rel_paths}; use worktree::{Entry, ProjectEntryId, Snapshot, Worktree}; use crate::{ @@ -50,6 +50,7 @@ enum SearchKind { remote_id: u64, models: Arc>, }, + OpenBuffersOnly, } /// Represents results of project search and allows one to either obtain match positions OR @@ -92,6 +93,7 @@ enum FindSearchCandidates { get_buffer_for_full_scan_tx: Sender, }, Remote, + OpenBuffersOnly, } impl Search { @@ -99,7 +101,6 @@ impl Search { fs: Arc, buffer_store: Entity, worktree_store: Entity, - limit: usize, cx: &mut App, ) -> Self { @@ -129,6 +130,18 @@ impl Search { limit, } } + pub(crate) fn open_buffers_only( + buffer_store: Entity, + worktree_store: Entity, + limit: usize, + ) -> Self { + Self { + kind: SearchKind::OpenBuffersOnly, + buffer_store, + worktree_store, + limit, + } + } pub(crate) const MAX_SEARCH_RESULT_FILES: usize = 5_000; pub(crate) const MAX_SEARCH_RESULT_RANGES: usize = 10_000; @@ -164,6 +177,22 @@ impl Search { bounded(MAX_CONCURRENT_BUFFER_OPENS); let (candidate_searcher, tasks) = match self.kind { + SearchKind::OpenBuffersOnly => { + let Ok(open_buffers) = cx.update(|cx| self.all_loaded_buffers(&query, cx)) + else { + return; + }; + let fill_requests = cx + .background_spawn(async move { + for buffer in open_buffers { + if let Err(_) = grab_buffer_snapshot_tx.send(buffer).await { + return; + } + } + }) + .boxed_local(); + (FindSearchCandidates::OpenBuffersOnly, vec![fill_requests]) + } SearchKind::Local { fs, ref mut worktrees, @@ -434,6 +463,45 @@ impl Search { }) .await; } + + fn all_loaded_buffers(&self, search_query: &SearchQuery, cx: &App) -> Vec> { + let worktree_store = self.worktree_store.read(cx); + let mut buffers = search_query + .buffers() + .into_iter() + .flatten() + .filter(|buffer| { + let b = buffer.read(cx); + if let Some(file) = b.file() { + if !search_query.match_path(file.path().as_std_path()) { + return false; + } + if !search_query.include_ignored() + && let Some(entry) = b + .entry_id(cx) + .and_then(|entry_id| worktree_store.entry_for_id(entry_id, cx)) + && entry.is_ignored + { + return false; + } + } + true + }) + .cloned() + .collect::>(); + buffers.sort_by(|a, b| { + let a = a.read(cx); + let b = b.read(cx); + match (a.file(), b.file()) { + (None, None) => a.remote_id().cmp(&b.remote_id()), + (None, Some(_)) => std::cmp::Ordering::Less, + (Some(_), None) => std::cmp::Ordering::Greater, + (Some(a), Some(b)) => compare_rel_paths((a.path(), true), (b.path(), true)), + } + }); + + buffers + } } struct Worker<'search> { @@ -470,7 +538,7 @@ impl Worker<'_> { get_buffer_for_full_scan_tx, Some(fs), ), - FindSearchCandidates::Remote => ( + FindSearchCandidates::Remote | FindSearchCandidates::OpenBuffersOnly => ( unbounded().1, unbounded().1, unbounded().0,