From 2f0212ee985f12d7849be02eb3da315f4a8a046a Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 4 Oct 2021 16:45:05 -0700 Subject: [PATCH] Rename worktree crate to project, pull in Project Also, move the high-level fuzzy mathcing functions in zed::fuzzy into the fuzzy crate so that project can use them. This required defining a 'PathMatchCandidateSet' trait to avoid a circular dependency from fuzzy to worktree. Co-Authored-By: Nathan Sobo --- Cargo.lock | 66 +++---- crates/fuzzy/Cargo.toml | 4 + crates/fuzzy/src/lib.rs | 149 ++++++++++++++- crates/{worktree => project}/Cargo.toml | 2 +- crates/{worktree => project}/src/fs.rs | 0 crates/{worktree => project}/src/ignore.rs | 0 .../src/project.rs => project/src/lib.rs} | 115 +++++++++--- .../src/lib.rs => project/src/worktree.rs} | 9 +- crates/server/src/rpc.rs | 3 +- crates/zed/Cargo.toml | 8 +- crates/zed/src/file_finder.rs | 11 +- crates/zed/src/fuzzy.rs | 173 ------------------ crates/zed/src/lib.rs | 4 +- crates/zed/src/project_panel.rs | 17 +- crates/zed/src/test.rs | 2 +- crates/zed/src/theme_selector.rs | 11 +- crates/zed/src/workspace.rs | 10 +- crates/zed/src/workspace/items.rs | 2 +- 18 files changed, 316 insertions(+), 270 deletions(-) rename crates/{worktree => project}/Cargo.toml (98%) rename crates/{worktree => project}/src/fs.rs (100%) rename crates/{worktree => project}/src/ignore.rs (100%) rename crates/{zed/src/project.rs => project/src/lib.rs} (79%) rename crates/{worktree/src/lib.rs => project/src/worktree.rs} (99%) delete mode 100644 crates/zed/src/fuzzy.rs diff --git a/Cargo.lock b/Cargo.lock index dc36ca627f..a4536da262 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2097,6 +2097,10 @@ dependencies = [ [[package]] name = "fuzzy" version = "0.1.0" +dependencies = [ + "gpui", + "util", +] [[package]] name = "generator" @@ -3674,6 +3678,36 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "project" +version = "0.1.0" +dependencies = [ + "anyhow", + "async-trait", + "buffer", + "clock", + "fsevent", + "futures", + "fuzzy", + "gpui", + "ignore", + "lazy_static", + "libc", + "log", + "parking_lot", + "postage", + "rand 0.8.3", + "rpc", + "rpc_client", + "serde 1.0.125", + "serde_json 1.0.64", + "smol", + "sum_tree", + "tempdir", + "toml 0.5.8", + "util", +] + [[package]] name = "prost" version = "0.8.0" @@ -5975,36 +6009,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "worktree" -version = "0.1.0" -dependencies = [ - "anyhow", - "async-trait", - "buffer", - "clock", - "fsevent", - "futures", - "fuzzy", - "gpui", - "ignore", - "lazy_static", - "libc", - "log", - "parking_lot", - "postage", - "rand 0.8.3", - "rpc", - "rpc_client", - "serde 1.0.125", - "serde_json 1.0.64", - "smol", - "sum_tree", - "tempdir", - "toml 0.5.8", - "util", -] - [[package]] name = "wyz" version = "0.2.0" @@ -6070,6 +6074,7 @@ dependencies = [ "num_cpus", "parking_lot", "postage", + "project", "rand 0.8.3", "rpc", "rpc_client", @@ -6093,7 +6098,6 @@ dependencies = [ "unindent", "url", "util", - "worktree", ] [[package]] diff --git a/crates/fuzzy/Cargo.toml b/crates/fuzzy/Cargo.toml index 8445f40cec..0a60e0973d 100644 --- a/crates/fuzzy/Cargo.toml +++ b/crates/fuzzy/Cargo.toml @@ -2,3 +2,7 @@ name = "fuzzy" version = "0.1.0" edition = "2018" + +[dependencies] +gpui = { path = "../gpui" } +util = { path = "../util" } diff --git a/crates/fuzzy/src/lib.rs b/crates/fuzzy/src/lib.rs index c2e02e4eb8..c9bcdb827f 100644 --- a/crates/fuzzy/src/lib.rs +++ b/crates/fuzzy/src/lib.rs @@ -1,8 +1,9 @@ mod char_bag; +use gpui::executor; use std::{ borrow::Cow, - cmp::Ordering, + cmp::{self, Ordering}, path::Path, sync::atomic::{self, AtomicBool}, sync::Arc, @@ -58,6 +59,14 @@ pub struct StringMatchCandidate { pub char_bag: CharBag, } +pub trait PathMatchCandidateSet<'a>: Send + Sync { + type Candidates: Iterator>; + fn id(&self) -> usize; + fn len(&self) -> usize; + fn prefix(&self) -> Arc; + fn candidates(&'a self, start: usize) -> Self::Candidates; +} + impl Match for PathMatch { fn score(&self) -> f64 { self.score @@ -152,6 +161,140 @@ impl Ord for PathMatch { } } +pub async fn match_strings( + candidates: &[StringMatchCandidate], + query: &str, + smart_case: bool, + max_results: usize, + cancel_flag: &AtomicBool, + background: Arc, +) -> Vec { + let lowercase_query = query.to_lowercase().chars().collect::>(); + let query = query.chars().collect::>(); + + let lowercase_query = &lowercase_query; + let query = &query; + let query_char_bag = CharBag::from(&lowercase_query[..]); + + let num_cpus = background.num_cpus().min(candidates.len()); + let segment_size = (candidates.len() + num_cpus - 1) / num_cpus; + let mut segment_results = (0..num_cpus) + .map(|_| Vec::with_capacity(max_results)) + .collect::>(); + + background + .scoped(|scope| { + for (segment_idx, results) in segment_results.iter_mut().enumerate() { + let cancel_flag = &cancel_flag; + scope.spawn(async move { + let segment_start = segment_idx * segment_size; + let segment_end = segment_start + segment_size; + let mut matcher = Matcher::new( + query, + lowercase_query, + query_char_bag, + smart_case, + max_results, + ); + matcher.match_strings( + &candidates[segment_start..segment_end], + results, + cancel_flag, + ); + }); + } + }) + .await; + + let mut results = Vec::new(); + for segment_result in segment_results { + if results.is_empty() { + results = segment_result; + } else { + util::extend_sorted(&mut results, segment_result, max_results, |a, b| b.cmp(&a)); + } + } + results +} + +pub async fn match_paths<'a, Set: PathMatchCandidateSet<'a>>( + candidate_sets: &'a [Set], + query: &str, + smart_case: bool, + max_results: usize, + cancel_flag: &AtomicBool, + background: Arc, +) -> Vec { + let path_count: usize = candidate_sets.iter().map(|s| s.len()).sum(); + if path_count == 0 { + return Vec::new(); + } + + let lowercase_query = query.to_lowercase().chars().collect::>(); + let query = query.chars().collect::>(); + + let lowercase_query = &lowercase_query; + let query = &query; + let query_char_bag = CharBag::from(&lowercase_query[..]); + + let num_cpus = background.num_cpus().min(path_count); + let segment_size = (path_count + num_cpus - 1) / num_cpus; + let mut segment_results = (0..num_cpus) + .map(|_| Vec::with_capacity(max_results)) + .collect::>(); + + background + .scoped(|scope| { + for (segment_idx, results) in segment_results.iter_mut().enumerate() { + scope.spawn(async move { + let segment_start = segment_idx * segment_size; + let segment_end = segment_start + segment_size; + let mut matcher = Matcher::new( + query, + lowercase_query, + query_char_bag, + smart_case, + max_results, + ); + + let mut tree_start = 0; + for candidate_set in candidate_sets { + let tree_end = tree_start + candidate_set.len(); + + if tree_start < segment_end && segment_start < tree_end { + let start = cmp::max(tree_start, segment_start) - tree_start; + let end = cmp::min(tree_end, segment_end) - tree_start; + let candidates = candidate_set.candidates(start).take(end - start); + + matcher.match_paths( + candidate_set.id(), + candidate_set.prefix(), + candidates, + results, + &cancel_flag, + ); + } + if tree_end >= segment_end { + break; + } + tree_start = tree_end; + } + }) + } + }) + .await; + + let mut results = Vec::new(); + for segment_result in segment_results { + if results.is_empty() { + results = segment_result; + } else { + util::extend_sorted(&mut results, segment_result, max_results, |a, b| b.cmp(&a)); + } + } + results +} + impl<'a> Matcher<'a> { pub fn new( query: &'a [char], @@ -194,11 +337,11 @@ impl<'a> Matcher<'a> { ) } - pub fn match_paths( + pub fn match_paths<'c: 'a>( &mut self, tree_id: usize, path_prefix: Arc, - path_entries: impl Iterator>, + path_entries: impl Iterator>, results: &mut Vec, cancel_flag: &AtomicBool, ) { diff --git a/crates/worktree/Cargo.toml b/crates/project/Cargo.toml similarity index 98% rename from crates/worktree/Cargo.toml rename to crates/project/Cargo.toml index a8e40d27fc..1144aeec59 100644 --- a/crates/worktree/Cargo.toml +++ b/crates/project/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "worktree" +name = "project" version = "0.1.0" edition = "2018" diff --git a/crates/worktree/src/fs.rs b/crates/project/src/fs.rs similarity index 100% rename from crates/worktree/src/fs.rs rename to crates/project/src/fs.rs diff --git a/crates/worktree/src/ignore.rs b/crates/project/src/ignore.rs similarity index 100% rename from crates/worktree/src/ignore.rs rename to crates/project/src/ignore.rs diff --git a/crates/zed/src/project.rs b/crates/project/src/lib.rs similarity index 79% rename from crates/zed/src/project.rs rename to crates/project/src/lib.rs index 3e69de5706..2be5c7ffa3 100644 --- a/crates/zed/src/project.rs +++ b/crates/project/src/lib.rs @@ -1,10 +1,11 @@ -use crate::{ - fuzzy::{self, PathMatch}, - AppState, -}; +pub mod fs; +mod ignore; +mod worktree; + use anyhow::Result; use buffer::LanguageRegistry; use futures::Future; +use fuzzy::{self, PathMatch, PathMatchCandidate, PathMatchCandidateSet}; use gpui::{AppContext, Entity, ModelContext, ModelHandle, Task}; use rpc_client as rpc; use std::{ @@ -12,7 +13,9 @@ use std::{ sync::{atomic::AtomicBool, Arc}, }; use util::TryFutureExt as _; -use worktree::{fs::Fs, Worktree}; + +pub use fs::*; +pub use worktree::*; pub struct Project { worktrees: Vec>, @@ -40,13 +43,13 @@ pub struct ProjectEntry { } impl Project { - pub fn new(app_state: &AppState) -> Self { + pub fn new(languages: Arc, rpc: Arc, fs: Arc) -> Self { Self { worktrees: Default::default(), active_entry: None, - languages: app_state.languages.clone(), - rpc: app_state.rpc.clone(), - fs: app_state.fs.clone(), + languages, + rpc, + fs, } } @@ -207,18 +210,22 @@ impl Project { cancel_flag: &'a AtomicBool, cx: &AppContext, ) -> impl 'a + Future> { - let snapshots = self + let include_root_name = self.worktrees.len() > 1; + let candidate_sets = self .worktrees .iter() - .map(|worktree| worktree.read(cx).snapshot()) + .map(|worktree| CandidateSet { + snapshot: worktree.read(cx).snapshot(), + include_ignored, + include_root_name, + }) .collect::>(); - let background = cx.background().clone(); + let background = cx.background().clone(); async move { fuzzy::match_paths( - snapshots.as_slice(), + candidate_sets.as_slice(), query, - include_ignored, smart_case, max_results, cancel_flag, @@ -229,6 +236,65 @@ impl Project { } } +struct CandidateSet { + snapshot: Snapshot, + include_ignored: bool, + include_root_name: bool, +} + +impl<'a> PathMatchCandidateSet<'a> for CandidateSet { + type Candidates = CandidateSetIter<'a>; + + fn id(&self) -> usize { + self.snapshot.id() + } + + fn len(&self) -> usize { + if self.include_ignored { + self.snapshot.file_count() + } else { + self.snapshot.visible_file_count() + } + } + + fn prefix(&self) -> Arc { + if self.snapshot.root_entry().map_or(false, |e| e.is_file()) { + self.snapshot.root_name().into() + } else if self.include_root_name { + format!("{}/", self.snapshot.root_name()).into() + } else { + "".into() + } + } + + fn candidates(&'a self, start: usize) -> Self::Candidates { + CandidateSetIter { + traversal: self.snapshot.files(self.include_ignored, start), + } + } +} + +struct CandidateSetIter<'a> { + traversal: Traversal<'a>, +} + +impl<'a> Iterator for CandidateSetIter<'a> { + type Item = PathMatchCandidate<'a>; + + fn next(&mut self) -> Option { + self.traversal.next().map(|entry| { + if let EntryKind::File(char_bag) = entry.kind { + PathMatchCandidate { + path: &entry.path, + char_bag, + } + } else { + unreachable!() + } + }) + } +} + impl Entity for Project { type Event = Event; } @@ -236,16 +302,15 @@ impl Entity for Project { #[cfg(test)] mod tests { use super::*; - use crate::test::test_app_state; + use buffer::LanguageRegistry; + use fs::RealFs; + use gpui::TestAppContext; use serde_json::json; use std::{os::unix, path::PathBuf}; use util::test::temp_tree; - use worktree::fs::RealFs; #[gpui::test] async fn test_populate_and_search(mut cx: gpui::TestAppContext) { - let mut app_state = cx.update(test_app_state); - Arc::get_mut(&mut app_state).unwrap().fs = Arc::new(RealFs); let dir = temp_tree(json!({ "root": { "apple": "", @@ -269,7 +334,8 @@ mod tests { ) .unwrap(); - let project = cx.add_model(|_| Project::new(app_state.as_ref())); + let project = build_project(&mut cx); + let tree = project .update(&mut cx, |project, cx| { project.add_local_worktree(&root_link_path, cx) @@ -308,8 +374,6 @@ mod tests { #[gpui::test] async fn test_search_worktree_without_files(mut cx: gpui::TestAppContext) { - let mut app_state = cx.update(test_app_state); - Arc::get_mut(&mut app_state).unwrap().fs = Arc::new(RealFs); let dir = temp_tree(json!({ "root": { "dir1": {}, @@ -319,7 +383,7 @@ mod tests { } })); - let project = cx.add_model(|_| Project::new(app_state.as_ref())); + let project = build_project(&mut cx); let tree = project .update(&mut cx, |project, cx| { project.add_local_worktree(&dir.path(), cx) @@ -339,4 +403,11 @@ mod tests { assert!(results.is_empty()); } + + fn build_project(cx: &mut TestAppContext) -> ModelHandle { + let languages = Arc::new(LanguageRegistry::new()); + let fs = Arc::new(RealFs); + let rpc = rpc::Client::new(); + cx.add_model(|_| Project::new(languages, rpc, fs)) + } } diff --git a/crates/worktree/src/lib.rs b/crates/project/src/worktree.rs similarity index 99% rename from crates/worktree/src/lib.rs rename to crates/project/src/worktree.rs index 3803401ed7..4bccc58e35 100644 --- a/crates/worktree/src/lib.rs +++ b/crates/project/src/worktree.rs @@ -1,12 +1,11 @@ -pub mod fs; -mod ignore; - -use self::ignore::IgnoreStack; +use super::{ + fs::{self, Fs}, + ignore::IgnoreStack, +}; use ::ignore::gitignore::{Gitignore, GitignoreBuilder}; use anyhow::{anyhow, Result}; use buffer::{self, Buffer, History, LanguageRegistry, Operation, Rope}; use clock::ReplicaId; -pub use fs::*; use futures::{Stream, StreamExt}; use fuzzy::CharBag; use gpui::{ diff --git a/crates/server/src/rpc.rs b/crates/server/src/rpc.rs index e4a6f6d268..60b877bf38 100644 --- a/crates/server/src/rpc.rs +++ b/crates/server/src/rpc.rs @@ -981,12 +981,11 @@ mod tests { editor::{Editor, EditorSettings, Insert}, fs::{FakeFs, Fs as _}, people_panel::JoinWorktree, - project::ProjectPath, + project::{ProjectPath, Worktree}, rpc::{self, Client, Credentials, EstablishConnectionError}, test::FakeHttpClient, user::UserStore, workspace::Workspace, - worktree::Worktree, }; #[gpui::test] diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index 2fea72cc6c..6387d8950b 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -17,10 +17,10 @@ path = "src/main.rs" test-support = [ "buffer/test-support", "gpui/test-support", + "project/test-support", + "rpc/test-support", "rpc_client/test-support", "tempdir", - "worktree/test-support", - "rpc/test-support", ] [dependencies] @@ -30,11 +30,11 @@ fsevent = { path = "../fsevent" } fuzzy = { path = "../fuzzy" } editor = { path = "../editor" } gpui = { path = "../gpui" } +project = { path = "../project" } rpc = { path = "../rpc" } rpc_client = { path = "../rpc_client" } sum_tree = { path = "../sum_tree" } util = { path = "../util" } -worktree = { path = "../worktree" } anyhow = "1.0.38" async-recursion = "0.3" @@ -79,10 +79,10 @@ url = "2.2" buffer = { path = "../buffer", features = ["test-support"] } editor = { path = "../editor", features = ["test-support"] } gpui = { path = "../gpui", features = ["test-support"] } +project = { path = "../project", features = ["test-support"] } rpc = { path = "../rpc", features = ["test-support"] } rpc_client = { path = "../rpc_client", features = ["test-support"] } util = { path = "../util", features = ["test-support"] } -worktree = { path = "../worktree", features = ["test-support"] } cargo-bundle = "0.5.0" env_logger = "0.8" diff --git a/crates/zed/src/file_finder.rs b/crates/zed/src/file_finder.rs index 5eca8a1827..93ca2d963b 100644 --- a/crates/zed/src/file_finder.rs +++ b/crates/zed/src/file_finder.rs @@ -1,10 +1,6 @@ -use crate::{ - fuzzy::PathMatch, - project::{Project, ProjectPath}, - settings::Settings, - workspace::Workspace, -}; +use crate::{settings::Settings, workspace::Workspace}; use editor::{self, Editor, EditorSettings}; +use fuzzy::PathMatch; use gpui::{ action, elements::*, @@ -17,6 +13,7 @@ use gpui::{ ViewContext, ViewHandle, WeakViewHandle, }; use postage::watch; +use project::{Project, ProjectPath}; use std::{ cmp, path::Path, @@ -427,9 +424,9 @@ mod tests { use super::*; use crate::{test::test_app_state, workspace::Workspace}; use editor::{self, Insert}; + use project::fs::FakeFs; use serde_json::json; use std::path::PathBuf; - use worktree::fs::FakeFs; #[gpui::test] async fn test_matching_paths(mut cx: gpui::TestAppContext) { diff --git a/crates/zed/src/fuzzy.rs b/crates/zed/src/fuzzy.rs deleted file mode 100644 index 990bca6cbf..0000000000 --- a/crates/zed/src/fuzzy.rs +++ /dev/null @@ -1,173 +0,0 @@ -use gpui::executor; -use std::{ - cmp, - sync::{atomic::AtomicBool, Arc}, -}; -use util; -use worktree::{EntryKind, Snapshot}; - -pub use fuzzy::*; - -pub async fn match_strings( - candidates: &[StringMatchCandidate], - query: &str, - smart_case: bool, - max_results: usize, - cancel_flag: &AtomicBool, - background: Arc, -) -> Vec { - let lowercase_query = query.to_lowercase().chars().collect::>(); - let query = query.chars().collect::>(); - - let lowercase_query = &lowercase_query; - let query = &query; - let query_char_bag = CharBag::from(&lowercase_query[..]); - - let num_cpus = background.num_cpus().min(candidates.len()); - let segment_size = (candidates.len() + num_cpus - 1) / num_cpus; - let mut segment_results = (0..num_cpus) - .map(|_| Vec::with_capacity(max_results)) - .collect::>(); - - background - .scoped(|scope| { - for (segment_idx, results) in segment_results.iter_mut().enumerate() { - let cancel_flag = &cancel_flag; - scope.spawn(async move { - let segment_start = segment_idx * segment_size; - let segment_end = segment_start + segment_size; - let mut matcher = Matcher::new( - query, - lowercase_query, - query_char_bag, - smart_case, - max_results, - ); - matcher.match_strings( - &candidates[segment_start..segment_end], - results, - cancel_flag, - ); - }); - } - }) - .await; - - let mut results = Vec::new(); - for segment_result in segment_results { - if results.is_empty() { - results = segment_result; - } else { - util::extend_sorted(&mut results, segment_result, max_results, |a, b| b.cmp(&a)); - } - } - results -} - -pub async fn match_paths( - snapshots: &[Snapshot], - query: &str, - include_ignored: bool, - smart_case: bool, - max_results: usize, - cancel_flag: &AtomicBool, - background: Arc, -) -> Vec { - let path_count: usize = if include_ignored { - snapshots.iter().map(Snapshot::file_count).sum() - } else { - snapshots.iter().map(Snapshot::visible_file_count).sum() - }; - if path_count == 0 { - return Vec::new(); - } - - let lowercase_query = query.to_lowercase().chars().collect::>(); - let query = query.chars().collect::>(); - - let lowercase_query = &lowercase_query; - let query = &query; - let query_char_bag = CharBag::from(&lowercase_query[..]); - - let num_cpus = background.num_cpus().min(path_count); - let segment_size = (path_count + num_cpus - 1) / num_cpus; - let mut segment_results = (0..num_cpus) - .map(|_| Vec::with_capacity(max_results)) - .collect::>(); - - background - .scoped(|scope| { - for (segment_idx, results) in segment_results.iter_mut().enumerate() { - scope.spawn(async move { - let segment_start = segment_idx * segment_size; - let segment_end = segment_start + segment_size; - let mut matcher = Matcher::new( - query, - lowercase_query, - query_char_bag, - smart_case, - max_results, - ); - - let mut tree_start = 0; - for snapshot in snapshots { - let tree_end = if include_ignored { - tree_start + snapshot.file_count() - } else { - tree_start + snapshot.visible_file_count() - }; - - if tree_start < segment_end && segment_start < tree_end { - let path_prefix: Arc = - if snapshot.root_entry().map_or(false, |e| e.is_file()) { - snapshot.root_name().into() - } else if snapshots.len() > 1 { - format!("{}/", snapshot.root_name()).into() - } else { - "".into() - }; - - let start = cmp::max(tree_start, segment_start) - tree_start; - let end = cmp::min(tree_end, segment_end) - tree_start; - let paths = snapshot - .files(include_ignored, start) - .take(end - start) - .map(|entry| { - if let EntryKind::File(char_bag) = entry.kind { - PathMatchCandidate { - path: &entry.path, - char_bag, - } - } else { - unreachable!() - } - }); - - matcher.match_paths( - snapshot.id(), - path_prefix, - paths, - results, - &cancel_flag, - ); - } - if tree_end >= segment_end { - break; - } - tree_start = tree_end; - } - }) - } - }) - .await; - - let mut results = Vec::new(); - for segment_result in segment_results { - if results.is_empty() { - results = segment_result; - } else { - util::extend_sorted(&mut results, segment_result, max_results, |a, b| b.cmp(&a)); - } - } - results -} diff --git a/crates/zed/src/lib.rs b/crates/zed/src/lib.rs index e6584d34d8..914939bf45 100644 --- a/crates/zed/src/lib.rs +++ b/crates/zed/src/lib.rs @@ -2,12 +2,10 @@ pub mod assets; pub mod channel; pub mod chat_panel; pub mod file_finder; -mod fuzzy; pub mod http; pub mod language; pub mod menus; pub mod people_panel; -pub mod project; pub mod project_panel; pub mod settings; #[cfg(any(test, feature = "test-support"))] @@ -24,11 +22,11 @@ pub use editor; use gpui::{action, keymap::Binding, ModelHandle}; use parking_lot::Mutex; use postage::watch; +pub use project::{self, fs}; pub use rpc_client as rpc; pub use settings::Settings; use std::sync::Arc; use util::TryFutureExt; -pub use worktree::{self, fs}; action!(About); action!(Quit); diff --git a/crates/zed/src/project_panel.rs b/crates/zed/src/project_panel.rs index 3d243dbebb..7fc3206f22 100644 --- a/crates/zed/src/project_panel.rs +++ b/crates/zed/src/project_panel.rs @@ -20,12 +20,12 @@ use gpui::{ ViewContext, ViewHandle, WeakViewHandle, }; use postage::watch; +use project::Worktree; use std::{ collections::{hash_map, HashMap}, ffi::OsStr, ops::Range, }; -use worktree::Worktree; pub struct ProjectPanel { project: ModelHandle, @@ -288,7 +288,7 @@ impl ProjectPanel { &self, target_ix: usize, cx: &'a AppContext, - ) -> Option<(&'a Worktree, &'a worktree::Entry)> { + ) -> Option<(&'a Worktree, &'a project::Entry)> { let project = self.project.read(cx); let mut offset = None; let mut ix = 0; @@ -309,10 +309,7 @@ impl ProjectPanel { }) } - fn selected_entry<'a>( - &self, - cx: &'a AppContext, - ) -> Option<(&'a Worktree, &'a worktree::Entry)> { + fn selected_entry<'a>(&self, cx: &'a AppContext) -> Option<(&'a Worktree, &'a project::Entry)> { let selection = self.selection?; let project = self.project.read(cx); let worktree = project.worktree_for_id(selection.worktree_id)?.read(cx); @@ -626,7 +623,13 @@ mod tests { ) .await; - let project = cx.add_model(|_| Project::new(&app_state)); + let project = cx.add_model(|_| { + Project::new( + app_state.languages.clone(), + app_state.rpc.clone(), + app_state.fs.clone(), + ) + }); let root1 = project .update(&mut cx, |project, cx| { project.add_local_worktree("/root1".as_ref(), cx) diff --git a/crates/zed/src/test.rs b/crates/zed/src/test.rs index ab5edd6354..0fff5c2aaf 100644 --- a/crates/zed/src/test.rs +++ b/crates/zed/src/test.rs @@ -12,9 +12,9 @@ use buffer::LanguageRegistry; use futures::{future::BoxFuture, Future}; use gpui::MutableAppContext; use parking_lot::Mutex; +use project::fs::FakeFs; use rpc_client as rpc; use std::{fmt, sync::Arc}; -use worktree::fs::FakeFs; #[cfg(test)] #[ctor::ctor] diff --git a/crates/zed/src/theme_selector.rs b/crates/zed/src/theme_selector.rs index 9f7edb02ff..7df045740e 100644 --- a/crates/zed/src/theme_selector.rs +++ b/crates/zed/src/theme_selector.rs @@ -1,12 +1,6 @@ -use std::{cmp, sync::Arc}; - -use crate::{ - fuzzy::{match_strings, StringMatch, StringMatchCandidate}, - settings::ThemeRegistry, - workspace::Workspace, - AppState, Settings, -}; +use crate::{settings::ThemeRegistry, workspace::Workspace, AppState, Settings}; use editor::{self, Editor, EditorSettings}; +use fuzzy::{match_strings, StringMatch, StringMatchCandidate}; use gpui::{ action, elements::*, @@ -16,6 +10,7 @@ use gpui::{ }; use parking_lot::Mutex; use postage::watch; +use std::{cmp, sync::Arc}; pub struct ThemeSelector { settings_tx: Arc>>, diff --git a/crates/zed/src/workspace.rs b/crates/zed/src/workspace.rs index fc91edab3a..0ca10a761b 100644 --- a/crates/zed/src/workspace.rs +++ b/crates/zed/src/workspace.rs @@ -32,13 +32,13 @@ use log::error; pub use pane::*; pub use pane_group::*; use postage::{prelude::Stream, watch}; +use project::Worktree; use std::{ collections::{hash_map::Entry, HashMap}, future::Future, path::{Path, PathBuf}, sync::Arc, }; -use worktree::Worktree; action!(Open, Arc); action!(OpenPaths, OpenParams); @@ -376,7 +376,13 @@ pub struct Workspace { impl Workspace { pub fn new(app_state: &AppState, cx: &mut ViewContext) -> Self { - let project = cx.add_model(|_| Project::new(app_state)); + let project = cx.add_model(|_| { + Project::new( + app_state.languages.clone(), + app_state.rpc.clone(), + app_state.fs.clone(), + ) + }); cx.observe(&project, |_, _, cx| cx.notify()).detach(); let pane = cx.add_view(|_| Pane::new(app_state.settings.clone())); diff --git a/crates/zed/src/workspace/items.rs b/crates/zed/src/workspace/items.rs index c002fddd41..9d927fcf64 100644 --- a/crates/zed/src/workspace/items.rs +++ b/crates/zed/src/workspace/items.rs @@ -5,8 +5,8 @@ use buffer::{Buffer, File as _}; use editor::{Editor, EditorSettings, Event}; use gpui::{fonts::TextStyle, AppContext, ModelHandle, Task, ViewContext}; use postage::watch; +use project::Worktree; use std::path::Path; -use worktree::Worktree; impl Item for Buffer { type View = Editor;