Allow saving of all buffers contained in project diagnostics editor

Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
Antonio Scandurra 2021-12-17 16:48:16 +01:00
parent f0fe346e15
commit 88d663a253
3 changed files with 64 additions and 36 deletions

View file

@ -1,3 +1,4 @@
use anyhow::Result;
use editor::{ use editor::{
context_header_renderer, diagnostic_block_renderer, diagnostic_header_renderer, context_header_renderer, diagnostic_block_renderer, diagnostic_header_renderer,
display_map::{BlockDisposition, BlockProperties}, display_map::{BlockDisposition, BlockProperties},
@ -5,7 +6,7 @@ use editor::{
}; };
use gpui::{ use gpui::{
action, elements::*, keymap::Binding, AppContext, Entity, ModelHandle, MutableAppContext, action, elements::*, keymap::Binding, AppContext, Entity, ModelHandle, MutableAppContext,
RenderContext, View, ViewContext, ViewHandle, RenderContext, Task, View, ViewContext, ViewHandle,
}; };
use language::{Bias, Buffer, Point}; use language::{Bias, Buffer, Point};
use postage::watch; use postage::watch;
@ -207,7 +208,7 @@ impl workspace::Item for ProjectDiagnostics {
.await?; .await?;
view.update(&mut cx, |view, cx| view.populate_excerpts(buffer, cx)) view.update(&mut cx, |view, cx| view.populate_excerpts(buffer, cx))
} }
Result::Ok::<_, anyhow::Error>(()) Result::<_, anyhow::Error>::Ok(())
} }
}) })
.detach(); .detach();
@ -229,11 +230,8 @@ impl workspace::ItemView for ProjectDiagnosticsEditor {
None None
} }
fn save( fn save(&mut self, cx: &mut ViewContext<Self>) -> Result<Task<Result<()>>> {
&mut self, self.excerpts.update(cx, |excerpts, cx| excerpts.save(cx))
_: &mut ViewContext<Self>,
) -> anyhow::Result<gpui::Task<anyhow::Result<()>>> {
todo!()
} }
fn save_as( fn save_as(
@ -241,8 +239,8 @@ impl workspace::ItemView for ProjectDiagnosticsEditor {
_: ModelHandle<project::Worktree>, _: ModelHandle<project::Worktree>,
_: &std::path::Path, _: &std::path::Path,
_: &mut ViewContext<Self>, _: &mut ViewContext<Self>,
) -> gpui::Task<anyhow::Result<()>> { ) -> Task<Result<()>> {
todo!() unreachable!()
} }
fn is_dirty(&self, cx: &AppContext) -> bool { fn is_dirty(&self, cx: &AppContext) -> bool {
@ -259,6 +257,14 @@ impl workspace::ItemView for ProjectDiagnosticsEditor {
Event::Saved | Event::Dirtied | Event::FileHandleChanged Event::Saved | Event::Dirtied | Event::FileHandleChanged
) )
} }
fn can_save(&self, _: &AppContext) -> bool {
true
}
fn can_save_as(&self, _: &AppContext) -> bool {
false
}
} }
#[cfg(test)] #[cfg(test)]

View file

@ -187,6 +187,14 @@ impl ItemView for Editor {
fn has_conflict(&self, cx: &AppContext) -> bool { fn has_conflict(&self, cx: &AppContext) -> bool {
self.buffer().read(cx).read(cx).has_conflict() 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 { pub struct CursorPosition {

View file

@ -102,7 +102,9 @@ pub trait ItemView: View {
fn has_conflict(&self, _: &AppContext) -> bool { fn has_conflict(&self, _: &AppContext) -> bool {
false false
} }
fn can_save(&self, cx: &AppContext) -> bool;
fn save(&mut self, cx: &mut ViewContext<Self>) -> Result<Task<Result<()>>>; fn save(&mut self, cx: &mut ViewContext<Self>) -> Result<Task<Result<()>>>;
fn can_save_as(&self, cx: &AppContext) -> bool;
fn save_as( fn save_as(
&mut self, &mut self,
worktree: ModelHandle<Worktree>, worktree: ModelHandle<Worktree>,
@ -146,6 +148,8 @@ pub trait ItemViewHandle {
fn to_any(&self) -> AnyViewHandle; fn to_any(&self) -> AnyViewHandle;
fn is_dirty(&self, cx: &AppContext) -> bool; fn is_dirty(&self, cx: &AppContext) -> bool;
fn has_conflict(&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<Task<Result<()>>>; fn save(&self, cx: &mut MutableAppContext) -> Result<Task<Result<()>>>;
fn save_as( fn save_as(
&self, &self,
@ -276,6 +280,14 @@ impl<T: ItemView> ItemViewHandle for ViewHandle<T> {
fn to_any(&self) -> AnyViewHandle { fn to_any(&self) -> AnyViewHandle {
self.into() 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<dyn ItemViewHandle> { impl Clone for Box<dyn ItemViewHandle> {
@ -685,7 +697,35 @@ impl Workspace {
pub fn save_active_item(&mut self, _: &Save, cx: &mut ViewContext<Self>) { pub fn save_active_item(&mut self, _: &Save, cx: &mut ViewContext<Self>) {
if let Some(item) = self.active_item(cx) { if let Some(item) = self.active_item(cx) {
let handle = cx.handle(); 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 worktree = self.worktrees(cx).first();
let start_abs_path = worktree let start_abs_path = worktree
.and_then(|w| w.read(cx).as_local()) .and_then(|w| w.read(cx).as_local())
@ -717,32 +757,6 @@ impl Workspace {
.detach() .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();
} }
} }
} }