Cargo.lock 🔗
@@ -1532,6 +1532,7 @@ dependencies = [
"log",
"parking_lot",
"postage",
+ "project",
"rand 0.8.3",
"serde",
"smallvec",
Antonio Scandurra created
Cargo.lock | 1
crates/editor/Cargo.toml | 1
crates/workspace/src/lib.rs | 63 ++++++++++++++++++++++++++++++--------
crates/zed/src/lib.rs | 2 +
crates/zed/src/main.rs | 19 ++++++----
crates/zed/src/menus.rs | 1
crates/zed/src/test.rs | 1
7 files changed, 67 insertions(+), 21 deletions(-)
@@ -1532,6 +1532,7 @@ dependencies = [
"log",
"parking_lot",
"postage",
+ "project",
"rand 0.8.3",
"serde",
"smallvec",
@@ -15,6 +15,7 @@ buffer = { path = "../buffer" }
clock = { path = "../clock" }
gpui = { path = "../gpui" }
language = { path = "../language" }
+project = { path = "../project" }
sum_tree = { path = "../sum_tree" }
theme = { path = "../theme" }
util = { path = "../util" }
@@ -5,12 +5,12 @@ pub mod settings;
pub mod sidebar;
mod status_bar;
-use anyhow::Result;
+use anyhow::{anyhow, Result};
use client::{Authenticate, ChannelList, Client, UserStore};
use gpui::{
action, elements::*, json::to_string_pretty, keymap::Binding, platform::CursorStyle,
- AnyViewHandle, AppContext, ClipboardItem, Entity, ModelHandle, MutableAppContext, PromptLevel,
- RenderContext, Task, View, ViewContext, ViewHandle, WeakModelHandle,
+ AnyViewHandle, AppContext, ClipboardItem, Entity, ModelContext, ModelHandle, MutableAppContext,
+ PromptLevel, RenderContext, Task, View, ViewContext, ViewHandle, WeakModelHandle,
};
use language::{Buffer, LanguageRegistry};
use log::error;
@@ -33,7 +33,28 @@ action!(OpenNew, WorkspaceParams);
action!(Save);
action!(DebugElements);
-pub fn init(cx: &mut MutableAppContext) {
+struct BufferOpener;
+
+impl EntryOpener for BufferOpener {
+ fn open(
+ &self,
+ worktree: &mut Worktree,
+ project_path: ProjectPath,
+ cx: &mut ModelContext<Worktree>,
+ ) -> Option<Task<Result<Box<dyn ItemHandle>>>> {
+ let buffer = worktree.open_buffer(project_path.path, cx);
+ let task = cx.spawn(|_, _| async move {
+ buffer
+ .await
+ .map(|buffer| Box::new(buffer) as Box<dyn ItemHandle>)
+ });
+ Some(task)
+ }
+}
+
+pub fn init(cx: &mut MutableAppContext, entry_openers: &mut Vec<Box<dyn EntryOpener>>) {
+ entry_openers.push(Box::new(BufferOpener));
+
cx.add_action(Workspace::save_active_item);
cx.add_action(Workspace::debug_elements);
cx.add_action(Workspace::open_new_file);
@@ -62,6 +83,15 @@ pub fn init(cx: &mut MutableAppContext) {
pane::init(cx);
}
+pub trait EntryOpener {
+ fn open(
+ &self,
+ worktree: &mut Worktree,
+ path: ProjectPath,
+ cx: &mut ModelContext<Worktree>,
+ ) -> Option<Task<Result<Box<dyn ItemHandle>>>>;
+}
+
pub trait Item: Entity + Sized {
type View: ItemView;
@@ -268,6 +298,7 @@ pub struct WorkspaceParams {
pub settings: watch::Receiver<Settings>,
pub user_store: ModelHandle<UserStore>,
pub channel_list: ModelHandle<ChannelList>,
+ pub entry_openers: Arc<[Box<dyn EntryOpener>]>,
}
impl WorkspaceParams {
@@ -299,6 +330,7 @@ impl WorkspaceParams {
languages: Arc::new(languages),
settings: watch::channel_with(settings).1,
user_store,
+ entry_openers: Arc::from([]),
}
}
}
@@ -316,6 +348,7 @@ pub struct Workspace {
active_pane: ViewHandle<Pane>,
status_bar: ViewHandle<StatusBar>,
project: ModelHandle<Project>,
+ entry_openers: Arc<[Box<dyn EntryOpener>]>,
items: Vec<Box<dyn WeakItemHandle>>,
loading_items: HashMap<
ProjectPath,
@@ -388,6 +421,7 @@ impl Workspace {
left_sidebar: Sidebar::new(Side::Left),
right_sidebar: Sidebar::new(Side::Right),
project,
+ entry_openers: params.entry_openers.clone(),
items: Default::default(),
loading_items: Default::default(),
_observe_current_user,
@@ -600,18 +634,21 @@ impl Workspace {
entry.insert(rx);
let project_path = project_path.clone();
+ let entry_openers = self.entry_openers.clone();
cx.as_mut()
.spawn(|mut cx| async move {
- let buffer = worktree
- .update(&mut cx, |worktree, cx| {
- worktree.open_buffer(project_path.path.as_ref(), cx)
+ let item = worktree.update(&mut cx, move |worktree, cx| {
+ for opener in entry_openers.iter() {
+ if let Some(task) = opener.open(worktree, project_path.clone(), cx) {
+ return task;
+ }
+ }
+
+ cx.spawn(|_, _| async move {
+ Err(anyhow!("no opener for path {:?} found", project_path))
})
- .await;
- *tx.borrow_mut() = Some(
- buffer
- .map(|buffer| Box::new(buffer) as Box<dyn ItemHandle>)
- .map_err(Arc::new),
- );
+ });
+ *tx.borrow_mut() = Some(item.await.map_err(Arc::new));
})
.detach();
}
@@ -45,6 +45,7 @@ pub struct AppState {
pub user_store: ModelHandle<client::UserStore>,
pub fs: Arc<dyn fs::Fs>,
pub channel_list: ModelHandle<client::ChannelList>,
+ pub entry_openers: Arc<[Box<dyn workspace::EntryOpener>]>,
}
#[derive(Clone)]
@@ -185,6 +186,7 @@ impl<'a> From<&'a AppState> for WorkspaceParams {
settings: state.settings.clone(),
user_store: state.user_store.clone(),
channel_list: state.channel_list.clone(),
+ entry_openers: state.entry_openers.clone(),
}
}
}
@@ -33,6 +33,16 @@ fn main() {
let client = client::Client::new();
let http = http::client();
let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http.clone(), cx));
+ let mut entry_openers = Vec::new();
+
+ client::init(client.clone(), cx);
+ workspace::init(cx, &mut entry_openers);
+ editor::init(cx);
+ file_finder::init(cx);
+ people_panel::init(cx);
+ chat_panel::init(cx);
+ project_panel::init(cx);
+
let app_state = Arc::new(AppState {
languages: languages.clone(),
settings_tx: Arc::new(Mutex::new(settings_tx)),
@@ -43,16 +53,9 @@ fn main() {
client,
user_store,
fs: Arc::new(RealFs),
+ entry_openers: Arc::from(entry_openers),
});
-
zed::init(&app_state, cx);
- client::init(app_state.client.clone(), cx);
- workspace::init(cx);
- editor::init(cx);
- file_finder::init(cx);
- people_panel::init(cx);
- chat_panel::init(cx);
- project_panel::init(cx);
theme_selector::init(app_state.as_ref().into(), cx);
cx.set_menus(menus::menus(&app_state.clone()));
@@ -11,6 +11,7 @@ pub fn menus(state: &Arc<AppState>) -> Vec<Menu<'static>> {
settings: state.settings.clone(),
user_store: state.user_store.clone(),
channel_list: state.channel_list.clone(),
+ entry_openers: state.entry_openers.clone(),
};
vec![
@@ -30,6 +30,7 @@ pub fn test_app_state(cx: &mut MutableAppContext) -> Arc<AppState> {
client,
user_store,
fs: Arc::new(FakeFs::new()),
+ entry_openers: Arc::from([]),
})
}