Detailed changes
@@ -428,6 +428,7 @@ version = "0.1.0"
dependencies = [
"anyhow",
"client",
+ "db",
"gpui",
"isahc",
"lazy_static",
@@ -1560,7 +1561,6 @@ dependencies = [
"rusqlite_migration",
"serde",
"serde_rusqlite",
- "settings",
"tempdir",
]
@@ -81,3 +81,4 @@ split-debuginfo = "unpacked"
[profile.release]
debug = true
+
@@ -8,6 +8,7 @@ path = "src/auto_update.rs"
doctest = false
[dependencies]
+db = { path = "../db" }
client = { path = "../client" }
gpui = { path = "../gpui" }
menu = { path = "../menu" }
@@ -1,7 +1,8 @@
mod update_notification;
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::{
actions, platform::AppVersion, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle,
MutableAppContext, Task, WeakViewHandle,
@@ -55,11 +56,16 @@ impl Entity for AutoUpdater {
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()) {
- let server_url = ZED_SERVER_URL.to_string();
+ let server_url = server_url;
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
});
@@ -905,8 +905,14 @@ async fn test_host_disconnect(
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()));
- let (_, workspace_b) =
- cx_b.add_window(|cx| Workspace::new(project_b.clone(), |_, _| unimplemented!(), cx));
+ let (_, workspace_b) = cx_b.add_window(|cx| {
+ Workspace::new(
+ Default::default(),
+ project_b.clone(),
+ |_, _| unimplemented!(),
+ cx,
+ )
+ });
let editor_b = workspace_b
.update(cx_b, |workspace, 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.
let project_b = client_b.build_remote_project(project_id, cx_b).await;
- let (_window_b, workspace_b) =
- cx_b.add_window(|cx| Workspace::new(project_b.clone(), |_, _| unimplemented!(), cx));
+ let (_window_b, workspace_b) = cx_b.add_window(|cx| {
+ Workspace::new(
+ Default::default(),
+ project_b.clone(),
+ |_, _| unimplemented!(),
+ cx,
+ )
+ });
let editor_b = workspace_b
.update(cx_b, |workspace, 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();
let project_b = client_b.build_remote_project(project_id, cx_b).await;
- let (_window_b, workspace_b) =
- cx_b.add_window(|cx| Workspace::new(project_b.clone(), |_, _| unimplemented!(), cx));
+ let (_window_b, workspace_b) = cx_b.add_window(|cx| {
+ Workspace::new(
+ Default::default(),
+ project_b.clone(),
+ |_, _| unimplemented!(),
+ cx,
+ )
+ });
let editor_b = workspace_b
.update(cx_b, |workspace, cx| {
workspace.open_path((worktree_id, "one.rs"), None, true, cx)
@@ -6054,7 +6072,12 @@ impl TestClient {
) -> ViewHandle<Workspace> {
let (_, root_view) = cx.add_window(|_| EmptyView);
cx.add_view(&root_view, |cx| {
- Workspace::new(project.clone(), |_, _| unimplemented!(), cx)
+ Workspace::new(
+ Default::default(),
+ project.clone(),
+ |_, _| unimplemented!(),
+ cx,
+ )
})
}
@@ -51,7 +51,12 @@ pub fn init(app_state: Arc<AppState>, cx: &mut MutableAppContext) {
.await?;
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);
workspace
});
@@ -350,8 +350,9 @@ mod tests {
});
let project = Project::test(app_state.fs.clone(), [], cx).await;
- let (_, workspace) =
- cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx));
+ let (_, workspace) = cx.add_window(|cx| {
+ Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
+ });
let editor = cx.add_view(&workspace, |cx| {
let mut editor = Editor::single_line(None, cx);
editor.set_text("abc", cx);
@@ -13,7 +13,6 @@ test-support = []
[dependencies]
collections = { path = "../collections" }
gpui = { path = "../gpui" }
-settings = { path = "../settings" }
anyhow = "1.0.57"
async-trait = "0.1"
lazy_static = "1.4.0"
@@ -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 settings::DockAnchor;
+use db::pane::{DockAnchor, SerializedDockPane};
const TEST_FILE: &'static str = "test-db.db";
@@ -25,7 +24,7 @@ fn main() -> anyhow::Result<()> {
shown: true,
});
- let new_workspace = db.workspace_for_roots(&["/tmp"]);
+ let _new_workspace = db.workspace_for_roots(&["/tmp"]);
db.write_to(file).ok();
@@ -1,69 +1,69 @@
-use std::{
- ffi::OsStr,
- fmt::Display,
- hash::Hash,
- os::unix::prelude::OsStrExt,
- path::{Path, PathBuf},
- sync::Arc,
-};
-
-use anyhow::Result;
-use collections::HashSet;
-use rusqlite::{named_params, params, types::FromSql};
-
-use crate::workspace::WorkspaceId;
-
-use super::Db;
-
-/// 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
-/// - 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
-/// -
-
-// (workspace_id, item_id)
-// kind -> ::Editor::
-
-// ->
-// At the workspace level
-// -> (Workspace_ID, item_id)
-// -> One shot, big query, load everything up:
-
-// -> SerializedWorkspace::deserialize(tx, itemKey)
-// -> SerializedEditor::deserialize(tx, itemKey)
-
-// ->
-// -> Workspace::new(SerializedWorkspace)
-// -> 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)
-// //Cons: DB has to know the internals of the entire rest of the app
-
-// Workspace
-// Worktree roots
-// Pane groups
-// Dock
-// Items
-// Sidebars
-
-// Things I'm doing: finding about nullability for foreign keys
-pub(crate) const ITEMS_M_1: &str = "
-CREATE TABLE project_searches(
- workspace_id INTEGER,
- item_id INTEGER,
- query TEXT,
- PRIMARY KEY (workspace_id, item_id)
- FOREIGN KEY(workspace_id) REFERENCES workspace_ids(workspace_id)
-) STRICT;
-
-CREATE TABLE editors(
- workspace_id INTEGER,
- item_id INTEGER,
- path BLOB NOT NULL,
- PRIMARY KEY (workspace_id, item_id)
- FOREIGN KEY(workspace_id) REFERENCES workspace_ids(workspace_id)
-) STRICT;
-";
+// use std::{
+// ffi::OsStr,
+// fmt::Display,
+// hash::Hash,
+// os::unix::prelude::OsStrExt,
+// path::{Path, PathBuf},
+// sync::Arc,
+// };
+
+// use anyhow::Result;
+// use collections::HashSet;
+// use rusqlite::{named_params, params, types::FromSql};
+
+// use crate::workspace::WorkspaceId;
+
+// use super::Db;
+
+// /// 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
+// /// - 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
+// /// -
+
+// // (workspace_id, item_id)
+// // kind -> ::Editor::
+
+// // ->
+// // At the workspace level
+// // -> (Workspace_ID, item_id)
+// // -> One shot, big query, load everything up:
+
+// // -> SerializedWorkspace::deserialize(tx, itemKey)
+// // -> SerializedEditor::deserialize(tx, itemKey)
+
+// // ->
+// // -> Workspace::new(SerializedWorkspace)
+// // -> 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)
+// // //Cons: DB has to know the internals of the entire rest of the app
+
+// // Workspace
+// // Worktree roots
+// // Pane groups
+// // Dock
+// // Items
+// // Sidebars
+
+// // Things I'm doing: finding about nullability for foreign keys
+// pub(crate) const ITEMS_M_1: &str = "
+// CREATE TABLE project_searches(
+// workspace_id INTEGER,
+// item_id INTEGER,
+// query TEXT,
+// PRIMARY KEY (workspace_id, item_id)
+// FOREIGN KEY(workspace_id) REFERENCES workspace_ids(workspace_id)
+// ) STRICT;
+
+// CREATE TABLE editors(
+// workspace_id INTEGER,
+// item_id INTEGER,
+// path BLOB NOT NULL,
+// PRIMARY KEY (workspace_id, item_id)
+// FOREIGN KEY(workspace_id) REFERENCES workspace_ids(workspace_id)
+// ) STRICT;
+// ";
#[derive(Debug, PartialEq, Eq)]
pub struct ItemId {
@@ -71,45 +71,45 @@ pub struct ItemId {
item_id: usize,
}
-enum SerializedItemKind {
- Editor,
- Diagnostics,
- ProjectSearch,
- Terminal,
-}
-
-struct SerializedItemRow {
- kind: SerializedItemKind,
- item_id: usize,
- path: Option<Arc<Path>>,
- query: Option<String>,
-}
-
-#[derive(Debug, PartialEq, Eq)]
-pub enum SerializedItem {
- Editor { item_id: usize, path: Arc<Path> },
- Diagnostics { item_id: usize },
- ProjectSearch { item_id: usize, query: String },
- Terminal { item_id: usize },
-}
-
-impl SerializedItem {
- pub fn item_id(&self) -> usize {
- match self {
- SerializedItem::Editor { item_id, .. } => *item_id,
- SerializedItem::Diagnostics { item_id } => *item_id,
- SerializedItem::ProjectSearch { item_id, .. } => *item_id,
- SerializedItem::Terminal { item_id } => *item_id,
- }
- }
-}
-
-impl Db {
- pub fn get_item(&self, item_id: ItemId) -> SerializedItem {
- unimplemented!()
- }
-
- pub fn save_item(&self, workspace_id: WorkspaceId, item: &SerializedItem) {}
-
- pub fn close_item(&self, item_id: ItemId) {}
-}
+// enum SerializedItemKind {
+// Editor,
+// Diagnostics,
+// ProjectSearch,
+// Terminal,
+// }
+
+// struct SerializedItemRow {
+// kind: SerializedItemKind,
+// item_id: usize,
+// path: Option<Arc<Path>>,
+// query: Option<String>,
+// }
+
+// #[derive(Debug, PartialEq, Eq)]
+// pub enum SerializedItem {
+// Editor { item_id: usize, path: Arc<Path> },
+// Diagnostics { item_id: usize },
+// ProjectSearch { item_id: usize, query: String },
+// Terminal { item_id: usize },
+// }
+
+// impl SerializedItem {
+// pub fn item_id(&self) -> usize {
+// match self {
+// SerializedItem::Editor { item_id, .. } => *item_id,
+// SerializedItem::Diagnostics { item_id } => *item_id,
+// SerializedItem::ProjectSearch { item_id, .. } => *item_id,
+// SerializedItem::Terminal { item_id } => *item_id,
+// }
+// }
+// }
+
+// impl Db {
+// pub fn get_item(&self, item_id: ItemId) -> SerializedItem {
+// unimplemented!()
+// }
+
+// pub fn save_item(&self, workspace_id: WorkspaceId, item: &SerializedItem) {}
+
+// pub fn close_item(&self, item_id: ItemId) {}
+// }
@@ -1,5 +1,4 @@
use gpui::Axis;
-use settings::DockAnchor;
use crate::{items::ItemId, workspace::WorkspaceId};
@@ -32,7 +31,7 @@ pub struct PaneGroupId {
}
impl PaneGroupId {
- pub(crate) fn root(workspace_id: WorkspaceId) -> Self {
+ pub fn root(workspace_id: WorkspaceId) -> Self {
Self {
workspace_id,
group_id: 0,
@@ -48,7 +47,7 @@ pub struct SerializedPaneGroup {
}
impl SerializedPaneGroup {
- pub(crate) fn empty_root(workspace_id: WorkspaceId) -> Self {
+ pub fn empty_root(workspace_id: WorkspaceId) -> Self {
Self {
group_id: PaneGroupId::root(workspace_id),
axis: Default::default(),
@@ -136,6 +135,14 @@ CREATE TABLE dock_items(
COMMIT;
";
+#[derive(Default, Debug)]
+pub enum DockAnchor {
+ #[default]
+ Bottom,
+ Right,
+ Expanded,
+}
+
#[derive(Default, Debug)]
pub struct SerializedDockPane {
pub workspace: WorkspaceId,
@@ -144,7 +151,7 @@ pub struct SerializedDockPane {
}
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 mut children: Vec<(usize, PaneGroupChild)> = Vec::new();
for child_row in self.get_pane_group_children(pane_group_id) {
@@ -177,40 +184,39 @@ impl Db {
fn get_pane_group_children(
&self,
- pane_group_id: PaneGroupId,
+ _pane_group_id: PaneGroupId,
) -> impl Iterator<Item = PaneGroupChildRow> {
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!();
}
- 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
// Generate new pane group IDs as we go through
// insert them
// 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!();
}
- pub fn get_dock_pane(&self, workspace: WorkspaceId) -> Option<SerializedDockPane> {
+ pub fn get_dock_pane(&self, _workspace: WorkspaceId) -> Option<SerializedDockPane> {
unimplemented!()
}
- pub fn save_dock_pane(&self, dock_pane: SerializedDockPane) {}
+ pub fn save_dock_pane(&self, _dock_pane: SerializedDockPane) {}
}
#[cfg(test)]
mod tests {
- use settings::DockAnchor;
use crate::Db;
- use super::SerializedDockPane;
+ use super::{DockAnchor, SerializedDockPane};
#[test]
fn test_basic_dock_pane() {
@@ -226,6 +232,6 @@ mod tests {
shown: true,
});
- let new_workspace = db.workspace_for_roots(&["/tmp"]);
+ let _new_workspace = db.workspace_for_roots(&["/tmp"]);
}
}
@@ -781,8 +781,14 @@ mod tests {
.await;
let project = Project::test(app_state.fs.clone(), ["/test".as_ref()], cx).await;
- let (_, workspace) =
- cx.add_window(|cx| Workspace::new(project.clone(), |_, _| unimplemented!(), cx));
+ let (_, workspace) = cx.add_window(|cx| {
+ Workspace::new(
+ Default::default(),
+ project.clone(),
+ |_, _| unimplemented!(),
+ cx,
+ )
+ });
// Create some diagnostics
project.update(cx, |project, cx| {
@@ -63,8 +63,14 @@ impl<'a> EditorLspTestContext<'a> {
.insert_tree("/root", json!({ "dir": { file_name: "" }}))
.await;
- let (window_id, workspace) =
- cx.add_window(|cx| Workspace::new(project.clone(), |_, _| unimplemented!(), cx));
+ let (window_id, workspace) = cx.add_window(|cx| {
+ Workspace::new(
+ Default::default(),
+ project.clone(),
+ |_, _| unimplemented!(),
+ cx,
+ )
+ });
project
.update(cx, |project, cx| {
project.find_or_create_local_worktree("/root", true, cx)
@@ -316,8 +316,9 @@ mod tests {
.await;
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
- let (window_id, workspace) =
- cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx));
+ let (window_id, workspace) = cx.add_window(|cx| {
+ Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
+ });
cx.dispatch_action(window_id, Toggle);
let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
@@ -371,8 +372,9 @@ mod tests {
.await;
let project = Project::test(app_state.fs.clone(), ["/dir".as_ref()], cx).await;
- let (_, workspace) =
- cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx));
+ let (_, workspace) = cx.add_window(|cx| {
+ Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
+ });
let (_, finder) =
cx.add_window(|cx| FileFinder::new(workspace.read(cx).project().clone(), cx));
@@ -446,8 +448,9 @@ mod tests {
cx,
)
.await;
- let (_, workspace) =
- cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx));
+ let (_, workspace) = cx.add_window(|cx| {
+ Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
+ });
let (_, finder) =
cx.add_window(|cx| FileFinder::new(workspace.read(cx).project().clone(), cx));
finder
@@ -471,8 +474,9 @@ mod tests {
cx,
)
.await;
- let (_, workspace) =
- cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx));
+ let (_, workspace) = cx.add_window(|cx| {
+ Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
+ });
let (_, finder) =
cx.add_window(|cx| FileFinder::new(workspace.read(cx).project().clone(), cx));
@@ -524,8 +528,9 @@ mod tests {
cx,
)
.await;
- let (_, workspace) =
- cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx));
+ let (_, workspace) = cx.add_window(|cx| {
+ Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
+ });
let (_, finder) =
cx.add_window(|cx| FileFinder::new(workspace.read(cx).project().clone(), cx));
@@ -563,8 +568,9 @@ mod tests {
.await;
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
- let (_, workspace) =
- cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx));
+ let (_, workspace) = cx.add_window(|cx| {
+ Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
+ });
let (_, finder) =
cx.add_window(|cx| FileFinder::new(workspace.read(cx).project().clone(), cx));
finder
@@ -1393,8 +1393,14 @@ mod tests {
.await;
let project = Project::test(fs.clone(), ["/root1".as_ref(), "/root2".as_ref()], cx).await;
- let (_, workspace) =
- cx.add_window(|cx| Workspace::new(project.clone(), |_, _| unimplemented!(), cx));
+ let (_, workspace) = cx.add_window(|cx| {
+ Workspace::new(
+ Default::default(),
+ project.clone(),
+ |_, _| unimplemented!(),
+ cx,
+ )
+ });
let panel = workspace.update(cx, |_, cx| ProjectPanel::new(project, cx));
assert_eq!(
visible_entries_as_strings(&panel, 0..50, cx),
@@ -1486,8 +1492,14 @@ mod tests {
.await;
let project = Project::test(fs.clone(), ["/root1".as_ref(), "/root2".as_ref()], cx).await;
- let (_, workspace) =
- cx.add_window(|cx| Workspace::new(project.clone(), |_, _| unimplemented!(), cx));
+ let (_, workspace) = cx.add_window(|cx| {
+ Workspace::new(
+ Default::default(),
+ project.clone(),
+ |_, _| unimplemented!(),
+ cx,
+ )
+ });
let panel = workspace.update(cx, |_, cx| ProjectPanel::new(project, cx));
select_path(&panel, "root1", cx);
@@ -28,9 +28,14 @@ impl<'a> TerminalTestContext<'a> {
let params = self.cx.update(AppState::test);
let project = Project::test(params.fs.clone(), [], self.cx).await;
- let (_, workspace) = self
- .cx
- .add_window(|cx| Workspace::new(project.clone(), |_, _| unimplemented!(), cx));
+ let (_, workspace) = self.cx.add_window(|cx| {
+ Workspace::new(
+ Default::default(),
+ project.clone(),
+ |_, _| unimplemented!(),
+ cx,
+ )
+ });
(project, workspace)
}
@@ -41,8 +41,14 @@ impl<'a> VimTestContext<'a> {
.insert_tree("/root", json!({ "dir": { "test.txt": "" } }))
.await;
- let (window_id, workspace) =
- cx.add_window(|cx| Workspace::new(project.clone(), |_, _| unimplemented!(), cx));
+ let (window_id, workspace) = cx.add_window(|cx| {
+ Workspace::new(
+ Default::default(),
+ project.clone(),
+ |_, _| unimplemented!(),
+ cx,
+ )
+ });
// Setup search toolbars
workspace.update(cx, |workspace, cx| {
@@ -568,8 +568,9 @@ mod tests {
cx.update(|cx| init(cx));
let project = Project::test(fs, [], cx).await;
- let (window_id, workspace) =
- cx.add_window(|cx| Workspace::new(project, default_item_factory, cx));
+ let (window_id, workspace) = cx.add_window(|cx| {
+ Workspace::new(Default::default(), project, default_item_factory, cx)
+ });
workspace.update(cx, |workspace, cx| {
let left_panel = cx.add_view(|_| TestItem::new());
@@ -1645,8 +1645,9 @@ mod tests {
let fs = FakeFs::new(cx.background());
let project = Project::test(fs, None, cx).await;
- let (_, workspace) =
- cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx));
+ let (_, workspace) = cx.add_window(|cx| {
+ Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
+ });
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
// 1. Add with a destination index
@@ -1734,8 +1735,9 @@ mod tests {
let fs = FakeFs::new(cx.background());
let project = Project::test(fs, None, cx).await;
- let (_, workspace) =
- cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx));
+ let (_, workspace) = cx.add_window(|cx| {
+ Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
+ });
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
// 1. Add with a destination index
@@ -1811,8 +1813,9 @@ mod tests {
let fs = FakeFs::new(cx.background());
let project = Project::test(fs, None, cx).await;
- let (_, workspace) =
- cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx));
+ let (_, workspace) = cx.add_window(|cx| {
+ Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
+ });
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
// singleton view
@@ -1073,7 +1073,7 @@ pub enum Event {
pub struct Workspace {
weak_self: WeakViewHandle<Self>,
- db_id: WorkspaceId,
+ _db_id: WorkspaceId,
client: Arc<Client>,
user_store: ModelHandle<client::UserStore>,
remote_entity_subscription: Option<client::Subscription>,
@@ -1217,7 +1217,7 @@ impl Workspace {
let mut this = Workspace {
modal: None,
weak_self: weak_handle,
- db_id: serialized_workspace.workspace_id,
+ _db_id: serialized_workspace.workspace_id,
center: PaneGroup::new(center_pane.clone()),
dock,
// When removing an item, the last element remaining in this array
@@ -1250,16 +1250,14 @@ impl Workspace {
this
}
- fn new_local<T, F>(
- abs_paths: &[PathBuf],
- app_state: &Arc<AppState>,
+ fn new_local(
+ abs_paths: Vec<PathBuf>,
+ app_state: Arc<AppState>,
cx: &mut MutableAppContext,
- callback: F,
- ) -> Task<T>
- where
- T: 'static,
- F: 'static + FnOnce(&mut Workspace, &mut ViewContext<Workspace>) -> T,
- {
+ ) -> Task<(
+ ViewHandle<Workspace>,
+ Vec<Option<Result<Box<dyn ItemHandle>, Arc<anyhow::Error>>>>,
+ )> {
let project_handle = Project::local(
app_state.client.clone(),
app_state.user_store.clone(),
@@ -1273,21 +1271,25 @@ impl Workspace {
// Get project paths for all of the abs_paths
let mut worktree_roots: HashSet<Arc<Path>> = Default::default();
let mut project_paths = Vec::new();
- for path in abs_paths {
+ for path in abs_paths.iter() {
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
.log_err()
{
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
let serialized_workspace = cx.read(|cx| {
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
@@ -1303,18 +1305,36 @@ impl Workspace {
});
// Call open path for each of the project paths
- // (this will bring them to the front if they were in kthe serialized workspace)
- let tasks = workspace.update(&mut cx, |workspace, cx| {
- let tasks = Vec::new();
- for path in project_paths {
- tasks.push(workspace.open_path(path, true, cx));
- }
- tasks
- });
- futures::future::join_all(tasks.into_iter()).await;
+ // (this will bring them to the front if they were in the serialized workspace)
+ debug_assert!(abs_paths.len() == project_paths.len());
+ let tasks = abs_paths
+ .iter()
+ .cloned()
+ .zip(project_paths.into_iter())
+ .map(|(abs_path, project_path)| {
+ let workspace = workspace.clone();
+ 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
+ }
+ }
+ })
+ });
+
+ let opened_items = futures::future::join_all(tasks.into_iter()).await;
- // Finally call callback on the workspace
- workspace.update(&mut cx, |workspace, cx| callback(workspace, cx))
+ (workspace, opened_items)
})
}
@@ -1371,12 +1391,16 @@ impl Workspace {
) -> Task<T>
where
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() {
Task::Ready(Some(callback(self, cx)))
} 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 {
project_paths.push(
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
.log_err(),
@@ -3017,8 +3041,15 @@ pub fn open_paths(
let app_state = app_state.clone();
let abs_paths = abs_paths.to_vec();
cx.spawn(|mut cx| async move {
- let workspace = if let Some(existing) = existing {
- existing
+ if let Some(existing) = existing {
+ (
+ existing.clone(),
+ existing
+ .update(&mut cx, |workspace, cx| {
+ workspace.open_paths(abs_paths, true, cx)
+ })
+ .await,
+ )
} else {
let contains_directory =
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);
cx.update(|cx| {
- Workspace::new_local(&abs_paths[..], &app_state, cx, move |workspace, cx| {
- if contains_directory {
- workspace.toggle_sidebar(SidebarSide::Left, cx);
- }
- cx.handle()
+ let task = Workspace::new_local(abs_paths, app_state.clone(), cx);
+
+ cx.spawn(|mut cx| async move {
+ let (workspace, items) = task.await;
+
+ workspace.update(&mut cx, |workspace, cx| {
+ if contains_directory {
+ workspace.toggle_sidebar(SidebarSide::Left, cx);
+ }
+ });
+
+ (workspace, items)
})
})
.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<()> {
- 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)]
@@ -3076,8 +3111,14 @@ mod tests {
let fs = FakeFs::new(cx.background());
let project = Project::test(fs, [], cx).await;
- let (_, workspace) =
- cx.add_window(|cx| Workspace::new(project.clone(), default_item_factory, cx));
+ let (_, workspace) = cx.add_window(|cx| {
+ Workspace::new(
+ Default::default(),
+ project.clone(),
+ default_item_factory,
+ cx,
+ )
+ });
// Adding an item with no ambiguity renders the tab without detail.
let item1 = cx.add_view(&workspace, |_| {
@@ -3141,8 +3182,14 @@ mod tests {
.await;
let project = Project::test(fs, ["root1".as_ref()], cx).await;
- let (window_id, workspace) =
- cx.add_window(|cx| Workspace::new(project.clone(), default_item_factory, cx));
+ let (window_id, workspace) = cx.add_window(|cx| {
+ Workspace::new(
+ Default::default(),
+ project.clone(),
+ default_item_factory,
+ cx,
+ )
+ });
let worktree_id = project.read_with(cx, |project, cx| {
project.worktrees(cx).next().unwrap().read(cx).id()
});
@@ -3238,8 +3285,14 @@ mod tests {
fs.insert_tree("/root", json!({ "one": "" })).await;
let project = Project::test(fs, ["root".as_ref()], cx).await;
- let (window_id, workspace) =
- cx.add_window(|cx| Workspace::new(project.clone(), default_item_factory, cx));
+ let (window_id, workspace) = cx.add_window(|cx| {
+ Workspace::new(
+ Default::default(),
+ project.clone(),
+ default_item_factory,
+ cx,
+ )
+ });
// When there are no dirty items, there's nothing to do.
let item1 = cx.add_view(&workspace, |_| TestItem::new());
@@ -3279,8 +3332,8 @@ mod tests {
let fs = FakeFs::new(cx.background());
let project = Project::test(fs, None, cx).await;
- let (window_id, workspace) =
- cx.add_window(|cx| Workspace::new(project, default_item_factory, cx));
+ let (window_id, workspace) = cx
+ .add_window(|cx| Workspace::new(Default::default(), project, default_item_factory, cx));
let item1 = cx.add_view(&workspace, |_| {
let mut item = TestItem::new();
@@ -3375,8 +3428,8 @@ mod tests {
let fs = FakeFs::new(cx.background());
let project = Project::test(fs, [], cx).await;
- let (window_id, workspace) =
- cx.add_window(|cx| Workspace::new(project, default_item_factory, cx));
+ let (window_id, workspace) = cx
+ .add_window(|cx| Workspace::new(Default::default(), project, default_item_factory, cx));
// Create several workspace items with single project entries, and two
// workspace items with multiple project entries.
@@ -3477,8 +3530,8 @@ mod tests {
let fs = FakeFs::new(cx.background());
let project = Project::test(fs, [], cx).await;
- let (window_id, workspace) =
- cx.add_window(|cx| Workspace::new(project, default_item_factory, cx));
+ let (window_id, workspace) = cx
+ .add_window(|cx| Workspace::new(Default::default(), project, default_item_factory, cx));
let item = cx.add_view(&workspace, |_| {
let mut item = TestItem::new();
@@ -3595,7 +3648,8 @@ mod tests {
let fs = FakeFs::new(cx.background());
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 mut item = TestItem::new();
@@ -23,7 +23,7 @@ use isahc::{config::Configurable, Request};
use language::LanguageRegistry;
use log::LevelFilter;
use parking_lot::Mutex;
-use project::{Fs, HomeDir, ProjectStore};
+use project::{Db, Fs, HomeDir, ProjectStore};
use serde_json::json;
use settings::{
self, settings_file::SettingsFile, KeymapFileContent, Settings, SettingsFileContent,
@@ -148,7 +148,9 @@ fn main() {
let project_store = cx.add_model(|_| ProjectStore::new());
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());
let app_state = Arc::new(AppState {
@@ -162,7 +164,12 @@ fn main() {
initialize_workspace,
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);
journal::init(app_state.clone(), cx);
theme_selector::init(app_state.clone(), cx);
@@ -463,10 +463,11 @@ fn open_config_file(
workspace
.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)
})
})
+ .await
.await;
Ok::<_, anyhow::Error>(())
})
@@ -480,51 +481,55 @@ fn open_log_file(
) {
const MAX_LINES: usize = 1000;
- workspace.with_local_workspace(app_state.clone(), cx, |_, cx| {
- cx.spawn_weak(|workspace, mut cx| async move {
- let (old_log, new_log) = futures::join!(
- app_state.fs.load(&paths::OLD_LOG),
- app_state.fs.load(&paths::LOG)
- );
+ workspace
+ .with_local_workspace(&app_state.clone(), cx, move |_, cx| {
+ cx.spawn_weak(|workspace, mut cx| async move {
+ let (old_log, new_log) = futures::join!(
+ app_state.fs.load(&paths::OLD_LOG),
+ app_state.fs.load(&paths::LOG)
+ );
- if let Some(workspace) = workspace.upgrade(&cx) {
- let mut lines = VecDeque::with_capacity(MAX_LINES);
- for line in old_log
- .iter()
- .flat_map(|log| log.lines())
- .chain(new_log.iter().flat_map(|log| log.lines()))
- {
- if lines.len() == MAX_LINES {
- lines.pop_front();
+ if let Some(workspace) = workspace.upgrade(&cx) {
+ let mut lines = VecDeque::with_capacity(MAX_LINES);
+ for line in old_log
+ .iter()
+ .flat_map(|log| log.lines())
+ .chain(new_log.iter().flat_map(|log| log.lines()))
+ {
+ if lines.len() == MAX_LINES {
+ lines.pop_front();
+ }
+ lines.push_back(line);
}
- lines.push_back(line);
- }
- let log = lines
- .into_iter()
- .flat_map(|line| [line, "\n"])
- .collect::<String>();
-
- workspace.update(&mut cx, |workspace, cx| {
- let project = workspace.project().clone();
- let buffer = project
- .update(cx, |project, cx| project.create_buffer("", None, cx))
- .expect("creating buffers on a local workspace always succeeds");
- buffer.update(cx, |buffer, cx| buffer.edit([(0..0, log)], None, cx));
-
- let buffer = cx.add_model(|cx| {
- MultiBuffer::singleton(buffer, cx).with_title("Log".into())
+ let log = lines
+ .into_iter()
+ .flat_map(|line| [line, "\n"])
+ .collect::<String>();
+
+ workspace.update(&mut cx, |workspace, cx| {
+ let project = workspace.project().clone();
+ let buffer = project
+ .update(cx, |project, cx| project.create_buffer("", None, cx))
+ .expect("creating buffers on a local workspace always succeeds");
+ buffer.update(cx, |buffer, cx| buffer.edit([(0..0, log)], None, cx));
+
+ let buffer = cx.add_model(|cx| {
+ 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)),
- ),
- cx,
- );
- });
- }
+ }
+ })
+ .detach();
})
.detach();
- });
}
fn open_telemetry_log_file(
@@ -532,7 +537,7 @@ fn open_telemetry_log_file(
app_state: Arc<AppState>,
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 {
let workspace = workspace.upgrade(&cx)?;
let path = app_state.client.telemetry_log_file_path()?;
@@ -580,31 +585,36 @@ fn open_telemetry_log_file(
Some(())
})
.detach();
- });
+ }).detach();
}
fn open_bundled_config_file(
workspace: &mut Workspace,
app_state: Arc<AppState>,
asset_path: &'static str,
- title: &str,
+ title: &'static str,
cx: &mut ViewContext<Workspace>,
) {
- workspace.with_local_workspace(cx, app_state, |workspace, cx| {
- let project = workspace.project().clone();
- let buffer = project.update(cx, |project, cx| {
- let text = Assets::get(asset_path).unwrap().data;
- let text = str::from_utf8(text.as_ref()).unwrap();
- project
- .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(
- Box::new(cx.add_view(|cx| Editor::for_multibuffer(buffer, Some(project.clone()), cx))),
- cx,
- );
- });
+ workspace
+ .with_local_workspace(&app_state.clone(), cx, |workspace, cx| {
+ let project = workspace.project().clone();
+ let buffer = project.update(cx, |project, cx| {
+ let text = Assets::get(asset_path).unwrap().data;
+ let text = str::from_utf8(text.as_ref()).unwrap();
+ project
+ .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(
+ Box::new(
+ cx.add_view(|cx| Editor::for_multibuffer(buffer, Some(project.clone()), cx)),
+ ),
+ cx,
+ );
+ })
+ .detach();
}
fn schema_file_match(path: &Path) -> &Path {
@@ -808,8 +818,9 @@ mod tests {
.await;
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
- let (_, workspace) =
- cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx));
+ let (_, workspace) = cx.add_window(|cx| {
+ Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
+ });
let entries = cx.read(|cx| workspace.file_project_paths(cx));
let file1 = entries[0].clone();
@@ -928,8 +939,9 @@ mod tests {
.await;
let project = Project::test(app_state.fs.clone(), ["/dir1".as_ref()], cx).await;
- let (_, workspace) =
- cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx));
+ let (_, workspace) = cx.add_window(|cx| {
+ Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
+ });
// Open a file within an existing worktree.
cx.update(|cx| {
@@ -1088,8 +1100,9 @@ mod tests {
.await;
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
- let (window_id, workspace) =
- cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx));
+ let (window_id, workspace) = cx.add_window(|cx| {
+ Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
+ });
// Open a file within an existing worktree.
cx.update(|cx| {
@@ -1131,8 +1144,9 @@ mod tests {
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
project.update(cx, |project, _| project.languages().add(rust_lang()));
- let (window_id, workspace) =
- cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx));
+ let (window_id, workspace) = cx.add_window(|cx| {
+ Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
+ });
let worktree = cx.read(|cx| workspace.read(cx).worktrees(cx).next().unwrap());
// Create a new untitled buffer
@@ -1221,8 +1235,9 @@ mod tests {
let project = Project::test(app_state.fs.clone(), [], cx).await;
project.update(cx, |project, _| project.languages().add(rust_lang()));
- let (window_id, workspace) =
- cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx));
+ let (window_id, workspace) = cx.add_window(|cx| {
+ Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
+ });
// Create a new untitled buffer
cx.dispatch_action(window_id, NewFile);
@@ -1275,8 +1290,9 @@ mod tests {
.await;
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
- let (window_id, workspace) =
- cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx));
+ let (window_id, workspace) = cx.add_window(|cx| {
+ Workspace::new(Default::default(), project, |_, _| unimplemented!(), cx)
+ });
let entries = cx.read(|cx| workspace.file_project_paths(cx));
let file1 = entries[0].clone();
@@ -1350,8 +1366,14 @@ mod tests {
.await;
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
- let (_, workspace) =
- cx.add_window(|cx| Workspace::new(project.clone(), |_, _| unimplemented!(), cx));
+ let (_, workspace) = cx.add_window(|cx| {
+ Workspace::new(
+ Default::default(),
+ project.clone(),
+ |_, _| unimplemented!(),
+ cx,
+ )
+ });
let entries = cx.read(|cx| workspace.file_project_paths(cx));
let file1 = entries[0].clone();
@@ -1615,8 +1637,14 @@ mod tests {
.await;
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
- let (_, workspace) =
- cx.add_window(|cx| Workspace::new(project.clone(), |_, _| unimplemented!(), cx));
+ let (_, workspace) = cx.add_window(|cx| {
+ Workspace::new(
+ Default::default(),
+ project.clone(),
+ |_, _| unimplemented!(),
+ cx,
+ )
+ });
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
let entries = cx.read(|cx| workspace.file_project_paths(cx));