diff --git a/Cargo.lock b/Cargo.lock
index 0f19d4455f..9b2ae7f167 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3018,6 +3018,17 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adab1eaa3408fb7f0c777a73e7465fd5656136fc93b670eb6df3c88c2c1344e3"
+[[package]]
+name = "install_cli"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "gpui",
+ "log",
+ "smol",
+ "util",
+]
+
[[package]]
name = "instant"
version = "0.1.12"
@@ -8030,6 +8041,26 @@ version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb"
+[[package]]
+name = "welcome"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "db",
+ "editor",
+ "fuzzy",
+ "gpui",
+ "install_cli",
+ "log",
+ "picker",
+ "project",
+ "settings",
+ "theme",
+ "theme_selector",
+ "util",
+ "workspace",
+]
+
[[package]]
name = "wepoll-ffi"
version = "0.1.2"
@@ -8305,6 +8336,7 @@ dependencies = [
"futures 0.3.25",
"gpui",
"indoc",
+ "install_cli",
"language",
"lazy_static",
"log",
@@ -8397,6 +8429,7 @@ dependencies = [
"command_palette",
"context_menu",
"ctor",
+ "db",
"diagnostics",
"easy-parallel",
"editor",
@@ -8412,6 +8445,7 @@ dependencies = [
"ignore",
"image",
"indexmap",
+ "install_cli",
"isahc",
"journal",
"language",
@@ -8477,6 +8511,7 @@ dependencies = [
"util",
"uuid 1.2.2",
"vim",
+ "welcome",
"workspace",
]
diff --git a/Cargo.toml b/Cargo.toml
index 63882573ab..ab8bcd6de8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -26,6 +26,7 @@ members = [
"crates/go_to_line",
"crates/gpui",
"crates/gpui_macros",
+ "crates/install_cli",
"crates/journal",
"crates/language",
"crates/language_selector",
@@ -59,6 +60,7 @@ members = [
"crates/util",
"crates/vim",
"crates/workspace",
+ "crates/welcome",
"crates/zed",
]
default-members = ["crates/zed"]
diff --git a/assets/icons/logo_96.svg b/assets/icons/logo_96.svg
new file mode 100644
index 0000000000..dc98bb8bc2
--- /dev/null
+++ b/assets/icons/logo_96.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/keymaps/atom.json b/assets/keymaps/atom.json
new file mode 100644
index 0000000000..766c46c133
--- /dev/null
+++ b/assets/keymaps/atom.json
@@ -0,0 +1,68 @@
+[
+ {
+ "bindings": {
+ "cmd-k cmd-p": "workspace::ActivatePreviousPane",
+ "cmd-k cmd-n": "workspace::ActivateNextPane"
+ }
+ },
+ {
+ "context": "Editor",
+ "bindings": {
+ "cmd-b": "editor::GoToDefinition",
+ "cmd-<": "editor::ScrollCursorCenter",
+ "cmd-g": [
+ "editor::SelectNext",
+ {
+ "replace_newest": true
+ }
+ ],
+ "ctrl-shift-down": "editor::AddSelectionBelow",
+ "ctrl-shift-up": "editor::AddSelectionAbove",
+ "cmd-shift-backspace": "editor::DeleteToBeginningOfLine"
+ }
+ },
+ {
+ "context": "Editor && mode == full",
+ "bindings": {
+ "cmd-r": "outline::Toggle"
+ }
+ },
+ {
+ "context": "BufferSearchBar",
+ "bindings": {
+ "cmd-f3": "search::SelectNextMatch",
+ "cmd-shift-f3": "search::SelectPrevMatch"
+ }
+ },
+ {
+ "context": "Workspace",
+ "bindings": {
+ "cmd-\\": "workspace::ToggleLeftSidebar",
+ "cmd-k cmd-b": "workspace::ToggleLeftSidebar",
+ "cmd-t": "file_finder::Toggle",
+ "cmd-shift-r": "project_symbols::Toggle"
+ }
+ },
+ {
+ "context": "Pane",
+ "bindings": {
+ "alt-cmd-/": "search::ToggleRegex",
+ "ctrl-0": "project_panel::ToggleFocus"
+ }
+ },
+ {
+ "context": "ProjectPanel",
+ "bindings": {
+ "ctrl-[": "project_panel::CollapseSelectedEntry",
+ "ctrl-b": "project_panel::CollapseSelectedEntry",
+ "h": "project_panel::CollapseSelectedEntry",
+ "ctrl-]": "project_panel::ExpandSelectedEntry",
+ "ctrl-f": "project_panel::ExpandSelectedEntry",
+ "ctrl-shift-c": "project_panel::CopyPath"
+ }
+ },
+ {
+ "context": "Dock",
+ "bindings": {}
+ }
+]
\ No newline at end of file
diff --git a/assets/keymaps/jetbrains.json b/assets/keymaps/jetbrains.json
new file mode 100644
index 0000000000..2e6e5e77e6
--- /dev/null
+++ b/assets/keymaps/jetbrains.json
@@ -0,0 +1,78 @@
+[
+ {
+ "bindings": {
+ "cmd-shift-[": "pane::ActivatePrevItem",
+ "cmd-shift-]": "pane::ActivateNextItem"
+ }
+ },
+ {
+ "context": "Editor",
+ "bindings": {
+ "ctrl->": "zed::IncreaseBufferFontSize",
+ "ctrl-<": "zed::DecreaseBufferFontSize",
+ "cmd-d": "editor::DuplicateLine",
+ "cmd-pagedown": "editor::MovePageDown",
+ "cmd-pageup": "editor::MovePageUp",
+ "ctrl-alt-shift-b": "editor::SelectToPreviousWordStart",
+ "shift-enter": "editor::NewlineBelow",
+ "cmd--": "editor::Fold",
+ "cmd-=": "editor::UnfoldLines",
+ "alt-shift-g": "editor::SplitSelectionIntoLines",
+ "ctrl-g": [
+ "editor::SelectNext",
+ {
+ "replace_newest": false
+ }
+ ],
+ "cmd-/": [
+ "editor::ToggleComments",
+ {
+ "advance_downwards": true
+ }
+ ],
+ "shift-alt-up": "editor::MoveLineUp",
+ "shift-alt-down": "editor::MoveLineDown",
+ "cmd-[": "pane::GoBack",
+ "cmd-]": "pane::GoForward",
+ "alt-f7": "editor::FindAllReferences",
+ "cmd-alt-f7": "editor::FindAllReferences",
+ "cmd-b": "editor::GoToDefinition",
+ "cmd-alt-b": "editor::GoToDefinition",
+ "cmd-shift-b": "editor::GoToTypeDefinition",
+ "alt-enter": "editor::ToggleCodeActions",
+ "f2": "editor::GoToDiagnostic",
+ "cmd-f2": "editor::GoToPrevDiagnostic",
+ "ctrl-alt-shift-down": "editor::GoToHunk",
+ "ctrl-alt-shift-up": "editor::GoToPrevHunk",
+ "cmd-home": "editor::MoveToBeginning",
+ "cmd-end": "editor::MoveToEnd",
+ "cmd-shift-home": "editor::SelectToBeginning",
+ "cmd-shift-end": "editor::SelectToEnd"
+ }
+ },
+ {
+ "context": "Editor && mode == full",
+ "bindings": {
+ "cmd-f12": "outline::Toggle",
+ "cmd-7": "outline::Toggle",
+ "cmd-shift-o": "file_finder::Toggle",
+ "cmd-l": "go_to_line::Toggle"
+ }
+ },
+ {
+ "context": "Workspace",
+ "bindings": {
+ "cmd-shift-a": "command_palette::Toggle",
+ "cmd-alt-o": "project_symbols::Toggle",
+ "cmd-1": "workspace::ToggleLeftSidebar",
+ "cmd-6": "diagnostics::Deploy",
+ "alt-f12": "dock::FocusDock"
+ }
+ },
+ {
+ "context": "Dock",
+ "bindings": {
+ "alt-f12": "dock::HideDock"
+ }
+ }
+]
\ No newline at end of file
diff --git a/assets/keymaps/sublime_text.json b/assets/keymaps/sublime_text.json
new file mode 100644
index 0000000000..1d3dd887d7
--- /dev/null
+++ b/assets/keymaps/sublime_text.json
@@ -0,0 +1,60 @@
+[
+ {
+ "bindings": {
+ "cmd-shift-[": "pane::ActivatePrevItem",
+ "cmd-shift-]": "pane::ActivateNextItem",
+ "ctrl-pagedown": "pane::ActivatePrevItem",
+ "ctrl-pageup": "pane::ActivateNextItem",
+ "ctrl-shift-tab": "pane::ActivateNextItem",
+ "ctrl-tab": "pane::ActivatePrevItem",
+ "cmd-+": "zed::IncreaseBufferFontSize"
+ }
+ },
+ {
+ "context": "Editor",
+ "bindings": {
+ "ctrl-shift-up": "editor::AddSelectionAbove",
+ "ctrl-shift-down": "editor::AddSelectionBelow",
+ "cmd-shift-space": "editor::SelectAll",
+ "ctrl-shift-m": "editor::SelectLargerSyntaxNode",
+ "cmd-shift-a": "editor::SelectLargerSyntaxNode",
+ "shift-f12": "editor::FindAllReferences",
+ "alt-cmd-down": "editor::GoToDefinition",
+ "alt-shift-cmd-down": "editor::FindAllReferences",
+ "ctrl-.": "editor::GoToHunk",
+ "ctrl-,": "editor::GoToPrevHunk",
+ "ctrl-backspace": "editor::DeleteToPreviousWordStart",
+ "ctrl-delete": "editor::DeleteToNextWordEnd"
+ }
+ },
+ {
+ "context": "Editor && mode == full",
+ "bindings": {
+ "cmd-r": "outline::Toggle"
+ }
+ },
+ {
+ "context": "Pane",
+ "bindings": {
+ "f4": "search::SelectNextMatch",
+ "shift-f4": "search::SelectPrevMatch"
+ }
+ },
+ {
+ "context": "Workspace",
+ "bindings": {
+ "ctrl-`": "dock::FocusDock",
+ "cmd-k cmd-b": "workspace::ToggleLeftSidebar",
+ "cmd-t": "file_finder::Toggle",
+ "shift-cmd-r": "project_symbols::Toggle",
+ // Currently busted: https://github.com/zed-industries/feedback/issues/898
+ "ctrl-0": "project_panel::ToggleFocus"
+ }
+ },
+ {
+ "context": "Dock",
+ "bindings": {
+ "ctrl-`": "dock::HideDock"
+ }
+ }
+]
\ No newline at end of file
diff --git a/assets/settings/default.json b/assets/settings/default.json
index 2a5e05b401..90c47478f3 100644
--- a/assets/settings/default.json
+++ b/assets/settings/default.json
@@ -50,7 +50,7 @@
// "default_dock_anchor": "right"
// 3. Position the dock full screen over the entire workspace"
// "default_dock_anchor": "expanded"
- "default_dock_anchor": "right",
+ "default_dock_anchor": "bottom",
// Whether or not to remove any trailing whitespace from lines of a buffer
// before saving it.
"remove_trailing_whitespace_on_save": true,
diff --git a/crates/collab/src/tests.rs b/crates/collab/src/tests.rs
index e9ffecf246..80df0ed6df 100644
--- a/crates/collab/src/tests.rs
+++ b/crates/collab/src/tests.rs
@@ -197,7 +197,8 @@ impl TestServer {
fs: fs.clone(),
build_window_options: |_, _, _| Default::default(),
initialize_workspace: |_, _, _| unimplemented!(),
- dock_default_item_factory: |_, _| unimplemented!(),
+ dock_default_item_factory: |_, _| None,
+ background_actions: || &[],
});
Project::init(&client);
@@ -434,15 +435,7 @@ impl TestClient {
cx: &mut TestAppContext,
) -> ViewHandle {
let (_, root_view) = cx.add_window(|_| EmptyView);
- cx.add_view(&root_view, |cx| {
- Workspace::new(
- Default::default(),
- 0,
- project.clone(),
- |_, _| unimplemented!(),
- cx,
- )
- })
+ cx.add_view(&root_view, |cx| Workspace::test_new(project.clone(), cx))
}
fn create_new_root_dir(&mut self) -> PathBuf {
diff --git a/crates/collab/src/tests/integration_tests.rs b/crates/collab/src/tests/integration_tests.rs
index 4f027af758..44a2839f27 100644
--- a/crates/collab/src/tests/integration_tests.rs
+++ b/crates/collab/src/tests/integration_tests.rs
@@ -1449,15 +1449,7 @@ async fn test_host_disconnect(
deterministic.run_until_parked();
assert!(worktree_a.read_with(cx_a, |tree, _| tree.as_local().unwrap().is_shared()));
- let (_, workspace_b) = cx_b.add_window(|cx| {
- Workspace::new(
- Default::default(),
- 0,
- project_b.clone(),
- |_, _| unimplemented!(),
- cx,
- )
- });
+ let (_, workspace_b) = cx_b.add_window(|cx| Workspace::test_new(project_b.clone(), cx));
let editor_b = workspace_b
.update(cx_b, |workspace, cx| {
workspace.open_path((worktree_id, "b.txt"), None, true, cx)
@@ -4706,15 +4698,7 @@ 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(
- Default::default(),
- 0,
- project_b.clone(),
- |_, _| unimplemented!(),
- cx,
- )
- });
+ let (_window_b, workspace_b) = cx_b.add_window(|cx| Workspace::test_new(project_b.clone(), cx));
let editor_b = workspace_b
.update(cx_b, |workspace, cx| {
workspace.open_path((worktree_id, "main.rs"), None, true, cx)
@@ -4937,15 +4921,7 @@ async fn test_collaborating_with_renames(
.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(
- Default::default(),
- 0,
- project_b.clone(),
- |_, _| unimplemented!(),
- cx,
- )
- });
+ let (_window_b, workspace_b) = cx_b.add_window(|cx| Workspace::test_new(project_b.clone(), cx));
let editor_b = workspace_b
.update(cx_b, |workspace, cx| {
workspace.open_path((worktree_id, "one.rs"), None, true, cx)
diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs
index c838f6a55f..e8c8951526 100644
--- a/crates/collab_ui/src/collab_titlebar_item.rs
+++ b/crates/collab_ui/src/collab_titlebar_item.rs
@@ -821,7 +821,7 @@ impl CollabTitlebarItem {
avatar_style: AvatarStyle,
background_color: Color,
) -> ElementBox {
- Image::new(avatar)
+ Image::from_data(avatar)
.with_style(avatar_style.image)
.aligned()
.contained()
diff --git a/crates/collab_ui/src/collab_ui.rs b/crates/collab_ui/src/collab_ui.rs
index 6abfec21f7..2dd2b0e6b4 100644
--- a/crates/collab_ui/src/collab_ui.rs
+++ b/crates/collab_ui/src/collab_ui.rs
@@ -86,6 +86,7 @@ fn join_project(action: &JoinProject, app_state: Arc, cx: &mut Mutable
0,
project,
app_state.dock_default_item_factory,
+ app_state.background_actions,
cx,
);
(app_state.initialize_workspace)(&mut workspace, &app_state, cx);
diff --git a/crates/collab_ui/src/contact_finder.rs b/crates/collab_ui/src/contact_finder.rs
index 3b93414e1f..83f094ebad 100644
--- a/crates/collab_ui/src/contact_finder.rs
+++ b/crates/collab_ui/src/contact_finder.rs
@@ -128,7 +128,7 @@ impl PickerDelegate for ContactFinder {
.style_for(mouse_state, selected);
Flex::row()
.with_children(user.avatar.clone().map(|avatar| {
- Image::new(avatar)
+ Image::from_data(avatar)
.with_style(theme.contact_finder.contact_avatar)
.aligned()
.left()
diff --git a/crates/collab_ui/src/contact_list.rs b/crates/collab_ui/src/contact_list.rs
index dd6683292e..38444f6f12 100644
--- a/crates/collab_ui/src/contact_list.rs
+++ b/crates/collab_ui/src/contact_list.rs
@@ -736,7 +736,7 @@ impl ContactList {
) -> ElementBox {
Flex::row()
.with_children(user.avatar.clone().map(|avatar| {
- Image::new(avatar)
+ Image::from_data(avatar)
.with_style(theme.contact_avatar)
.aligned()
.left()
@@ -1090,7 +1090,7 @@ impl ContactList {
};
Stack::new()
.with_child(
- Image::new(avatar)
+ Image::from_data(avatar)
.with_style(theme.contact_avatar)
.aligned()
.left()
@@ -1183,7 +1183,7 @@ impl ContactList {
let mut row = Flex::row()
.with_children(user.avatar.clone().map(|avatar| {
- Image::new(avatar)
+ Image::from_data(avatar)
.with_style(theme.contact_avatar)
.aligned()
.left()
diff --git a/crates/collab_ui/src/incoming_call_notification.rs b/crates/collab_ui/src/incoming_call_notification.rs
index a0f54abe38..6fb0278218 100644
--- a/crates/collab_ui/src/incoming_call_notification.rs
+++ b/crates/collab_ui/src/incoming_call_notification.rs
@@ -108,7 +108,7 @@ impl IncomingCallNotification {
.unwrap_or(&default_project);
Flex::row()
.with_children(self.call.calling_user.avatar.clone().map(|avatar| {
- Image::new(avatar)
+ Image::from_data(avatar)
.with_style(theme.caller_avatar)
.aligned()
.boxed()
diff --git a/crates/collab_ui/src/notifications.rs b/crates/collab_ui/src/notifications.rs
index 06b6cf2a90..21c2d2c218 100644
--- a/crates/collab_ui/src/notifications.rs
+++ b/crates/collab_ui/src/notifications.rs
@@ -24,7 +24,7 @@ pub fn render_user_notification(
.with_child(
Flex::row()
.with_children(user.avatar.clone().map(|avatar| {
- Image::new(avatar)
+ Image::from_data(avatar)
.with_style(theme.header_avatar)
.aligned()
.constrained()
diff --git a/crates/collab_ui/src/project_shared_notification.rs b/crates/collab_ui/src/project_shared_notification.rs
index edf0354eec..b24f3492da 100644
--- a/crates/collab_ui/src/project_shared_notification.rs
+++ b/crates/collab_ui/src/project_shared_notification.rs
@@ -108,7 +108,7 @@ impl ProjectSharedNotification {
let theme = &cx.global::().theme.project_shared_notification;
Flex::row()
.with_children(self.owner.avatar.clone().map(|avatar| {
- Image::new(avatar)
+ Image::from_data(avatar)
.with_style(theme.owner_avatar)
.aligned()
.boxed()
diff --git a/crates/command_palette/src/command_palette.rs b/crates/command_palette/src/command_palette.rs
index 55522966fa..52a0e1cdc0 100644
--- a/crates/command_palette/src/command_palette.rs
+++ b/crates/command_palette/src/command_palette.rs
@@ -352,9 +352,7 @@ mod tests {
});
let project = Project::test(app_state.fs.clone(), [], cx).await;
- let (_, workspace) = cx.add_window(|cx| {
- Workspace::new(Default::default(), 0, project, |_, _| unimplemented!(), cx)
- });
+ let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
let editor = cx.add_view(&workspace, |cx| {
let mut editor = Editor::single_line(None, cx);
editor.set_text("abc", cx);
diff --git a/crates/db/src/db.rs b/crates/db/src/db.rs
index 20f2300d89..ae9325ea2e 100644
--- a/crates/db/src/db.rs
+++ b/crates/db/src/db.rs
@@ -4,6 +4,7 @@ pub mod query;
// Re-export
pub use anyhow;
use anyhow::Context;
+use gpui::MutableAppContext;
pub use indoc::indoc;
pub use lazy_static;
use parking_lot::{Mutex, RwLock};
@@ -17,6 +18,7 @@ use sqlez::domain::Migrator;
use sqlez::thread_safe_connection::ThreadSafeConnection;
use sqlez_macros::sql;
use std::fs::create_dir_all;
+use std::future::Future;
use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::{SystemTime, UNIX_EPOCH};
@@ -39,6 +41,7 @@ const FALLBACK_DB_NAME: &'static str = "FALLBACK_MEMORY_DB";
const DB_FILE_NAME: &'static str = "db.sqlite";
lazy_static::lazy_static! {
+ // !!!!!!! CHANGE BACK TO DEFAULT FALSE BEFORE SHIPPING
static ref ZED_STATELESS: bool = std::env::var("ZED_STATELESS").map_or(false, |v| !v.is_empty());
static ref DB_FILE_OPERATIONS: Mutex<()> = Mutex::new(());
pub static ref BACKUP_DB_PATH: RwLock