Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
a3ab144
Add benchmark for project search
osiewicz Oct 15, 2025
bd024c6
Start
osiewicz Oct 9, 2025
0b9b903
WIP
osiewicz Oct 10, 2025
70a4270
One step at a time
osiewicz Oct 10, 2025
4d71397
Another one
osiewicz Oct 10, 2025
9ec4895
Wire up searcher (incomplete one) to main search routine
osiewicz Oct 10, 2025
0451664
WTF, it works
osiewicz Oct 10, 2025
e3ed3ab
Clean up a bunch of warnings
osiewicz Oct 15, 2025
b9dcd42
Clean up a few more imports
osiewicz Oct 15, 2025
ff501aa
Make the search terminate
osiewicz Oct 15, 2025
469213a
Start exploring API for remote searches
osiewicz Oct 16, 2025
c673992
Send ignored buffers to the front
osiewicz Oct 16, 2025
34142ac
clippy
osiewicz Oct 16, 2025
e1a3039
Clean up lifetime of queues
osiewicz Oct 16, 2025
68571f6
:facepalm: Fixed test_search test.
osiewicz Oct 16, 2025
320a1ee
Reduce count of threads running the search to avoid oversubscribing.
osiewicz Oct 16, 2025
7223f18
Fix traversal of ignored directories for test
osiewicz Oct 16, 2025
3f1f78d
clippy
osiewicz Oct 16, 2025
7dc711e
Iterate on CI fixes
osiewicz Oct 16, 2025
99a92d5
Fix leaked handle
osiewicz Oct 16, 2025
7fd88a7
Load buffers concurrently
osiewicz Oct 17, 2025
77f1759
Start feeding buffers back even before we have all of them
osiewicz Oct 17, 2025
786ae67
Start on remote counterpart
osiewicz Oct 20, 2025
3f6dfda
Fix searching in collab scenarios
osiewicz Oct 20, 2025
7c7d736
Fix remote-server tests build features (enabled test-support for agent)
osiewicz Oct 20, 2025
2970f46
Fix project search in remote projects
osiewicz Oct 20, 2025
f0f8109
Fix searching within open buffers only
osiewicz Oct 20, 2025
b16f5e2
A couple of styling changes
osiewicz Oct 20, 2025
4f0c6f4
Fix incorrect limit calculation
osiewicz Oct 21, 2025
b6d75a1
Remove unused code
osiewicz Oct 22, 2025
0640247
Merge branch 'main' into search-v10000000
osiewicz Nov 6, 2025
e67db0e
Fix remote searcher not seeing all of the matches when using
osiewicz Nov 6, 2025
89e8a78
Merge branch 'main' into search-v10000000
osiewicz Nov 10, 2025
02de327
Merge branch 'main' into search-v10000000
osiewicz Nov 13, 2025
43381f1
Make project benchmarks compile again
osiewicz Nov 13, 2025
e290190
Make searching case-insensitive by default (matches Zed's defaults)
osiewicz Nov 13, 2025
abc7bfe
Fix benchmarks overeagerly grabbing matches in a buffer
osiewicz Nov 13, 2025
390d6df
Prevent racing in match reporting
osiewicz Nov 13, 2025
231609f
Make limiting more consistent by not doing it at the worker level
osiewicz Nov 13, 2025
a2b01f8
Remove unused imports
osiewicz Nov 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ members = [
"crates/picker",
"crates/prettier",
"crates/project",
"crates/project_benchmarks",
"crates/project_panel",
"crates/project_symbols",
"crates/prompt_store",
Expand Down
71 changes: 8 additions & 63 deletions crates/project/src/buffer_store.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
use crate::{
ProjectItem as _, ProjectPath,
ProjectPath,
lsp_store::OpenLspBufferHandle,
search::SearchQuery,
worktree_store::{WorktreeStore, WorktreeStoreEvent},
};
use anyhow::{Context as _, Result, anyhow};
use client::Client;
use collections::{HashMap, HashSet, hash_map};
use fs::Fs;
use futures::{Future, FutureExt as _, StreamExt, channel::oneshot, future::Shared};
use futures::{Future, FutureExt as _, channel::oneshot, future::Shared};
use gpui::{
App, AppContext as _, AsyncApp, Context, Entity, EventEmitter, Subscription, Task, WeakEntity,
};
Expand All @@ -23,8 +21,8 @@ use rpc::{
AnyProtoClient, ErrorCode, ErrorExt as _, TypedEnvelope,
proto::{self},
};
use smol::channel::Receiver;
use std::{io, pin::pin, sync::Arc, time::Instant};

use std::{io, sync::Arc, time::Instant};
use text::{BufferId, ReplicaId};
use util::{ResultExt as _, TryFutureExt, debug_panic, maybe, paths::PathStyle, rel_path::RelPath};
use worktree::{File, PathChange, ProjectEntryId, Worktree, WorktreeId};
Expand Down Expand Up @@ -978,6 +976,10 @@ impl BufferStore {
.filter_map(|buffer| buffer.upgrade())
}

pub(crate) fn is_searchable(&self, id: &BufferId) -> bool {
!self.non_searchable_buffers.contains(&id)
}

pub fn loading_buffers(
&self,
) -> impl Iterator<Item = (&ProjectPath, impl Future<Output = Result<Entity<Buffer>>>)> {
Expand Down Expand Up @@ -1102,63 +1104,6 @@ impl BufferStore {
Some(())
}

pub fn find_search_candidates(
&mut self,
query: &SearchQuery,
mut limit: usize,
fs: Arc<dyn Fs>,
cx: &mut Context<Self>,
) -> Receiver<Entity<Buffer>> {
let (tx, rx) = smol::channel::unbounded();
let mut open_buffers = HashSet::default();
let mut unnamed_buffers = Vec::new();
for handle in self.buffers() {
let buffer = handle.read(cx);
if self.non_searchable_buffers.contains(&buffer.remote_id()) {
continue;
} else if let Some(entry_id) = buffer.entry_id(cx) {
open_buffers.insert(entry_id);
} else {
limit = limit.saturating_sub(1);
unnamed_buffers.push(handle)
};
}

const MAX_CONCURRENT_BUFFER_OPENS: usize = 64;
let project_paths_rx = self
.worktree_store
.update(cx, |worktree_store, cx| {
worktree_store.find_search_candidates(query.clone(), limit, open_buffers, fs, cx)
})
.chunks(MAX_CONCURRENT_BUFFER_OPENS);

cx.spawn(async move |this, cx| {
for buffer in unnamed_buffers {
tx.send(buffer).await.ok();
}

let mut project_paths_rx = pin!(project_paths_rx);
while let Some(project_paths) = project_paths_rx.next().await {
let buffers = this.update(cx, |this, cx| {
project_paths
.into_iter()
.map(|project_path| this.open_buffer(project_path, cx))
.collect::<Vec<_>>()
})?;
for buffer_task in buffers {
if let Some(buffer) = buffer_task.await.log_err()
&& tx.send(buffer).await.is_err()
{
return anyhow::Ok(());
}
}
}
anyhow::Ok(())
})
.detach();
rx
}

fn on_buffer_event(
&mut self,
buffer: Entity<Buffer>,
Expand Down
Loading
Loading