diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index 9a8a27cec0..f39803f148 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -1,3 +1,4 @@ +use anyhow::Result; use editor::{ context_header_renderer, diagnostic_block_renderer, diagnostic_header_renderer, display_map::{BlockDisposition, BlockProperties}, @@ -5,7 +6,7 @@ use editor::{ }; use gpui::{ action, elements::*, keymap::Binding, AppContext, Entity, ModelHandle, MutableAppContext, - RenderContext, View, ViewContext, ViewHandle, + RenderContext, Task, View, ViewContext, ViewHandle, }; use language::{Bias, Buffer, Point}; use postage::watch; @@ -207,7 +208,7 @@ impl workspace::Item for ProjectDiagnostics { .await?; view.update(&mut cx, |view, cx| view.populate_excerpts(buffer, cx)) } - Result::Ok::<_, anyhow::Error>(()) + Result::<_, anyhow::Error>::Ok(()) } }) .detach(); @@ -229,11 +230,8 @@ impl workspace::ItemView for ProjectDiagnosticsEditor { None } - fn save( - &mut self, - _: &mut ViewContext, - ) -> anyhow::Result>> { - todo!() + fn save(&mut self, cx: &mut ViewContext) -> Result>> { + self.excerpts.update(cx, |excerpts, cx| excerpts.save(cx)) } fn save_as( @@ -241,8 +239,8 @@ impl workspace::ItemView for ProjectDiagnosticsEditor { _: ModelHandle, _: &std::path::Path, _: &mut ViewContext, - ) -> gpui::Task> { - todo!() + ) -> Task> { + unreachable!() } fn is_dirty(&self, cx: &AppContext) -> bool { @@ -259,6 +257,14 @@ impl workspace::ItemView for ProjectDiagnosticsEditor { Event::Saved | Event::Dirtied | Event::FileHandleChanged ) } + + fn can_save(&self, _: &AppContext) -> bool { + true + } + + fn can_save_as(&self, _: &AppContext) -> bool { + false + } } #[cfg(test)] diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index 62a0d53f0a..b662044553 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -187,6 +187,14 @@ impl ItemView for Editor { fn has_conflict(&self, cx: &AppContext) -> bool { self.buffer().read(cx).read(cx).has_conflict() } + + fn can_save(&self, cx: &AppContext) -> bool { + self.project_path(cx).is_some() + } + + fn can_save_as(&self, _: &AppContext) -> bool { + true + } } pub struct CursorPosition { diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index e49f81efa7..6f0aa75032 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -102,7 +102,9 @@ pub trait ItemView: View { fn has_conflict(&self, _: &AppContext) -> bool { false } + fn can_save(&self, cx: &AppContext) -> bool; fn save(&mut self, cx: &mut ViewContext) -> Result>>; + fn can_save_as(&self, cx: &AppContext) -> bool; fn save_as( &mut self, worktree: ModelHandle, @@ -146,6 +148,8 @@ pub trait ItemViewHandle { fn to_any(&self) -> AnyViewHandle; fn is_dirty(&self, cx: &AppContext) -> bool; fn has_conflict(&self, cx: &AppContext) -> bool; + fn can_save(&self, cx: &AppContext) -> bool; + fn can_save_as(&self, cx: &AppContext) -> bool; fn save(&self, cx: &mut MutableAppContext) -> Result>>; fn save_as( &self, @@ -276,6 +280,14 @@ impl ItemViewHandle for ViewHandle { fn to_any(&self) -> AnyViewHandle { self.into() } + + fn can_save(&self, cx: &AppContext) -> bool { + self.read(cx).can_save(cx) + } + + fn can_save_as(&self, cx: &AppContext) -> bool { + self.read(cx).can_save_as(cx) + } } impl Clone for Box { @@ -685,7 +697,35 @@ impl Workspace { pub fn save_active_item(&mut self, _: &Save, cx: &mut ViewContext) { if let Some(item) = self.active_item(cx) { let handle = cx.handle(); - if item.project_path(cx.as_ref()).is_none() { + if item.can_save(cx) { + if item.has_conflict(cx.as_ref()) { + const CONFLICT_MESSAGE: &'static str = "This file has changed on disk since you started editing it. Do you want to overwrite it?"; + + cx.prompt( + PromptLevel::Warning, + CONFLICT_MESSAGE, + &["Overwrite", "Cancel"], + move |answer, cx| { + if answer == 0 { + cx.spawn(|mut cx| async move { + if let Err(error) = cx.update(|cx| item.save(cx)).unwrap().await + { + error!("failed to save item: {:?}, ", error); + } + }) + .detach(); + } + }, + ); + } else { + cx.spawn(|_, mut cx| async move { + if let Err(error) = cx.update(|cx| item.save(cx)).unwrap().await { + error!("failed to save item: {:?}, ", error); + } + }) + .detach(); + } + } else if item.can_save_as(cx) { let worktree = self.worktrees(cx).first(); let start_abs_path = worktree .and_then(|w| w.read(cx).as_local()) @@ -717,32 +757,6 @@ impl Workspace { .detach() } }); - return; - } else if item.has_conflict(cx.as_ref()) { - const CONFLICT_MESSAGE: &'static str = "This file has changed on disk since you started editing it. Do you want to overwrite it?"; - - cx.prompt( - PromptLevel::Warning, - CONFLICT_MESSAGE, - &["Overwrite", "Cancel"], - move |answer, cx| { - if answer == 0 { - cx.spawn(|mut cx| async move { - if let Err(error) = cx.update(|cx| item.save(cx)).unwrap().await { - error!("failed to save item: {:?}, ", error); - } - }) - .detach(); - } - }, - ); - } else { - cx.spawn(|_, mut cx| async move { - if let Err(error) = cx.update(|cx| item.save(cx)).unwrap().await { - error!("failed to save item: {:?}, ", error); - } - }) - .detach(); } } }