mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-27 04:44:30 +00:00
WIP: Working modal, without navigation and search on every keystroke
This commit is contained in:
parent
9d19dea7dd
commit
40ff7779bb
4 changed files with 146 additions and 19 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -7960,6 +7960,7 @@ dependencies = [
|
|||
"log",
|
||||
"matrixmultiply",
|
||||
"ndarray",
|
||||
"picker",
|
||||
"project",
|
||||
"rand 0.8.5",
|
||||
"rusqlite",
|
||||
|
@ -7968,6 +7969,7 @@ dependencies = [
|
|||
"sha-1 0.10.1",
|
||||
"smol",
|
||||
"tempdir",
|
||||
"theme",
|
||||
"tree-sitter",
|
||||
"tree-sitter-rust",
|
||||
"unindent",
|
||||
|
|
|
@ -14,6 +14,8 @@ language = { path = "../language" }
|
|||
project = { path = "../project" }
|
||||
workspace = { path = "../workspace" }
|
||||
util = { path = "../util" }
|
||||
picker = { path = "../picker" }
|
||||
theme = { path = "../theme" }
|
||||
anyhow.workspace = true
|
||||
futures.workspace = true
|
||||
smol.workspace = true
|
||||
|
|
107
crates/vector_store/src/modal.rs
Normal file
107
crates/vector_store/src/modal.rs
Normal file
|
@ -0,0 +1,107 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use gpui::{
|
||||
actions, elements::*, AnyElement, AppContext, ModelHandle, MouseState, Task, ViewContext,
|
||||
WeakViewHandle,
|
||||
};
|
||||
use picker::{Picker, PickerDelegate, PickerEvent};
|
||||
use project::Project;
|
||||
use util::ResultExt;
|
||||
use workspace::Workspace;
|
||||
|
||||
use crate::{SearchResult, VectorStore};
|
||||
|
||||
actions!(semantic_search, [Toggle]);
|
||||
|
||||
pub type SemanticSearch = Picker<SemanticSearchDelegate>;
|
||||
|
||||
pub struct SemanticSearchDelegate {
|
||||
workspace: WeakViewHandle<Workspace>,
|
||||
project: ModelHandle<Project>,
|
||||
vector_store: ModelHandle<VectorStore>,
|
||||
selected_match_index: usize,
|
||||
matches: Vec<SearchResult>,
|
||||
}
|
||||
|
||||
impl SemanticSearchDelegate {
|
||||
// This is currently searching on every keystroke,
|
||||
// This is wildly overkill, and has the potential to get expensive
|
||||
// We will need to update this to throttle searching
|
||||
pub fn new(
|
||||
workspace: WeakViewHandle<Workspace>,
|
||||
project: ModelHandle<Project>,
|
||||
vector_store: ModelHandle<VectorStore>,
|
||||
) -> Self {
|
||||
Self {
|
||||
workspace,
|
||||
project,
|
||||
vector_store,
|
||||
selected_match_index: 0,
|
||||
matches: vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PickerDelegate for SemanticSearchDelegate {
|
||||
fn placeholder_text(&self) -> Arc<str> {
|
||||
"Search repository in natural language...".into()
|
||||
}
|
||||
|
||||
fn confirm(&mut self, cx: &mut ViewContext<SemanticSearch>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn dismissed(&mut self, _cx: &mut ViewContext<SemanticSearch>) {}
|
||||
|
||||
fn match_count(&self) -> usize {
|
||||
self.matches.len()
|
||||
}
|
||||
|
||||
fn selected_index(&self) -> usize {
|
||||
self.selected_match_index
|
||||
}
|
||||
|
||||
fn set_selected_index(&mut self, ix: usize, _cx: &mut ViewContext<SemanticSearch>) {
|
||||
self.selected_match_index = ix;
|
||||
}
|
||||
|
||||
fn update_matches(&mut self, query: String, cx: &mut ViewContext<SemanticSearch>) -> Task<()> {
|
||||
let task = self
|
||||
.vector_store
|
||||
.update(cx, |store, cx| store.search(query.to_string(), 10, cx));
|
||||
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
let results = task.await.log_err();
|
||||
this.update(&mut cx, |this, cx| {
|
||||
if let Some(results) = results {
|
||||
let delegate = this.delegate_mut();
|
||||
delegate.matches = results;
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
fn render_match(
|
||||
&self,
|
||||
ix: usize,
|
||||
mouse_state: &mut MouseState,
|
||||
selected: bool,
|
||||
cx: &AppContext,
|
||||
) -> AnyElement<Picker<Self>> {
|
||||
let theme = theme::current(cx);
|
||||
let style = &theme.picker.item;
|
||||
let current_style = style.style_for(mouse_state, selected);
|
||||
|
||||
let search_result = &self.matches[ix];
|
||||
|
||||
let mut path = search_result.file_path.to_string_lossy();
|
||||
let name = search_result.name.clone();
|
||||
|
||||
Flex::column()
|
||||
.with_child(Text::new(name, current_style.label.text.clone()).with_soft_wrap(false))
|
||||
.with_child(Label::new(path.to_string(), style.default.label.clone()))
|
||||
.contained()
|
||||
.with_style(current_style.container)
|
||||
.into_any()
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
mod db;
|
||||
mod embedding;
|
||||
mod modal;
|
||||
mod search;
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -10,6 +11,7 @@ use db::{FileSha1, VectorDatabase, VECTOR_DB_URL};
|
|||
use embedding::{EmbeddingProvider, OpenAIEmbeddings};
|
||||
use gpui::{actions, AppContext, Entity, ModelContext, ModelHandle, Task, ViewContext};
|
||||
use language::{Language, LanguageRegistry};
|
||||
use modal::{SemanticSearch, SemanticSearchDelegate, Toggle};
|
||||
use project::{Fs, Project};
|
||||
use smol::channel;
|
||||
use std::{cmp::Ordering, collections::HashMap, path::PathBuf, sync::Arc};
|
||||
|
@ -17,8 +19,6 @@ use tree_sitter::{Parser, QueryCursor};
|
|||
use util::{http::HttpClient, ResultExt, TryFutureExt};
|
||||
use workspace::{Workspace, WorkspaceCreated};
|
||||
|
||||
actions!(semantic_search, [TestSearch]);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Document {
|
||||
pub offset: usize,
|
||||
|
@ -60,24 +60,40 @@ pub fn init(
|
|||
.detach();
|
||||
|
||||
cx.add_action({
|
||||
let vector_store = vector_store.clone();
|
||||
move |workspace: &mut Workspace, _: &TestSearch, cx: &mut ViewContext<Workspace>| {
|
||||
let t0 = std::time::Instant::now();
|
||||
let task = vector_store.update(cx, |store, cx| {
|
||||
store.search("compute embeddings for all of the symbols in the codebase and write them to a database".to_string(), 10, cx)
|
||||
});
|
||||
|
||||
cx.spawn(|this, cx| async move {
|
||||
let results = task.await?;
|
||||
let duration = t0.elapsed();
|
||||
|
||||
println!("search took {:?}", duration);
|
||||
println!("results {:?}", results);
|
||||
|
||||
anyhow::Ok(())
|
||||
}).detach()
|
||||
move |workspace: &mut Workspace, _: &Toggle, cx: &mut ViewContext<Workspace>| {
|
||||
let vector_store = vector_store.clone();
|
||||
workspace.toggle_modal(cx, |workspace, cx| {
|
||||
let project = workspace.project().clone();
|
||||
let workspace = cx.weak_handle();
|
||||
cx.add_view(|cx| {
|
||||
SemanticSearch::new(
|
||||
SemanticSearchDelegate::new(workspace, project, vector_store),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
})
|
||||
}
|
||||
});
|
||||
SemanticSearch::init(cx);
|
||||
// cx.add_action({
|
||||
// let vector_store = vector_store.clone();
|
||||
// move |workspace: &mut Workspace, _: &TestSearch, cx: &mut ViewContext<Workspace>| {
|
||||
// let t0 = std::time::Instant::now();
|
||||
// let task = vector_store.update(cx, |store, cx| {
|
||||
// store.search("compute embeddings for all of the symbols in the codebase and write them to a database".to_string(), 10, cx)
|
||||
// });
|
||||
|
||||
// cx.spawn(|this, cx| async move {
|
||||
// let results = task.await?;
|
||||
// let duration = t0.elapsed();
|
||||
|
||||
// println!("search took {:?}", duration);
|
||||
// println!("results {:?}", results);
|
||||
|
||||
// anyhow::Ok(())
|
||||
// }).detach()
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -87,7 +103,7 @@ pub struct IndexedFile {
|
|||
documents: Vec<Document>,
|
||||
}
|
||||
|
||||
struct VectorStore {
|
||||
pub struct VectorStore {
|
||||
fs: Arc<dyn Fs>,
|
||||
database_url: Arc<str>,
|
||||
embedding_provider: Arc<dyn EmbeddingProvider>,
|
||||
|
|
Loading…
Reference in a new issue