Detailed changes
@@ -443,7 +443,7 @@ impl<T: 'static> PromptEditor<T> {
self.mention_set
.update(cx, |mention_set, _cx| mention_set.remove_invalid(&snapshot));
- if let Some(workspace) = window.root::<Workspace>().flatten() {
+ if let Some(workspace) = Workspace::for_window(window, cx) {
workspace.update(cx, |workspace, cx| {
let is_via_ssh = workspace.project().read(cx).is_via_remote_server();
@@ -35,7 +35,7 @@ pub fn initiate_sign_out(copilot: Entity<Copilot>, window: &mut Window, cx: &mut
cx.update(|window, cx| copilot_toast(Some("Signed out of Copilot"), window, cx))
}
Err(err) => cx.update(|window, cx| {
- if let Some(workspace) = window.root::<Workspace>().flatten() {
+ if let Some(workspace) = Workspace::for_window(window, cx) {
workspace.update(cx, |workspace, cx| {
workspace.show_error(&err, cx);
})
@@ -82,7 +82,7 @@ fn open_copilot_code_verification_window(copilot: &Entity<Copilot>, window: &Win
fn copilot_toast(message: Option<&'static str>, window: &Window, cx: &mut App) {
const NOTIFICATION_ID: NotificationId = NotificationId::unique::<CopilotStatusToast>();
- let Some(workspace) = window.root::<Workspace>().flatten() else {
+ let Some(workspace) = Workspace::for_window(window, cx) else {
return;
};
@@ -904,7 +904,7 @@ impl Render for BufferDiagnosticsEditor {
.style(ButtonStyle::Transparent)
.tooltip(Tooltip::text("Open File"))
.on_click(cx.listener(|buffer_diagnostics, _, window, cx| {
- if let Some(workspace) = window.root::<Workspace>().flatten() {
+ if let Some(workspace) = Workspace::for_window(window, cx) {
workspace.update(cx, |workspace, cx| {
workspace
.open_path(
@@ -119,7 +119,7 @@ impl Render for EditPredictionButton {
IconButton::new("copilot-error", icon)
.icon_size(IconSize::Small)
.on_click(cx.listener(move |_, _, window, cx| {
- if let Some(workspace) = window.root::<Workspace>().flatten() {
+ if let Some(workspace) = Workspace::for_window(window, cx) {
workspace.update(cx, |workspace, cx| {
let copilot = copilot.clone();
workspace.show_toast(
@@ -719,7 +719,7 @@ pub fn diagnostics_markdown_style(window: &Window, cx: &App) -> MarkdownStyle {
pub fn open_markdown_url(link: SharedString, window: &mut Window, cx: &mut App) {
if let Ok(uri) = Url::parse(&link)
&& uri.scheme() == "file"
- && let Some(workspace) = window.root::<Workspace>().flatten()
+ && let Some(workspace) = Workspace::for_window(window, cx)
{
workspace.update(cx, |workspace, cx| {
let task = workspace.open_abs_path(
@@ -22,7 +22,7 @@ use language::{
use lsp::{notification, request};
use project::Project;
use smol::stream::StreamExt;
-use workspace::{AppState, Workspace, WorkspaceHandle};
+use workspace::{AppState, MultiWorkspace, Workspace, WorkspaceHandle};
use super::editor_test_context::{AssertionContextManager, EditorTestContext};
@@ -95,7 +95,8 @@ impl EditorLspTestContext {
)
.await;
- let window = cx.add_window(|window, cx| Workspace::test_new(project.clone(), window, cx));
+ let window =
+ cx.add_window(|window, cx| MultiWorkspace::test_new(project.clone(), window, cx));
let workspace = window.root(cx).unwrap();
@@ -106,12 +107,20 @@ impl EditorLspTestContext {
})
.await
.unwrap();
- cx.read(|cx| workspace.read(cx).worktree_scans_complete(cx))
- .await;
- let file = cx.read(|cx| workspace.file_project_paths(cx)[0].clone());
+ cx.read(|cx| {
+ workspace
+ .read(cx)
+ .workspace()
+ .read(cx)
+ .worktree_scans_complete(cx)
+ })
+ .await;
+ let file = cx.read(|cx| workspace.read(cx).workspace().file_project_paths(cx)[0].clone());
let item = workspace
.update_in(&mut cx, |workspace, window, cx| {
- workspace.open_path(file, None, true, window, cx)
+ workspace.workspace().update(cx, |workspace, cx| {
+ workspace.open_path(file, None, true, window, cx)
+ })
})
.await
.expect("Could not open test file");
@@ -121,6 +130,8 @@ impl EditorLspTestContext {
});
editor.update_in(&mut cx, |editor, window, cx| {
let nav_history = workspace
+ .read(cx)
+ .workspace()
.read(cx)
.active_pane()
.read(cx)
@@ -134,6 +145,8 @@ impl EditorLspTestContext {
// Ensure the language server is fully registered with the buffer
cx.executor().run_until_parked();
+ let workspace = cx.read(|cx| workspace.read(cx).workspace().clone());
+
Self {
cx: EditorTestContext {
cx,
@@ -20,7 +20,7 @@ use settings::Settings;
use theme::{ActiveTheme, ThemeSettings};
use ui::{ListItem, ListItemSpacing, prelude::*};
use util::ResultExt;
-use workspace::{DismissDecision, ModalView};
+use workspace::{DismissDecision, ModalView, Workspace};
pub fn init(cx: &mut App) {
cx.observe_new(OutlineView::register).detach();
@@ -41,16 +41,15 @@ pub fn toggle(
window: &mut Window,
cx: &mut App,
) {
- let outline = editor
- .read(cx)
- .buffer()
- .read(cx)
- .snapshot(cx)
- .outline(Some(cx.theme().syntax()));
-
- let workspace = editor.read(cx).workspace();
-
- if let Some((workspace, outline)) = workspace.zip(outline) {
+ if let Some((workspace, outline)) = Workspace::for_window(window, cx).and_then(|workspace| {
+ editor
+ .read(cx)
+ .buffer()
+ .read(cx)
+ .snapshot(cx)
+ .outline(Some(cx.theme().syntax()))
+ .map(|outline| (workspace, outline))
+ }) {
workspace.update(cx, |workspace, cx| {
workspace.toggle_modal(window, cx, |window, cx| {
OutlineView::new(outline, editor, window, cx)
@@ -397,7 +396,7 @@ mod tests {
use project::{FakeFs, Project};
use serde_json::json;
use util::{path, rel_path::rel_path};
- use workspace::{AppState, Workspace};
+ use workspace::{AppState, MultiWorkspace, Workspace};
#[gpui::test]
async fn test_outline_view_row_highlights(cx: &mut TestAppContext) {
@@ -425,7 +424,9 @@ mod tests {
});
let (workspace, cx) =
- cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
+ cx.add_window_view(|window, cx| MultiWorkspace::test_new(project.clone(), window, cx));
+
+ let workspace = cx.read(|cx| workspace.read(cx).workspace().clone());
let worktree_id = workspace.update(cx, |workspace, cx| {
workspace.project().update(cx, |project, cx| {
project.worktrees(cx).next().unwrap().read(cx).id()
@@ -191,7 +191,7 @@ pub(crate) fn show_no_more_matches(window: &mut Window, cx: &mut App) {
struct NotifType();
let notification_id = NotificationId::unique::<NotifType>();
- let Some(workspace) = window.root::<Workspace>().flatten() else {
+ let Some(workspace) = Workspace::for_window(window, cx) else {
return;
};
workspace.update(cx, |workspace, cx| {
@@ -318,7 +318,7 @@ pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
}
});
Vim::action(editor, cx, |vim, _: &VisualCommand, window, cx| {
- let Some(workspace) = vim.workspace(window) else {
+ let Some(workspace) = vim.workspace(window, cx) else {
return;
};
workspace.update(cx, |workspace, cx| {
@@ -327,7 +327,7 @@ pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
});
Vim::action(editor, cx, |vim, _: &ShellCommand, window, cx| {
- let Some(workspace) = vim.workspace(window) else {
+ let Some(workspace) = vim.workspace(window, cx) else {
return;
};
workspace.update(cx, |workspace, cx| {
@@ -346,7 +346,7 @@ pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
});
Vim::action(editor, cx, |vim, _: &ShellCommand, window, cx| {
- let Some(workspace) = vim.workspace(window) else {
+ let Some(workspace) = vim.workspace(window, cx) else {
return;
};
workspace.update(cx, |workspace, cx| {
@@ -398,7 +398,7 @@ pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
if action.filename.is_empty() {
if whole_buffer {
- if let Some(workspace) = vim.workspace(window) {
+ if let Some(workspace) = vim.workspace(window, cx) {
workspace.update(cx, |workspace, cx| {
workspace
.save_active_item(
@@ -472,7 +472,7 @@ pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
return;
}
if action.filename.is_empty() {
- if let Some(workspace) = vim.workspace(window) {
+ if let Some(workspace) = vim.workspace(window, cx) {
workspace.update(cx, |workspace, cx| {
workspace
.save_active_item(
@@ -549,7 +549,7 @@ pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
});
Vim::action(editor, cx, |vim, action: &VimSplit, window, cx| {
- let Some(workspace) = vim.workspace(window) else {
+ let Some(workspace) = vim.workspace(window, cx) else {
return;
};
@@ -647,7 +647,7 @@ pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
Vim::action(editor, cx, |vim, action: &VimEdit, window, cx| {
vim.update_editor(cx, |vim, editor, cx| {
- let Some(workspace) = vim.workspace(window) else {
+ let Some(workspace) = vim.workspace(window, cx) else {
return;
};
let Some(project) = editor.project().cloned() else {
@@ -814,7 +814,7 @@ pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
}
};
- let Some(workspace) = vim.workspace(window) else {
+ let Some(workspace) = vim.workspace(window, cx) else {
return;
};
let task = workspace.update(cx, |workspace, cx| {
@@ -855,7 +855,7 @@ pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
});
Vim::action(editor, cx, |vim, _: &CountCommand, window, cx| {
- let Some(workspace) = vim.workspace(window) else {
+ let Some(workspace) = vim.workspace(window, cx) else {
return;
};
let count = Vim::take_count(cx).unwrap_or(1);
@@ -888,7 +888,7 @@ pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
anyhow::Ok(())
});
if let Some(e @ Err(_)) = result {
- let Some(workspace) = vim.workspace(window) else {
+ let Some(workspace) = vim.workspace(window, cx) else {
return;
};
workspace.update(cx, |workspace, cx| {
@@ -932,7 +932,7 @@ pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
let range = match result {
None => return,
Some(e @ Err(_)) => {
- let Some(workspace) = vim.workspace(window) else {
+ let Some(workspace) = vim.workspace(window, cx) else {
return;
};
workspace.update(cx, |workspace, cx| {
@@ -2132,7 +2132,7 @@ impl OnMatchingLines {
let range = match result {
None => return,
Some(e @ Err(_)) => {
- let Some(workspace) = vim.workspace(window) else {
+ let Some(workspace) = vim.workspace(window, cx) else {
return;
};
workspace.update(cx, |workspace, cx| {
@@ -2149,7 +2149,7 @@ impl OnMatchingLines {
let mut regexes = match Regex::new(&self.search) {
Ok(regex) => vec![(regex, !self.invert)],
e @ Err(_) => {
- let Some(workspace) = vim.workspace(window) else {
+ let Some(workspace) = vim.workspace(window, cx) else {
return;
};
workspace.update(cx, |workspace, cx| {
@@ -2347,7 +2347,7 @@ impl Vim {
cx: &mut Context<Vim>,
) {
self.stop_recording(cx);
- let Some(workspace) = self.workspace(window) else {
+ let Some(workspace) = self.workspace(window, cx) else {
return;
};
let command = self.update_editor(cx, |_, editor, cx| {
@@ -2396,7 +2396,7 @@ impl Vim {
cx: &mut Context<Vim>,
) {
self.stop_recording(cx);
- let Some(workspace) = self.workspace(window) else {
+ let Some(workspace) = self.workspace(window, cx) else {
return;
};
let command = self.update_editor(cx, |_, editor, cx| {
@@ -2448,7 +2448,7 @@ impl ShellExec {
}
pub fn run(&self, vim: &mut Vim, window: &mut Window, cx: &mut Context<Vim>) {
- let Some(workspace) = vim.workspace(window) else {
+ let Some(workspace) = vim.workspace(window, cx) else {
return;
};
@@ -81,7 +81,7 @@ impl Vim {
window: &mut Window,
cx: &mut Context<Self>,
) {
- let Some(workspace) = self.workspace(window) else {
+ let Some(workspace) = self.workspace(window, cx) else {
return;
};
workspace.update(cx, |workspace, cx| {
@@ -133,7 +133,7 @@ impl Vim {
window: &mut Window,
cx: &mut Context<Self>,
) {
- let Some(workspace) = self.workspace(window) else {
+ let Some(workspace) = self.workspace(window, cx) else {
return;
};
let task = workspace.update(cx, |workspace, cx| {
@@ -272,7 +272,7 @@ impl Vim {
window: &mut Window,
cx: &mut App,
) {
- let Some(workspace) = self.workspace(window) else {
+ let Some(workspace) = self.workspace(window, cx) else {
return;
};
if name == "`" {
@@ -324,7 +324,7 @@ impl Vim {
return Some(Mark::Local(anchors));
}
VimGlobals::update_global(cx, |globals, cx| {
- let workspace_id = self.workspace(window)?.entity_id();
+ let workspace_id = self.workspace(window, cx)?.entity_id();
globals
.marks
.get_mut(&workspace_id)?
@@ -339,7 +339,7 @@ impl Vim {
window: &mut Window,
cx: &mut App,
) {
- let Some(workspace) = self.workspace(window) else {
+ let Some(workspace) = self.workspace(window, cx) else {
return;
};
if name == "`" || name == "'" {
@@ -112,7 +112,7 @@ impl Replayer {
let this = self.clone();
window.defer(cx, move |window, cx| {
this.next(window, cx);
- let Some(Some(workspace)) = window.root::<Workspace>() else {
+ let Some(workspace) = Workspace::for_window(window, cx) else {
return;
};
let Some(editor) = workspace
@@ -165,7 +165,7 @@ impl Replayer {
text,
utf16_range_to_replace,
} => {
- let Some(Some(workspace)) = window.root::<Workspace>() else {
+ let Some(workspace) = Workspace::for_window(window, cx) else {
return;
};
let Some(editor) = workspace
@@ -555,7 +555,7 @@ impl Vim {
let replacement = action.replacement.clone();
let Some(((pane, workspace), editor)) = self
.pane(window, cx)
- .zip(self.workspace(window))
+ .zip(self.workspace(window, cx))
.zip(self.editor())
else {
return;
@@ -1003,12 +1003,12 @@ impl Vim {
self.editor.upgrade()
}
- pub fn workspace(&self, window: &mut Window) -> Option<Entity<Workspace>> {
- window.root::<Workspace>().flatten()
+ pub fn workspace(&self, window: &Window, cx: &App) -> Option<Entity<Workspace>> {
+ Workspace::for_window(window, cx)
}
- pub fn pane(&self, window: &mut Window, cx: &mut Context<Self>) -> Option<Entity<Pane>> {
- self.workspace(window)
+ pub fn pane(&self, window: &Window, cx: &Context<Self>) -> Option<Entity<Pane>> {
+ self.workspace(window, cx)
.map(|workspace| workspace.read(cx).focused_pane(window, cx))
}
@@ -6731,8 +6731,11 @@ impl Workspace {
)
}
- pub fn for_window(window: &mut Window, _: &mut App) -> Option<Entity<Workspace>> {
- window.root().flatten()
+ pub fn for_window(window: &Window, cx: &App) -> Option<Entity<Workspace>> {
+ window
+ .root::<MultiWorkspace>()
+ .flatten()
+ .map(|multi_workspace| multi_workspace.read(cx).workspace().clone())
}
pub fn zoomed_item(&self) -> Option<&AnyWeakView> {