mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-07 20:39:04 +03:00
Invert dependency between editor
and workspace
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
2cf44d30b7
commit
e88d3bb97e
3
Cargo.lock
generated
3
Cargo.lock
generated
@ -1543,6 +1543,7 @@ dependencies = [
|
||||
"tree-sitter-rust",
|
||||
"unindent",
|
||||
"util",
|
||||
"workspace",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5612,9 +5613,7 @@ name = "workspace"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"buffer",
|
||||
"client",
|
||||
"editor",
|
||||
"gpui",
|
||||
"language",
|
||||
"log",
|
||||
|
@ -19,6 +19,7 @@ project = { path = "../project" }
|
||||
sum_tree = { path = "../sum_tree" }
|
||||
theme = { path = "../theme" }
|
||||
util = { path = "../util" }
|
||||
workspace = { path = "../workspace" }
|
||||
anyhow = "1.0"
|
||||
lazy_static = "1.4"
|
||||
log = "0.4"
|
||||
|
@ -1,66 +1,110 @@
|
||||
use super::{Item, ItemView};
|
||||
use crate::{status_bar::StatusItemView, Settings};
|
||||
use crate::{Editor, EditorSettings, Event};
|
||||
use anyhow::Result;
|
||||
use buffer::{Point, Selection, ToPoint};
|
||||
use editor::{Editor, EditorSettings, Event};
|
||||
use gpui::{
|
||||
elements::*, fonts::TextStyle, AppContext, Entity, ModelHandle, RenderContext, Subscription,
|
||||
Task, View, ViewContext, ViewHandle,
|
||||
elements::*, fonts::TextStyle, AppContext, Entity, ModelContext, ModelHandle,
|
||||
MutableAppContext, RenderContext, Subscription, Task, View, ViewContext, ViewHandle,
|
||||
WeakModelHandle,
|
||||
};
|
||||
use language::{Buffer, Diagnostic, File as _};
|
||||
use postage::watch;
|
||||
use project::{ProjectPath, Worktree};
|
||||
use std::fmt::Write;
|
||||
use std::path::Path;
|
||||
use workspace::{
|
||||
EntryOpener, ItemHandle, ItemView, ItemViewHandle, Settings, StatusItemView, WeakItemHandle,
|
||||
};
|
||||
|
||||
impl Item for Buffer {
|
||||
type View = Editor;
|
||||
pub struct BufferOpener;
|
||||
|
||||
fn build_view(
|
||||
handle: ModelHandle<Self>,
|
||||
#[derive(Clone)]
|
||||
pub struct BufferItemHandle(pub ModelHandle<Buffer>);
|
||||
|
||||
#[derive(Clone)]
|
||||
struct WeakBufferItemHandle(WeakModelHandle<Buffer>);
|
||||
|
||||
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(BufferItemHandle(buffer)) as Box<dyn ItemHandle>)
|
||||
});
|
||||
Some(task)
|
||||
}
|
||||
}
|
||||
|
||||
impl ItemHandle for BufferItemHandle {
|
||||
fn add_view(
|
||||
&self,
|
||||
window_id: usize,
|
||||
settings: watch::Receiver<Settings>,
|
||||
cx: &mut ViewContext<Self::View>,
|
||||
) -> Self::View {
|
||||
Editor::for_buffer(
|
||||
handle,
|
||||
move |cx| {
|
||||
let settings = settings.borrow();
|
||||
let font_cache = cx.font_cache();
|
||||
let font_family_id = settings.buffer_font_family;
|
||||
let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
|
||||
let font_properties = Default::default();
|
||||
let font_id = font_cache
|
||||
.select_font(font_family_id, &font_properties)
|
||||
.unwrap();
|
||||
let font_size = settings.buffer_font_size;
|
||||
cx: &mut MutableAppContext,
|
||||
) -> Box<dyn ItemViewHandle> {
|
||||
Box::new(cx.add_view(window_id, |cx| {
|
||||
Editor::for_buffer(
|
||||
self.0.clone(),
|
||||
move |cx| {
|
||||
let settings = settings.borrow();
|
||||
let font_cache = cx.font_cache();
|
||||
let font_family_id = settings.buffer_font_family;
|
||||
let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
|
||||
let font_properties = Default::default();
|
||||
let font_id = font_cache
|
||||
.select_font(font_family_id, &font_properties)
|
||||
.unwrap();
|
||||
let font_size = settings.buffer_font_size;
|
||||
|
||||
let mut theme = settings.theme.editor.clone();
|
||||
theme.text = TextStyle {
|
||||
color: theme.text.color,
|
||||
font_family_name,
|
||||
font_family_id,
|
||||
font_id,
|
||||
font_size,
|
||||
font_properties,
|
||||
underline: None,
|
||||
};
|
||||
EditorSettings {
|
||||
tab_size: settings.tab_size,
|
||||
style: theme,
|
||||
}
|
||||
},
|
||||
cx,
|
||||
)
|
||||
let mut theme = settings.theme.editor.clone();
|
||||
theme.text = TextStyle {
|
||||
color: theme.text.color,
|
||||
font_family_name,
|
||||
font_family_id,
|
||||
font_id,
|
||||
font_size,
|
||||
font_properties,
|
||||
underline: None,
|
||||
};
|
||||
EditorSettings {
|
||||
tab_size: settings.tab_size,
|
||||
style: theme,
|
||||
}
|
||||
},
|
||||
cx,
|
||||
)
|
||||
}))
|
||||
}
|
||||
|
||||
fn project_path(&self) -> Option<ProjectPath> {
|
||||
self.file().map(|f| ProjectPath {
|
||||
fn boxed_clone(&self) -> Box<dyn ItemHandle> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
|
||||
fn downgrade(&self) -> Box<dyn workspace::WeakItemHandle> {
|
||||
Box::new(WeakBufferItemHandle(self.0.downgrade()))
|
||||
}
|
||||
|
||||
fn project_path(&self, cx: &AppContext) -> Option<ProjectPath> {
|
||||
self.0.read(cx).file().map(|f| ProjectPath {
|
||||
worktree_id: f.worktree_id(),
|
||||
path: f.path().clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl WeakItemHandle for WeakBufferItemHandle {
|
||||
fn upgrade(&self, cx: &AppContext) -> Option<Box<dyn ItemHandle>> {
|
||||
self.0
|
||||
.upgrade(cx)
|
||||
.map(|buffer| Box::new(BufferItemHandle(buffer)) as Box<dyn ItemHandle>)
|
||||
}
|
||||
}
|
||||
|
||||
impl ItemView for Editor {
|
||||
fn should_activate_item_on_event(event: &Event) -> bool {
|
||||
matches!(event, Event::Activate)
|
||||
@ -226,7 +270,7 @@ impl View for CursorPosition {
|
||||
impl StatusItemView for CursorPosition {
|
||||
fn set_active_pane_item(
|
||||
&mut self,
|
||||
active_pane_item: Option<&dyn crate::ItemViewHandle>,
|
||||
active_pane_item: Option<&dyn ItemViewHandle>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
if let Some(editor) = active_pane_item.and_then(|item| item.to_any().downcast::<Editor>()) {
|
||||
@ -312,7 +356,7 @@ impl View for DiagnosticMessage {
|
||||
impl StatusItemView for DiagnosticMessage {
|
||||
fn set_active_pane_item(
|
||||
&mut self,
|
||||
active_pane_item: Option<&dyn crate::ItemViewHandle>,
|
||||
active_pane_item: Option<&dyn ItemViewHandle>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
if let Some(editor) = active_pane_item.and_then(|item| item.to_any().downcast::<Editor>()) {
|
@ -1,5 +1,6 @@
|
||||
pub mod display_map;
|
||||
mod element;
|
||||
pub mod items;
|
||||
pub mod movement;
|
||||
|
||||
#[cfg(test)]
|
||||
@ -17,6 +18,7 @@ use gpui::{
|
||||
text_layout, AppContext, ClipboardItem, Element, ElementBox, Entity, ModelHandle,
|
||||
MutableAppContext, RenderContext, View, ViewContext, WeakViewHandle,
|
||||
};
|
||||
use items::BufferItemHandle;
|
||||
use language::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use smallvec::SmallVec;
|
||||
@ -34,6 +36,7 @@ use std::{
|
||||
use sum_tree::Bias;
|
||||
use theme::{DiagnosticStyle, EditorStyle, SyntaxTheme};
|
||||
use util::post_inc;
|
||||
use workspace::{EntryOpener, Workspace};
|
||||
|
||||
const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
|
||||
const MAX_LINE_LEN: usize = 1024;
|
||||
@ -97,7 +100,8 @@ action!(FoldSelectedRanges);
|
||||
action!(Scroll, Vector2F);
|
||||
action!(Select, SelectPhase);
|
||||
|
||||
pub fn init(cx: &mut MutableAppContext) {
|
||||
pub fn init(cx: &mut MutableAppContext, entry_openers: &mut Vec<Box<dyn EntryOpener>>) {
|
||||
entry_openers.push(Box::new(items::BufferOpener));
|
||||
cx.add_bindings(vec![
|
||||
Binding::new("escape", Cancel, Some("Editor")),
|
||||
Binding::new("backspace", Backspace, Some("Editor")),
|
||||
@ -201,6 +205,7 @@ pub fn init(cx: &mut MutableAppContext) {
|
||||
Binding::new("alt-cmd-f", FoldSelectedRanges, Some("Editor")),
|
||||
]);
|
||||
|
||||
cx.add_action(Editor::open_new);
|
||||
cx.add_action(|this: &mut Editor, action: &Scroll, cx| this.set_scroll_position(action.0, cx));
|
||||
cx.add_action(Editor::select);
|
||||
cx.add_action(Editor::cancel);
|
||||
@ -478,6 +483,15 @@ impl Editor {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn open_new(
|
||||
workspace: &mut Workspace,
|
||||
_: &workspace::OpenNew,
|
||||
cx: &mut ViewContext<Workspace>,
|
||||
) {
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, "", cx));
|
||||
workspace.add_item(BufferItemHandle(buffer), cx);
|
||||
}
|
||||
|
||||
pub fn replica_id(&self, cx: &AppContext) -> ReplicaId {
|
||||
self.buffer.read(cx).replica_id()
|
||||
}
|
||||
|
@ -14,5 +14,6 @@ workspace = { path = "../workspace" }
|
||||
postage = { version = "0.4.1", features = ["futures-traits"] }
|
||||
|
||||
[dev-dependencies]
|
||||
gpui = { path = "../gpui", features = ["test-support"] }
|
||||
serde_json = { version = "1.0.64", features = ["preserve_order"] }
|
||||
workspace = { path = "../workspace", features = ["test-support"] }
|
||||
|
@ -429,7 +429,14 @@ mod tests {
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_matching_paths(mut cx: gpui::TestAppContext) {
|
||||
let params = cx.update(WorkspaceParams::test);
|
||||
let mut entry_openers = Vec::new();
|
||||
cx.update(|cx| {
|
||||
super::init(cx);
|
||||
editor::init(cx, &mut entry_openers);
|
||||
});
|
||||
|
||||
let mut params = cx.update(WorkspaceParams::test);
|
||||
params.entry_openers = Arc::from(entry_openers);
|
||||
params
|
||||
.fs
|
||||
.as_fake()
|
||||
@ -443,10 +450,6 @@ mod tests {
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
cx.update(|cx| {
|
||||
super::init(cx);
|
||||
editor::init(cx);
|
||||
});
|
||||
|
||||
let (window_id, workspace) = cx.add_window(|cx| Workspace::new(¶ms, cx));
|
||||
workspace
|
||||
|
@ -12,9 +12,7 @@ test-support = [
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
buffer = { path = "../buffer" }
|
||||
client = { path = "../client" }
|
||||
editor = { path = "../editor" }
|
||||
gpui = { path = "../gpui" }
|
||||
language = { path = "../language" }
|
||||
project = { path = "../project" }
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -130,11 +130,9 @@ fn open_paths(action: &OpenPaths, cx: &mut MutableAppContext) -> Task<()> {
|
||||
}
|
||||
|
||||
fn open_new(action: &workspace::OpenNew, cx: &mut MutableAppContext) {
|
||||
cx.add_window(window_options(), |cx| {
|
||||
let mut workspace = build_workspace(&action.0, cx);
|
||||
workspace.open_new_file(&action, cx);
|
||||
workspace
|
||||
});
|
||||
let (window_id, workspace) =
|
||||
cx.add_window(window_options(), |cx| build_workspace(&action.0, cx));
|
||||
cx.dispatch_action(window_id, vec![workspace.id()], action);
|
||||
}
|
||||
|
||||
fn build_workspace(params: &WorkspaceParams, cx: &mut ViewContext<Workspace>) -> Workspace {
|
||||
@ -163,9 +161,9 @@ fn build_workspace(params: &WorkspaceParams, cx: &mut ViewContext<Workspace>) ->
|
||||
);
|
||||
|
||||
let diagnostic =
|
||||
cx.add_view(|_| workspace::items::DiagnosticMessage::new(params.settings.clone()));
|
||||
cx.add_view(|_| editor::items::DiagnosticMessage::new(params.settings.clone()));
|
||||
let cursor_position =
|
||||
cx.add_view(|_| workspace::items::CursorPosition::new(params.settings.clone()));
|
||||
cx.add_view(|_| editor::items::CursorPosition::new(params.settings.clone()));
|
||||
workspace.status_bar().update(cx, |status_bar, cx| {
|
||||
status_bar.add_left_item(diagnostic, cx);
|
||||
status_bar.add_right_item(cursor_position, cx);
|
||||
|
@ -36,8 +36,8 @@ fn main() {
|
||||
let mut entry_openers = Vec::new();
|
||||
|
||||
client::init(client.clone(), cx);
|
||||
workspace::init(cx, &mut entry_openers);
|
||||
editor::init(cx);
|
||||
workspace::init(cx);
|
||||
editor::init(cx, &mut entry_openers);
|
||||
file_finder::init(cx);
|
||||
people_panel::init(cx);
|
||||
chat_panel::init(cx);
|
||||
|
Loading…
Reference in New Issue
Block a user