Rebase - Got Zed compiling and fixed a build error due to conflicting dependencies that cargo didn't catch :(

Co-Authored-By: kay@zed.dev
This commit is contained in:
Mikayla Maki 2022-10-27 15:52:38 -07:00
parent b9cbd4084e
commit 3451a3c7fe
22 changed files with 466 additions and 291 deletions

2
Cargo.lock generated
View File

@ -428,6 +428,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"client", "client",
"db",
"gpui", "gpui",
"isahc", "isahc",
"lazy_static", "lazy_static",
@ -1560,7 +1561,6 @@ dependencies = [
"rusqlite_migration", "rusqlite_migration",
"serde", "serde",
"serde_rusqlite", "serde_rusqlite",
"settings",
"tempdir", "tempdir",
] ]

View File

@ -81,3 +81,4 @@ split-debuginfo = "unpacked"
[profile.release] [profile.release]
debug = true debug = true

View File

@ -8,6 +8,7 @@ path = "src/auto_update.rs"
doctest = false doctest = false
[dependencies] [dependencies]
db = { path = "../db" }
client = { path = "../client" } client = { path = "../client" }
gpui = { path = "../gpui" } gpui = { path = "../gpui" }
menu = { path = "../menu" } menu = { path = "../menu" }

View File

@ -1,7 +1,8 @@
mod update_notification; mod update_notification;
use anyhow::{anyhow, Context, Result}; use anyhow::{anyhow, Context, Result};
use client::{http::HttpClient, ZED_SECRET_CLIENT_TOKEN, ZED_SERVER_URL}; use client::{http::HttpClient, ZED_SECRET_CLIENT_TOKEN};
use db::Db;
use gpui::{ use gpui::{
actions, platform::AppVersion, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, actions, platform::AppVersion, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle,
MutableAppContext, Task, WeakViewHandle, MutableAppContext, Task, WeakViewHandle,
@ -55,11 +56,16 @@ impl Entity for AutoUpdater {
type Event = (); type Event = ();
} }
pub fn init(db: project::Db, http_client: Arc<dyn HttpClient>, cx: &mut MutableAppContext) { pub fn init(
db: Db,
http_client: Arc<dyn HttpClient>,
server_url: String,
cx: &mut MutableAppContext,
) {
if let Some(version) = (*ZED_APP_VERSION).or_else(|| cx.platform().app_version().ok()) { if let Some(version) = (*ZED_APP_VERSION).or_else(|| cx.platform().app_version().ok()) {
let server_url = ZED_SERVER_URL.to_string(); let server_url = server_url;
let auto_updater = cx.add_model(|cx| { let auto_updater = cx.add_model(|cx| {
let updater = AutoUpdater::new(version, db.clone(), http_client, server_url.clone()); let updater = AutoUpdater::new(version, db, http_client, server_url.clone());
updater.start_polling(cx).detach(); updater.start_polling(cx).detach();
updater updater
}); });

View File

@ -905,8 +905,14 @@ async fn test_host_disconnect(
let project_b = client_b.build_remote_project(project_id, cx_b).await; let project_b = client_b.build_remote_project(project_id, cx_b).await;
assert!(worktree_a.read_with(cx_a, |tree, _| tree.as_local().unwrap().is_shared())); assert!(worktree_a.read_with(cx_a, |tree, _| tree.as_local().unwrap().is_shared()));
let (_, workspace_b) = let (_, workspace_b) = cx_b.add_window(|cx| {
cx_b.add_window(|cx| Workspace::new(project_b.clone(), |_, _| unimplemented!(), cx)); Workspace::new(
Default::default(),
project_b.clone(),
|_, _| unimplemented!(),
cx,
)
});
let editor_b = workspace_b let editor_b = workspace_b
.update(cx_b, |workspace, cx| { .update(cx_b, |workspace, cx| {
workspace.open_path((worktree_id, "b.txt"), None, true, cx) workspace.open_path((worktree_id, "b.txt"), None, true, cx)
@ -3701,8 +3707,14 @@ async fn test_collaborating_with_code_actions(
// Join the project as client B. // Join the project as client B.
let project_b = client_b.build_remote_project(project_id, cx_b).await; let project_b = client_b.build_remote_project(project_id, cx_b).await;
let (_window_b, workspace_b) = let (_window_b, workspace_b) = cx_b.add_window(|cx| {
cx_b.add_window(|cx| Workspace::new(project_b.clone(), |_, _| unimplemented!(), cx)); Workspace::new(
Default::default(),
project_b.clone(),
|_, _| unimplemented!(),
cx,
)
});
let editor_b = workspace_b let editor_b = workspace_b
.update(cx_b, |workspace, cx| { .update(cx_b, |workspace, cx| {
workspace.open_path((worktree_id, "main.rs"), None, true, cx) workspace.open_path((worktree_id, "main.rs"), None, true, cx)
@ -3922,8 +3934,14 @@ async fn test_collaborating_with_renames(cx_a: &mut TestAppContext, cx_b: &mut T
.unwrap(); .unwrap();
let project_b = client_b.build_remote_project(project_id, cx_b).await; let project_b = client_b.build_remote_project(project_id, cx_b).await;
let (_window_b, workspace_b) = let (_window_b, workspace_b) = cx_b.add_window(|cx| {
cx_b.add_window(|cx| Workspace::new(project_b.clone(), |_, _| unimplemented!(), cx)); Workspace::new(
Default::default(),
project_b.clone(),
|_, _| unimplemented!(),
cx,
)
});
let editor_b = workspace_b let editor_b = workspace_b
.update(cx_b, |workspace, cx| { .update(cx_b, |workspace, cx| {
workspace.open_path((worktree_id, "one.rs"), None, true, cx) workspace.open_path((worktree_id, "one.rs"), None, true, cx)
@ -6054,7 +6072,12 @@ impl TestClient {
) -> ViewHandle<Workspace> { ) -> ViewHandle<Workspace> {
let (_, root_view) = cx.add_window(|_| EmptyView); let (_, root_view) = cx.add_window(|_| EmptyView);
cx.add_view(&root_view, |cx| { cx.add_view(&root_view, |cx| {
Workspace::new(project.clone(), |_, _| unimplemented!(), cx) Workspace::new(
Default::default(),
project.clone(),
|_, _| unimplemented!(),
cx,
)
}) })
} }

View File

@ -51,7 +51,12 @@ pub fn init(app_state: Arc<AppState>, cx: &mut MutableAppContext) {
.await?; .await?;
let (_, workspace) = cx.add_window((app_state.build_window_options)(), |cx| { let (_, workspace) = cx.add_window((app_state.build_window_options)(), |cx| {
let mut workspace = Workspace::new(project, app_state.default_item_factory, cx); let mut workspace = Workspace::new(
Default::default(),
project,
app_state.default_item_factory,
cx,
);
(app_state.initialize_workspace)(&mut workspace, &app_state, cx); (app_state.initialize_workspace)(&mut workspace, &app_state, cx);
workspace workspace
}); });

View File

@ -350,8 +350,9 @@ mod tests {
}); });
let project = Project::test(app_state.fs.clone(), [], cx).await; let project = Project::test(app_state.fs.clone(), [], cx).await;
let (_, workspace) = let (_, workspace) = cx.add_window(|cx| {
cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx)); Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
});
let editor = cx.add_view(&workspace, |cx| { let editor = cx.add_view(&workspace, |cx| {
let mut editor = Editor::single_line(None, cx); let mut editor = Editor::single_line(None, cx);
editor.set_text("abc", cx); editor.set_text("abc", cx);

View File

@ -13,7 +13,6 @@ test-support = []
[dependencies] [dependencies]
collections = { path = "../collections" } collections = { path = "../collections" }
gpui = { path = "../gpui" } gpui = { path = "../gpui" }
settings = { path = "../settings" }
anyhow = "1.0.57" anyhow = "1.0.57"
async-trait = "0.1" async-trait = "0.1"
lazy_static = "1.4.0" lazy_static = "1.4.0"

View File

@ -1,7 +1,6 @@
use std::{fs::File, path::Path, thread::sleep, time::Duration}; use std::{fs::File, path::Path};
use db::pane::SerializedDockPane; use db::pane::{DockAnchor, SerializedDockPane};
use settings::DockAnchor;
const TEST_FILE: &'static str = "test-db.db"; const TEST_FILE: &'static str = "test-db.db";
@ -25,7 +24,7 @@ fn main() -> anyhow::Result<()> {
shown: true, shown: true,
}); });
let new_workspace = db.workspace_for_roots(&["/tmp"]); let _new_workspace = db.workspace_for_roots(&["/tmp"]);
db.write_to(file).ok(); db.write_to(file).ok();

View File

@ -1,69 +1,69 @@
use std::{ // use std::{
ffi::OsStr, // ffi::OsStr,
fmt::Display, // fmt::Display,
hash::Hash, // hash::Hash,
os::unix::prelude::OsStrExt, // os::unix::prelude::OsStrExt,
path::{Path, PathBuf}, // path::{Path, PathBuf},
sync::Arc, // sync::Arc,
}; // };
use anyhow::Result; // use anyhow::Result;
use collections::HashSet; // use collections::HashSet;
use rusqlite::{named_params, params, types::FromSql}; // use rusqlite::{named_params, params, types::FromSql};
use crate::workspace::WorkspaceId; // use crate::workspace::WorkspaceId;
use super::Db; // use super::Db;
/// Current design makes the cut at the item level, // /// Current design makes the cut at the item level,
/// - Maybe A little more bottom up, serialize 'Terminals' and 'Editors' directly, and then make a seperate // /// - Maybe A little more bottom up, serialize 'Terminals' and 'Editors' directly, and then make a seperate
/// - items table, with a kind, and an integer that acts as a key to one of these other tables // /// - items table, with a kind, and an integer that acts as a key to one of these other tables
/// This column is a foreign key to ONE OF: editors, terminals, searches // /// This column is a foreign key to ONE OF: editors, terminals, searches
/// - // /// -
// (workspace_id, item_id) // // (workspace_id, item_id)
// kind -> ::Editor:: // // kind -> ::Editor::
// -> // // ->
// At the workspace level // // At the workspace level
// -> (Workspace_ID, item_id) // // -> (Workspace_ID, item_id)
// -> One shot, big query, load everything up: // // -> One shot, big query, load everything up:
// -> SerializedWorkspace::deserialize(tx, itemKey) // // -> SerializedWorkspace::deserialize(tx, itemKey)
// -> SerializedEditor::deserialize(tx, itemKey) // // -> SerializedEditor::deserialize(tx, itemKey)
// -> // // ->
// -> Workspace::new(SerializedWorkspace) // // -> Workspace::new(SerializedWorkspace)
// -> Editor::new(serialized_workspace[???]serializedEditor) // // -> Editor::new(serialized_workspace[???]serializedEditor)
// //Pros: Keeps sql out of every body elese, makes changing it easier (e.g. for loading from a network or RocksDB) // // //Pros: Keeps sql out of every body elese, makes changing it easier (e.g. for loading from a network or RocksDB)
// //Cons: DB has to know the internals of the entire rest of the app // // //Cons: DB has to know the internals of the entire rest of the app
// Workspace // // Workspace
// Worktree roots // // Worktree roots
// Pane groups // // Pane groups
// Dock // // Dock
// Items // // Items
// Sidebars // // Sidebars
// Things I'm doing: finding about nullability for foreign keys // // Things I'm doing: finding about nullability for foreign keys
pub(crate) const ITEMS_M_1: &str = " // pub(crate) const ITEMS_M_1: &str = "
CREATE TABLE project_searches( // CREATE TABLE project_searches(
workspace_id INTEGER, // workspace_id INTEGER,
item_id INTEGER, // item_id INTEGER,
query TEXT, // query TEXT,
PRIMARY KEY (workspace_id, item_id) // PRIMARY KEY (workspace_id, item_id)
FOREIGN KEY(workspace_id) REFERENCES workspace_ids(workspace_id) // FOREIGN KEY(workspace_id) REFERENCES workspace_ids(workspace_id)
) STRICT; // ) STRICT;
CREATE TABLE editors( // CREATE TABLE editors(
workspace_id INTEGER, // workspace_id INTEGER,
item_id INTEGER, // item_id INTEGER,
path BLOB NOT NULL, // path BLOB NOT NULL,
PRIMARY KEY (workspace_id, item_id) // PRIMARY KEY (workspace_id, item_id)
FOREIGN KEY(workspace_id) REFERENCES workspace_ids(workspace_id) // FOREIGN KEY(workspace_id) REFERENCES workspace_ids(workspace_id)
) STRICT; // ) STRICT;
"; // ";
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct ItemId { pub struct ItemId {
@ -71,45 +71,45 @@ pub struct ItemId {
item_id: usize, item_id: usize,
} }
enum SerializedItemKind { // enum SerializedItemKind {
Editor, // Editor,
Diagnostics, // Diagnostics,
ProjectSearch, // ProjectSearch,
Terminal, // Terminal,
} // }
struct SerializedItemRow { // struct SerializedItemRow {
kind: SerializedItemKind, // kind: SerializedItemKind,
item_id: usize, // item_id: usize,
path: Option<Arc<Path>>, // path: Option<Arc<Path>>,
query: Option<String>, // query: Option<String>,
} // }
#[derive(Debug, PartialEq, Eq)] // #[derive(Debug, PartialEq, Eq)]
pub enum SerializedItem { // pub enum SerializedItem {
Editor { item_id: usize, path: Arc<Path> }, // Editor { item_id: usize, path: Arc<Path> },
Diagnostics { item_id: usize }, // Diagnostics { item_id: usize },
ProjectSearch { item_id: usize, query: String }, // ProjectSearch { item_id: usize, query: String },
Terminal { item_id: usize }, // Terminal { item_id: usize },
} // }
impl SerializedItem { // impl SerializedItem {
pub fn item_id(&self) -> usize { // pub fn item_id(&self) -> usize {
match self { // match self {
SerializedItem::Editor { item_id, .. } => *item_id, // SerializedItem::Editor { item_id, .. } => *item_id,
SerializedItem::Diagnostics { item_id } => *item_id, // SerializedItem::Diagnostics { item_id } => *item_id,
SerializedItem::ProjectSearch { item_id, .. } => *item_id, // SerializedItem::ProjectSearch { item_id, .. } => *item_id,
SerializedItem::Terminal { item_id } => *item_id, // SerializedItem::Terminal { item_id } => *item_id,
} // }
} // }
} // }
impl Db { // impl Db {
pub fn get_item(&self, item_id: ItemId) -> SerializedItem { // pub fn get_item(&self, item_id: ItemId) -> SerializedItem {
unimplemented!() // unimplemented!()
} // }
pub fn save_item(&self, workspace_id: WorkspaceId, item: &SerializedItem) {} // pub fn save_item(&self, workspace_id: WorkspaceId, item: &SerializedItem) {}
pub fn close_item(&self, item_id: ItemId) {} // pub fn close_item(&self, item_id: ItemId) {}
} // }

View File

@ -1,5 +1,4 @@
use gpui::Axis; use gpui::Axis;
use settings::DockAnchor;
use crate::{items::ItemId, workspace::WorkspaceId}; use crate::{items::ItemId, workspace::WorkspaceId};
@ -32,7 +31,7 @@ pub struct PaneGroupId {
} }
impl PaneGroupId { impl PaneGroupId {
pub(crate) fn root(workspace_id: WorkspaceId) -> Self { pub fn root(workspace_id: WorkspaceId) -> Self {
Self { Self {
workspace_id, workspace_id,
group_id: 0, group_id: 0,
@ -48,7 +47,7 @@ pub struct SerializedPaneGroup {
} }
impl SerializedPaneGroup { impl SerializedPaneGroup {
pub(crate) fn empty_root(workspace_id: WorkspaceId) -> Self { pub fn empty_root(workspace_id: WorkspaceId) -> Self {
Self { Self {
group_id: PaneGroupId::root(workspace_id), group_id: PaneGroupId::root(workspace_id),
axis: Default::default(), axis: Default::default(),
@ -136,6 +135,14 @@ CREATE TABLE dock_items(
COMMIT; COMMIT;
"; ";
#[derive(Default, Debug)]
pub enum DockAnchor {
#[default]
Bottom,
Right,
Expanded,
}
#[derive(Default, Debug)] #[derive(Default, Debug)]
pub struct SerializedDockPane { pub struct SerializedDockPane {
pub workspace: WorkspaceId, pub workspace: WorkspaceId,
@ -144,7 +151,7 @@ pub struct SerializedDockPane {
} }
impl Db { impl Db {
pub(crate) fn get_pane_group(&self, pane_group_id: PaneGroupId) -> SerializedPaneGroup { pub fn get_pane_group(&self, pane_group_id: PaneGroupId) -> SerializedPaneGroup {
let axis = self.get_pane_group_axis(pane_group_id); let axis = self.get_pane_group_axis(pane_group_id);
let mut children: Vec<(usize, PaneGroupChild)> = Vec::new(); let mut children: Vec<(usize, PaneGroupChild)> = Vec::new();
for child_row in self.get_pane_group_children(pane_group_id) { for child_row in self.get_pane_group_children(pane_group_id) {
@ -177,40 +184,39 @@ impl Db {
fn get_pane_group_children( fn get_pane_group_children(
&self, &self,
pane_group_id: PaneGroupId, _pane_group_id: PaneGroupId,
) -> impl Iterator<Item = PaneGroupChildRow> { ) -> impl Iterator<Item = PaneGroupChildRow> {
Vec::new().into_iter() Vec::new().into_iter()
} }
fn get_pane_group_axis(&self, pane_group_id: PaneGroupId) -> Axis { fn get_pane_group_axis(&self, _pane_group_id: PaneGroupId) -> Axis {
unimplemented!(); unimplemented!();
} }
pub fn save_pane_splits(&self, center_pane_group: SerializedPaneGroup) { pub fn save_pane_splits(&self, _center_pane_group: SerializedPaneGroup) {
// Delete the center pane group for this workspace and any of its children // Delete the center pane group for this workspace and any of its children
// Generate new pane group IDs as we go through // Generate new pane group IDs as we go through
// insert them // insert them
// Items garbage collect themselves when dropped // Items garbage collect themselves when dropped
} }
pub(crate) fn get_pane(&self, pane_id: PaneId) -> SerializedPane { pub(crate) fn get_pane(&self, _pane_id: PaneId) -> SerializedPane {
unimplemented!(); unimplemented!();
} }
pub fn get_dock_pane(&self, workspace: WorkspaceId) -> Option<SerializedDockPane> { pub fn get_dock_pane(&self, _workspace: WorkspaceId) -> Option<SerializedDockPane> {
unimplemented!() unimplemented!()
} }
pub fn save_dock_pane(&self, dock_pane: SerializedDockPane) {} pub fn save_dock_pane(&self, _dock_pane: SerializedDockPane) {}
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use settings::DockAnchor;
use crate::Db; use crate::Db;
use super::SerializedDockPane; use super::{DockAnchor, SerializedDockPane};
#[test] #[test]
fn test_basic_dock_pane() { fn test_basic_dock_pane() {
@ -226,6 +232,6 @@ mod tests {
shown: true, shown: true,
}); });
let new_workspace = db.workspace_for_roots(&["/tmp"]); let _new_workspace = db.workspace_for_roots(&["/tmp"]);
} }
} }

View File

@ -781,8 +781,14 @@ mod tests {
.await; .await;
let project = Project::test(app_state.fs.clone(), ["/test".as_ref()], cx).await; let project = Project::test(app_state.fs.clone(), ["/test".as_ref()], cx).await;
let (_, workspace) = let (_, workspace) = cx.add_window(|cx| {
cx.add_window(|cx| Workspace::new(project.clone(), |_, _| unimplemented!(), cx)); Workspace::new(
Default::default(),
project.clone(),
|_, _| unimplemented!(),
cx,
)
});
// Create some diagnostics // Create some diagnostics
project.update(cx, |project, cx| { project.update(cx, |project, cx| {

View File

@ -63,8 +63,14 @@ impl<'a> EditorLspTestContext<'a> {
.insert_tree("/root", json!({ "dir": { file_name: "" }})) .insert_tree("/root", json!({ "dir": { file_name: "" }}))
.await; .await;
let (window_id, workspace) = let (window_id, workspace) = cx.add_window(|cx| {
cx.add_window(|cx| Workspace::new(project.clone(), |_, _| unimplemented!(), cx)); Workspace::new(
Default::default(),
project.clone(),
|_, _| unimplemented!(),
cx,
)
});
project project
.update(cx, |project, cx| { .update(cx, |project, cx| {
project.find_or_create_local_worktree("/root", true, cx) project.find_or_create_local_worktree("/root", true, cx)

View File

@ -316,8 +316,9 @@ mod tests {
.await; .await;
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await; let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
let (window_id, workspace) = let (window_id, workspace) = cx.add_window(|cx| {
cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx)); Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
});
cx.dispatch_action(window_id, Toggle); cx.dispatch_action(window_id, Toggle);
let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap()); let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
@ -371,8 +372,9 @@ mod tests {
.await; .await;
let project = Project::test(app_state.fs.clone(), ["/dir".as_ref()], cx).await; let project = Project::test(app_state.fs.clone(), ["/dir".as_ref()], cx).await;
let (_, workspace) = let (_, workspace) = cx.add_window(|cx| {
cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx)); Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
});
let (_, finder) = let (_, finder) =
cx.add_window(|cx| FileFinder::new(workspace.read(cx).project().clone(), cx)); cx.add_window(|cx| FileFinder::new(workspace.read(cx).project().clone(), cx));
@ -446,8 +448,9 @@ mod tests {
cx, cx,
) )
.await; .await;
let (_, workspace) = let (_, workspace) = cx.add_window(|cx| {
cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx)); Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
});
let (_, finder) = let (_, finder) =
cx.add_window(|cx| FileFinder::new(workspace.read(cx).project().clone(), cx)); cx.add_window(|cx| FileFinder::new(workspace.read(cx).project().clone(), cx));
finder finder
@ -471,8 +474,9 @@ mod tests {
cx, cx,
) )
.await; .await;
let (_, workspace) = let (_, workspace) = cx.add_window(|cx| {
cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx)); Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
});
let (_, finder) = let (_, finder) =
cx.add_window(|cx| FileFinder::new(workspace.read(cx).project().clone(), cx)); cx.add_window(|cx| FileFinder::new(workspace.read(cx).project().clone(), cx));
@ -524,8 +528,9 @@ mod tests {
cx, cx,
) )
.await; .await;
let (_, workspace) = let (_, workspace) = cx.add_window(|cx| {
cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx)); Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
});
let (_, finder) = let (_, finder) =
cx.add_window(|cx| FileFinder::new(workspace.read(cx).project().clone(), cx)); cx.add_window(|cx| FileFinder::new(workspace.read(cx).project().clone(), cx));
@ -563,8 +568,9 @@ mod tests {
.await; .await;
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await; let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
let (_, workspace) = let (_, workspace) = cx.add_window(|cx| {
cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx)); Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
});
let (_, finder) = let (_, finder) =
cx.add_window(|cx| FileFinder::new(workspace.read(cx).project().clone(), cx)); cx.add_window(|cx| FileFinder::new(workspace.read(cx).project().clone(), cx));
finder finder

View File

@ -1393,8 +1393,14 @@ mod tests {
.await; .await;
let project = Project::test(fs.clone(), ["/root1".as_ref(), "/root2".as_ref()], cx).await; let project = Project::test(fs.clone(), ["/root1".as_ref(), "/root2".as_ref()], cx).await;
let (_, workspace) = let (_, workspace) = cx.add_window(|cx| {
cx.add_window(|cx| Workspace::new(project.clone(), |_, _| unimplemented!(), cx)); Workspace::new(
Default::default(),
project.clone(),
|_, _| unimplemented!(),
cx,
)
});
let panel = workspace.update(cx, |_, cx| ProjectPanel::new(project, cx)); let panel = workspace.update(cx, |_, cx| ProjectPanel::new(project, cx));
assert_eq!( assert_eq!(
visible_entries_as_strings(&panel, 0..50, cx), visible_entries_as_strings(&panel, 0..50, cx),
@ -1486,8 +1492,14 @@ mod tests {
.await; .await;
let project = Project::test(fs.clone(), ["/root1".as_ref(), "/root2".as_ref()], cx).await; let project = Project::test(fs.clone(), ["/root1".as_ref(), "/root2".as_ref()], cx).await;
let (_, workspace) = let (_, workspace) = cx.add_window(|cx| {
cx.add_window(|cx| Workspace::new(project.clone(), |_, _| unimplemented!(), cx)); Workspace::new(
Default::default(),
project.clone(),
|_, _| unimplemented!(),
cx,
)
});
let panel = workspace.update(cx, |_, cx| ProjectPanel::new(project, cx)); let panel = workspace.update(cx, |_, cx| ProjectPanel::new(project, cx));
select_path(&panel, "root1", cx); select_path(&panel, "root1", cx);

View File

@ -28,9 +28,14 @@ impl<'a> TerminalTestContext<'a> {
let params = self.cx.update(AppState::test); let params = self.cx.update(AppState::test);
let project = Project::test(params.fs.clone(), [], self.cx).await; let project = Project::test(params.fs.clone(), [], self.cx).await;
let (_, workspace) = self let (_, workspace) = self.cx.add_window(|cx| {
.cx Workspace::new(
.add_window(|cx| Workspace::new(project.clone(), |_, _| unimplemented!(), cx)); Default::default(),
project.clone(),
|_, _| unimplemented!(),
cx,
)
});
(project, workspace) (project, workspace)
} }

View File

@ -41,8 +41,14 @@ impl<'a> VimTestContext<'a> {
.insert_tree("/root", json!({ "dir": { "test.txt": "" } })) .insert_tree("/root", json!({ "dir": { "test.txt": "" } }))
.await; .await;
let (window_id, workspace) = let (window_id, workspace) = cx.add_window(|cx| {
cx.add_window(|cx| Workspace::new(project.clone(), |_, _| unimplemented!(), cx)); Workspace::new(
Default::default(),
project.clone(),
|_, _| unimplemented!(),
cx,
)
});
// Setup search toolbars // Setup search toolbars
workspace.update(cx, |workspace, cx| { workspace.update(cx, |workspace, cx| {

View File

@ -568,8 +568,9 @@ mod tests {
cx.update(|cx| init(cx)); cx.update(|cx| init(cx));
let project = Project::test(fs, [], cx).await; let project = Project::test(fs, [], cx).await;
let (window_id, workspace) = let (window_id, workspace) = cx.add_window(|cx| {
cx.add_window(|cx| Workspace::new(project, default_item_factory, cx)); Workspace::new(Default::default(), project, default_item_factory, cx)
});
workspace.update(cx, |workspace, cx| { workspace.update(cx, |workspace, cx| {
let left_panel = cx.add_view(|_| TestItem::new()); let left_panel = cx.add_view(|_| TestItem::new());

View File

@ -1645,8 +1645,9 @@ mod tests {
let fs = FakeFs::new(cx.background()); let fs = FakeFs::new(cx.background());
let project = Project::test(fs, None, cx).await; let project = Project::test(fs, None, cx).await;
let (_, workspace) = let (_, workspace) = cx.add_window(|cx| {
cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx)); Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
});
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
// 1. Add with a destination index // 1. Add with a destination index
@ -1734,8 +1735,9 @@ mod tests {
let fs = FakeFs::new(cx.background()); let fs = FakeFs::new(cx.background());
let project = Project::test(fs, None, cx).await; let project = Project::test(fs, None, cx).await;
let (_, workspace) = let (_, workspace) = cx.add_window(|cx| {
cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx)); Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
});
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
// 1. Add with a destination index // 1. Add with a destination index
@ -1811,8 +1813,9 @@ mod tests {
let fs = FakeFs::new(cx.background()); let fs = FakeFs::new(cx.background());
let project = Project::test(fs, None, cx).await; let project = Project::test(fs, None, cx).await;
let (_, workspace) = let (_, workspace) = cx.add_window(|cx| {
cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx)); Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
});
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
// singleton view // singleton view

View File

@ -1073,7 +1073,7 @@ pub enum Event {
pub struct Workspace { pub struct Workspace {
weak_self: WeakViewHandle<Self>, weak_self: WeakViewHandle<Self>,
db_id: WorkspaceId, _db_id: WorkspaceId,
client: Arc<Client>, client: Arc<Client>,
user_store: ModelHandle<client::UserStore>, user_store: ModelHandle<client::UserStore>,
remote_entity_subscription: Option<client::Subscription>, remote_entity_subscription: Option<client::Subscription>,
@ -1217,7 +1217,7 @@ impl Workspace {
let mut this = Workspace { let mut this = Workspace {
modal: None, modal: None,
weak_self: weak_handle, weak_self: weak_handle,
db_id: serialized_workspace.workspace_id, _db_id: serialized_workspace.workspace_id,
center: PaneGroup::new(center_pane.clone()), center: PaneGroup::new(center_pane.clone()),
dock, dock,
// When removing an item, the last element remaining in this array // When removing an item, the last element remaining in this array
@ -1250,16 +1250,14 @@ impl Workspace {
this this
} }
fn new_local<T, F>( fn new_local(
abs_paths: &[PathBuf], abs_paths: Vec<PathBuf>,
app_state: &Arc<AppState>, app_state: Arc<AppState>,
cx: &mut MutableAppContext, cx: &mut MutableAppContext,
callback: F, ) -> Task<(
) -> Task<T> ViewHandle<Workspace>,
where Vec<Option<Result<Box<dyn ItemHandle>, Arc<anyhow::Error>>>>,
T: 'static, )> {
F: 'static + FnOnce(&mut Workspace, &mut ViewContext<Workspace>) -> T,
{
let project_handle = Project::local( let project_handle = Project::local(
app_state.client.clone(), app_state.client.clone(),
app_state.user_store.clone(), app_state.user_store.clone(),
@ -1273,21 +1271,25 @@ impl Workspace {
// Get project paths for all of the abs_paths // Get project paths for all of the abs_paths
let mut worktree_roots: HashSet<Arc<Path>> = Default::default(); let mut worktree_roots: HashSet<Arc<Path>> = Default::default();
let mut project_paths = Vec::new(); let mut project_paths = Vec::new();
for path in abs_paths { for path in abs_paths.iter() {
if let Some((worktree, project_entry)) = cx if let Some((worktree, project_entry)) = cx
.update(|cx| Workspace::project_path_for_path(project_handle, path, true, cx)) .update(|cx| {
Workspace::project_path_for_path(project_handle.clone(), &path, true, cx)
})
.await .await
.log_err() .log_err()
{ {
worktree_roots.insert(worktree.read_with(&mut cx, |tree, _| tree.abs_path())); worktree_roots.insert(worktree.read_with(&mut cx, |tree, _| tree.abs_path()));
project_paths.push(project_entry); project_paths.push(Some(project_entry));
} else {
project_paths.push(None);
} }
} }
// Use the resolved worktree roots to get the serialized_db from the database // Use the resolved worktree roots to get the serialized_db from the database
let serialized_workspace = cx.read(|cx| { let serialized_workspace = cx.read(|cx| {
cx.global::<Db>() cx.global::<Db>()
.workspace_for_worktree_roots(&Vec::from_iter(worktree_roots.into_iter())[..]) .workspace_for_roots(&Vec::from_iter(worktree_roots.into_iter())[..])
}); });
// Use the serialized workspace to construct the new window // Use the serialized workspace to construct the new window
@ -1303,18 +1305,36 @@ impl Workspace {
}); });
// Call open path for each of the project paths // Call open path for each of the project paths
// (this will bring them to the front if they were in kthe serialized workspace) // (this will bring them to the front if they were in the serialized workspace)
let tasks = workspace.update(&mut cx, |workspace, cx| { debug_assert!(abs_paths.len() == project_paths.len());
let tasks = Vec::new(); let tasks = abs_paths
for path in project_paths { .iter()
tasks.push(workspace.open_path(path, true, cx)); .cloned()
} .zip(project_paths.into_iter())
tasks .map(|(abs_path, project_path)| {
}); let workspace = workspace.clone();
futures::future::join_all(tasks.into_iter()).await; cx.spawn(|mut cx| {
let fs = app_state.fs.clone();
async move {
let project_path = project_path?;
if fs.is_file(&abs_path).await {
Some(
workspace
.update(&mut cx, |workspace, cx| {
workspace.open_path(project_path, true, cx)
})
.await,
)
} else {
None
}
}
})
});
// Finally call callback on the workspace let opened_items = futures::future::join_all(tasks.into_iter()).await;
workspace.update(&mut cx, |workspace, cx| callback(workspace, cx))
(workspace, opened_items)
}) })
} }
@ -1371,12 +1391,16 @@ impl Workspace {
) -> Task<T> ) -> Task<T>
where where
T: 'static, T: 'static,
F: FnOnce(&mut Workspace, &mut ViewContext<Workspace>) -> T, F: 'static + FnOnce(&mut Workspace, &mut ViewContext<Workspace>) -> T,
{ {
if self.project.read(cx).is_local() { if self.project.read(cx).is_local() {
Task::Ready(Some(callback(self, cx))) Task::Ready(Some(callback(self, cx)))
} else { } else {
Self::new_local(&[], app_state, cx, callback) let task = Self::new_local(Vec::new(), app_state.clone(), cx);
cx.spawn(|_vh, mut cx| async move {
let (workspace, _) = task.await;
workspace.update(&mut cx, callback)
})
} }
} }
@ -1539,7 +1563,7 @@ impl Workspace {
for path in &abs_paths { for path in &abs_paths {
project_paths.push( project_paths.push(
this.update(&mut cx, |this, cx| { this.update(&mut cx, |this, cx| {
Workspace::project_path_for_path(this.project, path, visible, cx) Workspace::project_path_for_path(this.project.clone(), path, visible, cx)
}) })
.await .await
.log_err(), .log_err(),
@ -3017,8 +3041,15 @@ pub fn open_paths(
let app_state = app_state.clone(); let app_state = app_state.clone();
let abs_paths = abs_paths.to_vec(); let abs_paths = abs_paths.to_vec();
cx.spawn(|mut cx| async move { cx.spawn(|mut cx| async move {
let workspace = if let Some(existing) = existing { if let Some(existing) = existing {
existing (
existing.clone(),
existing
.update(&mut cx, |workspace, cx| {
workspace.open_paths(abs_paths, true, cx)
})
.await,
)
} else { } else {
let contains_directory = let contains_directory =
futures::future::join_all(abs_paths.iter().map(|path| app_state.fs.is_file(path))) futures::future::join_all(abs_paths.iter().map(|path| app_state.fs.is_file(path)))
@ -3026,28 +3057,32 @@ pub fn open_paths(
.contains(&false); .contains(&false);
cx.update(|cx| { cx.update(|cx| {
Workspace::new_local(&abs_paths[..], &app_state, cx, move |workspace, cx| { let task = Workspace::new_local(abs_paths, app_state.clone(), cx);
if contains_directory {
workspace.toggle_sidebar(SidebarSide::Left, cx); cx.spawn(|mut cx| async move {
} let (workspace, items) = task.await;
cx.handle()
workspace.update(&mut cx, |workspace, cx| {
if contains_directory {
workspace.toggle_sidebar(SidebarSide::Left, cx);
}
});
(workspace, items)
}) })
}) })
.await .await
}; }
let items = workspace
.update(&mut cx, |workspace, cx| {
workspace.open_paths(abs_paths, true, cx)
})
.await;
(workspace, items)
}) })
} }
fn open_new(app_state: &Arc<AppState>, cx: &mut MutableAppContext) -> Task<()> { fn open_new(app_state: &Arc<AppState>, cx: &mut MutableAppContext) -> Task<()> {
Workspace::new_local(&[], app_state, cx, |_, cx| cx.dispatch_action(NewFile)) let task = Workspace::new_local(Vec::new(), app_state.clone(), cx);
cx.spawn(|mut cx| async move {
let (workspace, _) = task.await;
workspace.update(&mut cx, |_, cx| cx.dispatch_action(NewFile))
})
} }
#[cfg(test)] #[cfg(test)]
@ -3076,8 +3111,14 @@ mod tests {
let fs = FakeFs::new(cx.background()); let fs = FakeFs::new(cx.background());
let project = Project::test(fs, [], cx).await; let project = Project::test(fs, [], cx).await;
let (_, workspace) = let (_, workspace) = cx.add_window(|cx| {
cx.add_window(|cx| Workspace::new(project.clone(), default_item_factory, cx)); Workspace::new(
Default::default(),
project.clone(),
default_item_factory,
cx,
)
});
// Adding an item with no ambiguity renders the tab without detail. // Adding an item with no ambiguity renders the tab without detail.
let item1 = cx.add_view(&workspace, |_| { let item1 = cx.add_view(&workspace, |_| {
@ -3141,8 +3182,14 @@ mod tests {
.await; .await;
let project = Project::test(fs, ["root1".as_ref()], cx).await; let project = Project::test(fs, ["root1".as_ref()], cx).await;
let (window_id, workspace) = let (window_id, workspace) = cx.add_window(|cx| {
cx.add_window(|cx| Workspace::new(project.clone(), default_item_factory, cx)); Workspace::new(
Default::default(),
project.clone(),
default_item_factory,
cx,
)
});
let worktree_id = project.read_with(cx, |project, cx| { let worktree_id = project.read_with(cx, |project, cx| {
project.worktrees(cx).next().unwrap().read(cx).id() project.worktrees(cx).next().unwrap().read(cx).id()
}); });
@ -3238,8 +3285,14 @@ mod tests {
fs.insert_tree("/root", json!({ "one": "" })).await; fs.insert_tree("/root", json!({ "one": "" })).await;
let project = Project::test(fs, ["root".as_ref()], cx).await; let project = Project::test(fs, ["root".as_ref()], cx).await;
let (window_id, workspace) = let (window_id, workspace) = cx.add_window(|cx| {
cx.add_window(|cx| Workspace::new(project.clone(), default_item_factory, cx)); Workspace::new(
Default::default(),
project.clone(),
default_item_factory,
cx,
)
});
// When there are no dirty items, there's nothing to do. // When there are no dirty items, there's nothing to do.
let item1 = cx.add_view(&workspace, |_| TestItem::new()); let item1 = cx.add_view(&workspace, |_| TestItem::new());
@ -3279,8 +3332,8 @@ mod tests {
let fs = FakeFs::new(cx.background()); let fs = FakeFs::new(cx.background());
let project = Project::test(fs, None, cx).await; let project = Project::test(fs, None, cx).await;
let (window_id, workspace) = let (window_id, workspace) = cx
cx.add_window(|cx| Workspace::new(project, default_item_factory, cx)); .add_window(|cx| Workspace::new(Default::default(), project, default_item_factory, cx));
let item1 = cx.add_view(&workspace, |_| { let item1 = cx.add_view(&workspace, |_| {
let mut item = TestItem::new(); let mut item = TestItem::new();
@ -3375,8 +3428,8 @@ mod tests {
let fs = FakeFs::new(cx.background()); let fs = FakeFs::new(cx.background());
let project = Project::test(fs, [], cx).await; let project = Project::test(fs, [], cx).await;
let (window_id, workspace) = let (window_id, workspace) = cx
cx.add_window(|cx| Workspace::new(project, default_item_factory, cx)); .add_window(|cx| Workspace::new(Default::default(), project, default_item_factory, cx));
// Create several workspace items with single project entries, and two // Create several workspace items with single project entries, and two
// workspace items with multiple project entries. // workspace items with multiple project entries.
@ -3477,8 +3530,8 @@ mod tests {
let fs = FakeFs::new(cx.background()); let fs = FakeFs::new(cx.background());
let project = Project::test(fs, [], cx).await; let project = Project::test(fs, [], cx).await;
let (window_id, workspace) = let (window_id, workspace) = cx
cx.add_window(|cx| Workspace::new(project, default_item_factory, cx)); .add_window(|cx| Workspace::new(Default::default(), project, default_item_factory, cx));
let item = cx.add_view(&workspace, |_| { let item = cx.add_view(&workspace, |_| {
let mut item = TestItem::new(); let mut item = TestItem::new();
@ -3595,7 +3648,8 @@ mod tests {
let fs = FakeFs::new(cx.background()); let fs = FakeFs::new(cx.background());
let project = Project::test(fs, [], cx).await; let project = Project::test(fs, [], cx).await;
let (_, workspace) = cx.add_window(|cx| Workspace::new(project, default_item_factory, cx)); let (_, workspace) = cx
.add_window(|cx| Workspace::new(Default::default(), project, default_item_factory, cx));
let item = cx.add_view(&workspace, |_| { let item = cx.add_view(&workspace, |_| {
let mut item = TestItem::new(); let mut item = TestItem::new();

View File

@ -23,7 +23,7 @@ use isahc::{config::Configurable, Request};
use language::LanguageRegistry; use language::LanguageRegistry;
use log::LevelFilter; use log::LevelFilter;
use parking_lot::Mutex; use parking_lot::Mutex;
use project::{Fs, HomeDir, ProjectStore}; use project::{Db, Fs, HomeDir, ProjectStore};
use serde_json::json; use serde_json::json;
use settings::{ use settings::{
self, settings_file::SettingsFile, KeymapFileContent, Settings, SettingsFileContent, self, settings_file::SettingsFile, KeymapFileContent, Settings, SettingsFileContent,
@ -148,7 +148,9 @@ fn main() {
let project_store = cx.add_model(|_| ProjectStore::new()); let project_store = cx.add_model(|_| ProjectStore::new());
let db = cx.background().block(db); let db = cx.background().block(db);
client.start_telemetry(db.clone()); cx.set_global(db);
client.start_telemetry(cx.global::<Db>().clone());
client.report_event("start app", Default::default()); client.report_event("start app", Default::default());
let app_state = Arc::new(AppState { let app_state = Arc::new(AppState {
@ -162,7 +164,12 @@ fn main() {
initialize_workspace, initialize_workspace,
default_item_factory, default_item_factory,
}); });
auto_update::init(db, http, cx); auto_update::init(
cx.global::<Db>().clone(),
http,
client::ZED_SERVER_URL.clone(),
cx,
);
workspace::init(app_state.clone(), cx); workspace::init(app_state.clone(), cx);
journal::init(app_state.clone(), cx); journal::init(app_state.clone(), cx);
theme_selector::init(app_state.clone(), cx); theme_selector::init(app_state.clone(), cx);

View File

@ -463,10 +463,11 @@ fn open_config_file(
workspace workspace
.update(&mut cx, |workspace, cx| { .update(&mut cx, |workspace, cx| {
workspace.with_local_workspace(app_state, cx, |workspace, cx| { workspace.with_local_workspace(&app_state, cx, |workspace, cx| {
workspace.open_paths(vec![path.to_path_buf()], false, cx) workspace.open_paths(vec![path.to_path_buf()], false, cx)
}) })
}) })
.await
.await; .await;
Ok::<_, anyhow::Error>(()) Ok::<_, anyhow::Error>(())
}) })
@ -480,51 +481,55 @@ fn open_log_file(
) { ) {
const MAX_LINES: usize = 1000; const MAX_LINES: usize = 1000;
workspace.with_local_workspace(app_state.clone(), cx, |_, cx| { workspace
cx.spawn_weak(|workspace, mut cx| async move { .with_local_workspace(&app_state.clone(), cx, move |_, cx| {
let (old_log, new_log) = futures::join!( cx.spawn_weak(|workspace, mut cx| async move {
app_state.fs.load(&paths::OLD_LOG), let (old_log, new_log) = futures::join!(
app_state.fs.load(&paths::LOG) app_state.fs.load(&paths::OLD_LOG),
); app_state.fs.load(&paths::LOG)
);
if let Some(workspace) = workspace.upgrade(&cx) { if let Some(workspace) = workspace.upgrade(&cx) {
let mut lines = VecDeque::with_capacity(MAX_LINES); let mut lines = VecDeque::with_capacity(MAX_LINES);
for line in old_log for line in old_log
.iter() .iter()
.flat_map(|log| log.lines()) .flat_map(|log| log.lines())
.chain(new_log.iter().flat_map(|log| log.lines())) .chain(new_log.iter().flat_map(|log| log.lines()))
{ {
if lines.len() == MAX_LINES { if lines.len() == MAX_LINES {
lines.pop_front(); lines.pop_front();
}
lines.push_back(line);
} }
lines.push_back(line); let log = lines
} .into_iter()
let log = lines .flat_map(|line| [line, "\n"])
.into_iter() .collect::<String>();
.flat_map(|line| [line, "\n"])
.collect::<String>();
workspace.update(&mut cx, |workspace, cx| { workspace.update(&mut cx, |workspace, cx| {
let project = workspace.project().clone(); let project = workspace.project().clone();
let buffer = project let buffer = project
.update(cx, |project, cx| project.create_buffer("", None, cx)) .update(cx, |project, cx| project.create_buffer("", None, cx))
.expect("creating buffers on a local workspace always succeeds"); .expect("creating buffers on a local workspace always succeeds");
buffer.update(cx, |buffer, cx| buffer.edit([(0..0, log)], None, cx)); buffer.update(cx, |buffer, cx| buffer.edit([(0..0, log)], None, cx));
let buffer = cx.add_model(|cx| { let buffer = cx.add_model(|cx| {
MultiBuffer::singleton(buffer, cx).with_title("Log".into()) MultiBuffer::singleton(buffer, cx).with_title("Log".into())
});
workspace.add_item(
Box::new(
cx.add_view(|cx| {
Editor::for_multibuffer(buffer, Some(project), cx)
}),
),
cx,
);
}); });
workspace.add_item( }
Box::new( })
cx.add_view(|cx| Editor::for_multibuffer(buffer, Some(project), cx)), .detach();
),
cx,
);
});
}
}) })
.detach(); .detach();
});
} }
fn open_telemetry_log_file( fn open_telemetry_log_file(
@ -532,7 +537,7 @@ fn open_telemetry_log_file(
app_state: Arc<AppState>, app_state: Arc<AppState>,
cx: &mut ViewContext<Workspace>, cx: &mut ViewContext<Workspace>,
) { ) {
workspace.with_local_workspace(app_state.clone(), cx, |_, cx| { workspace.with_local_workspace(&app_state.clone(), cx, move |_, cx| {
cx.spawn_weak(|workspace, mut cx| async move { cx.spawn_weak(|workspace, mut cx| async move {
let workspace = workspace.upgrade(&cx)?; let workspace = workspace.upgrade(&cx)?;
let path = app_state.client.telemetry_log_file_path()?; let path = app_state.client.telemetry_log_file_path()?;
@ -580,31 +585,36 @@ fn open_telemetry_log_file(
Some(()) Some(())
}) })
.detach(); .detach();
}); }).detach();
} }
fn open_bundled_config_file( fn open_bundled_config_file(
workspace: &mut Workspace, workspace: &mut Workspace,
app_state: Arc<AppState>, app_state: Arc<AppState>,
asset_path: &'static str, asset_path: &'static str,
title: &str, title: &'static str,
cx: &mut ViewContext<Workspace>, cx: &mut ViewContext<Workspace>,
) { ) {
workspace.with_local_workspace(cx, app_state, |workspace, cx| { workspace
let project = workspace.project().clone(); .with_local_workspace(&app_state.clone(), cx, |workspace, cx| {
let buffer = project.update(cx, |project, cx| { let project = workspace.project().clone();
let text = Assets::get(asset_path).unwrap().data; let buffer = project.update(cx, |project, cx| {
let text = str::from_utf8(text.as_ref()).unwrap(); let text = Assets::get(asset_path).unwrap().data;
project let text = str::from_utf8(text.as_ref()).unwrap();
.create_buffer(text, project.languages().get_language("JSON"), cx) project
.expect("creating buffers on a local workspace always succeeds") .create_buffer(text, project.languages().get_language("JSON"), cx)
}); .expect("creating buffers on a local workspace always succeeds")
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx).with_title(title.into())); });
workspace.add_item( let buffer =
Box::new(cx.add_view(|cx| Editor::for_multibuffer(buffer, Some(project.clone()), cx))), cx.add_model(|cx| MultiBuffer::singleton(buffer, cx).with_title(title.into()));
cx, workspace.add_item(
); Box::new(
}); cx.add_view(|cx| Editor::for_multibuffer(buffer, Some(project.clone()), cx)),
),
cx,
);
})
.detach();
} }
fn schema_file_match(path: &Path) -> &Path { fn schema_file_match(path: &Path) -> &Path {
@ -808,8 +818,9 @@ mod tests {
.await; .await;
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await; let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
let (_, workspace) = let (_, workspace) = cx.add_window(|cx| {
cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx)); Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
});
let entries = cx.read(|cx| workspace.file_project_paths(cx)); let entries = cx.read(|cx| workspace.file_project_paths(cx));
let file1 = entries[0].clone(); let file1 = entries[0].clone();
@ -928,8 +939,9 @@ mod tests {
.await; .await;
let project = Project::test(app_state.fs.clone(), ["/dir1".as_ref()], cx).await; let project = Project::test(app_state.fs.clone(), ["/dir1".as_ref()], cx).await;
let (_, workspace) = let (_, workspace) = cx.add_window(|cx| {
cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx)); Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
});
// Open a file within an existing worktree. // Open a file within an existing worktree.
cx.update(|cx| { cx.update(|cx| {
@ -1088,8 +1100,9 @@ mod tests {
.await; .await;
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await; let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
let (window_id, workspace) = let (window_id, workspace) = cx.add_window(|cx| {
cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx)); Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
});
// Open a file within an existing worktree. // Open a file within an existing worktree.
cx.update(|cx| { cx.update(|cx| {
@ -1131,8 +1144,9 @@ mod tests {
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await; let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
project.update(cx, |project, _| project.languages().add(rust_lang())); project.update(cx, |project, _| project.languages().add(rust_lang()));
let (window_id, workspace) = let (window_id, workspace) = cx.add_window(|cx| {
cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx)); Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
});
let worktree = cx.read(|cx| workspace.read(cx).worktrees(cx).next().unwrap()); let worktree = cx.read(|cx| workspace.read(cx).worktrees(cx).next().unwrap());
// Create a new untitled buffer // Create a new untitled buffer
@ -1221,8 +1235,9 @@ mod tests {
let project = Project::test(app_state.fs.clone(), [], cx).await; let project = Project::test(app_state.fs.clone(), [], cx).await;
project.update(cx, |project, _| project.languages().add(rust_lang())); project.update(cx, |project, _| project.languages().add(rust_lang()));
let (window_id, workspace) = let (window_id, workspace) = cx.add_window(|cx| {
cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx)); Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
});
// Create a new untitled buffer // Create a new untitled buffer
cx.dispatch_action(window_id, NewFile); cx.dispatch_action(window_id, NewFile);
@ -1275,8 +1290,9 @@ mod tests {
.await; .await;
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await; let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
let (window_id, workspace) = let (window_id, workspace) = cx.add_window(|cx| {
cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx)); Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
});
let entries = cx.read(|cx| workspace.file_project_paths(cx)); let entries = cx.read(|cx| workspace.file_project_paths(cx));
let file1 = entries[0].clone(); let file1 = entries[0].clone();
@ -1350,8 +1366,14 @@ mod tests {
.await; .await;
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await; let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
let (_, workspace) = let (_, workspace) = cx.add_window(|cx| {
cx.add_window(|cx| Workspace::new(project.clone(), |_, _| unimplemented!(), cx)); Workspace::new(
Default::default(),
project.clone(),
|_, _| unimplemented!(),
cx,
)
});
let entries = cx.read(|cx| workspace.file_project_paths(cx)); let entries = cx.read(|cx| workspace.file_project_paths(cx));
let file1 = entries[0].clone(); let file1 = entries[0].clone();
@ -1615,8 +1637,14 @@ mod tests {
.await; .await;
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await; let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
let (_, workspace) = let (_, workspace) = cx.add_window(|cx| {
cx.add_window(|cx| Workspace::new(project.clone(), |_, _| unimplemented!(), cx)); Workspace::new(
Default::default(),
project.clone(),
|_, _| unimplemented!(),
cx,
)
});
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
let entries = cx.read(|cx| workspace.file_project_paths(cx)); let entries = cx.read(|cx| workspace.file_project_paths(cx));