This commit is contained in:
Max Brunsfeld 2021-04-06 18:25:50 -07:00
parent 685665f3c0
commit d724387158
5 changed files with 50 additions and 41 deletions

1
Cargo.lock generated
View file

@ -2241,6 +2241,7 @@ dependencies = [
"crossbeam-channel 0.5.0", "crossbeam-channel 0.5.0",
"dirs", "dirs",
"easy-parallel", "easy-parallel",
"futures-core",
"gpui", "gpui",
"ignore", "ignore",
"lazy_static", "lazy_static",

View file

@ -20,6 +20,7 @@ dirs = "3.0"
easy-parallel = "3.1.0" easy-parallel = "3.1.0"
gpui = {path = "../gpui"} gpui = {path = "../gpui"}
ignore = {git = "https://github.com/zed-industries/ripgrep", rev = "1d152118f35b3e3590216709b86277062d79b8a0"} ignore = {git = "https://github.com/zed-industries/ripgrep", rev = "1d152118f35b3e3590216709b86277062d79b8a0"}
futures-core = "0.3"
lazy_static = "1.4.0" lazy_static = "1.4.0"
libc = "0.2" libc = "0.2"
log = "0.4" log = "0.4"

View file

@ -3,6 +3,7 @@ mod point;
mod text; mod text;
pub use anchor::*; pub use anchor::*;
use futures_core::future::LocalBoxFuture;
pub use point::*; pub use point::*;
pub use text::*; pub use text::*;
@ -14,7 +15,7 @@ use crate::{
worktree::FileHandle, worktree::FileHandle,
}; };
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use gpui::{AppContext, Entity, ModelContext, Task}; use gpui::{AppContext, Entity, ModelContext};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use rand::prelude::*; use rand::prelude::*;
use std::{ use std::{
@ -243,23 +244,25 @@ impl Buffer {
} }
} }
pub fn save(&mut self, ctx: &mut ModelContext<Self>) -> Option<Task<Result<()>>> { pub fn save(&mut self, ctx: &mut ModelContext<Self>) -> LocalBoxFuture<'static, Result<()>> {
if let Some(file) = &self.file { if let Some(file) = &self.file {
let snapshot = self.snapshot(); let snapshot = self.snapshot();
let version = self.version.clone();
let result = file.save(snapshot, ctx.app()); let save_task = file.save(snapshot, ctx.app());
let task = ctx.spawn(save_task, |me, save_result, ctx| {
// TODO - don't do this until the save has finished if save_result.is_ok() {
self.did_save(ctx); me.did_save(version, ctx);
}
Some(result) save_result
});
Box::pin(task)
} else { } else {
None Box::pin(async { Ok(()) })
} }
} }
fn did_save(&mut self, ctx: &mut ModelContext<Buffer>) { fn did_save(&mut self, version: time::Global, ctx: &mut ModelContext<Buffer>) {
self.persisted_version = self.fragments.summary().max_version; self.persisted_version = version;
ctx.emit(Event::Saved); ctx.emit(Event::Saved);
} }
@ -429,7 +432,7 @@ impl Buffer {
ctx.notify(); ctx.notify();
let changes = self.edits_since(old_version).collect::<Vec<_>>(); let changes = self.edits_since(old_version).collect::<Vec<_>>();
if !changes.is_empty() { if !changes.is_empty() {
ctx.emit(Event::Edited(changes)) self.did_edit(changes, ctx);
} }
} }
@ -447,6 +450,10 @@ impl Buffer {
Ok(ops) Ok(ops)
} }
fn did_edit(&self, changes: Vec<Edit>, ctx: &mut ModelContext<Self>) {
ctx.emit(Event::Edited(changes))
}
pub fn simulate_typing<T: Rng>(&mut self, rng: &mut T) { pub fn simulate_typing<T: Rng>(&mut self, rng: &mut T) {
let end = rng.gen_range(0..self.len() + 1); let end = rng.gen_range(0..self.len() + 1);
let start = rng.gen_range(0..end + 1); let start = rng.gen_range(0..end + 1);

View file

@ -5,12 +5,13 @@ use super::{
use crate::{ use crate::{
settings::Settings, settings::Settings,
watch, watch,
workspace::{self, ItemEventEffect}, workspace::{self, WorkspaceEvent},
}; };
use anyhow::Result; use anyhow::Result;
use futures_core::future::LocalBoxFuture;
use gpui::{ use gpui::{
fonts::Properties as FontProperties, keymap::Binding, text_layout, App, AppContext, Element, fonts::Properties as FontProperties, keymap::Binding, text_layout, App, AppContext, Element,
ElementBox, Entity, FontCache, ModelHandle, Task, View, ViewContext, WeakViewHandle, ElementBox, Entity, FontCache, ModelHandle, View, ViewContext, WeakViewHandle,
}; };
use gpui::{geometry::vector::Vector2F, TextLayoutCache}; use gpui::{geometry::vector::Vector2F, TextLayoutCache};
use parking_lot::Mutex; use parking_lot::Mutex;
@ -1152,11 +1153,11 @@ impl workspace::Item for Buffer {
} }
impl workspace::ItemView for BufferView { impl workspace::ItemView for BufferView {
fn event_effect(event: &Self::Event) -> ItemEventEffect { fn to_workspace_event(event: &Self::Event) -> Option<WorkspaceEvent> {
match event { match event {
Event::Activate => ItemEventEffect::Activate, Event::Activate => Some(WorkspaceEvent::Activate),
Event::Edited => ItemEventEffect::ChangeTab, Event::Saved => Some(WorkspaceEvent::TabStateChanged),
_ => ItemEventEffect::None, _ => None,
} }
} }
@ -1184,7 +1185,7 @@ impl workspace::ItemView for BufferView {
Some(clone) Some(clone)
} }
fn save(&self, ctx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> { fn save(&self, ctx: &mut ViewContext<Self>) -> LocalBoxFuture<'static, Result<()>> {
self.buffer.update(ctx, |buffer, ctx| buffer.save(ctx)) self.buffer.update(ctx, |buffer, ctx| buffer.save(ctx))
} }

View file

@ -1,8 +1,9 @@
use super::{pane, Pane, PaneGroup, SplitDirection, Workspace}; use super::{pane, Pane, PaneGroup, SplitDirection, Workspace};
use crate::{settings::Settings, watch}; use crate::{settings::Settings, watch};
use futures_core::future::LocalBoxFuture;
use gpui::{ use gpui::{
color::rgbu, elements::*, keymap::Binding, AnyViewHandle, App, AppContext, Entity, ModelHandle, color::rgbu, elements::*, keymap::Binding, AnyViewHandle, App, AppContext, Entity, ModelHandle,
MutableAppContext, Task, View, ViewContext, ViewHandle, MutableAppContext, View, ViewContext, ViewHandle,
}; };
use log::{error, info}; use log::{error, info};
use std::{collections::HashSet, path::PathBuf}; use std::{collections::HashSet, path::PathBuf};
@ -12,14 +13,13 @@ pub fn init(app: &mut App) {
app.add_bindings(vec![Binding::new("cmd-s", "workspace:save", None)]); app.add_bindings(vec![Binding::new("cmd-s", "workspace:save", None)]);
} }
pub enum ItemEventEffect { pub enum WorkspaceEvent {
None, TabStateChanged,
ChangeTab,
Activate, Activate,
} }
pub trait ItemView: View { pub trait ItemView: View {
fn event_effect(event: &Self::Event) -> ItemEventEffect; fn to_workspace_event(event: &Self::Event) -> Option<WorkspaceEvent>;
fn title(&self, app: &AppContext) -> String; fn title(&self, app: &AppContext) -> String;
fn entry_id(&self, app: &AppContext) -> Option<(usize, usize)>; fn entry_id(&self, app: &AppContext) -> Option<(usize, usize)>;
fn clone_on_split(&self, _: &mut ViewContext<Self>) -> Option<Self> fn clone_on_split(&self, _: &mut ViewContext<Self>) -> Option<Self>
@ -31,8 +31,8 @@ pub trait ItemView: View {
fn is_modified(&self, _: &AppContext) -> bool { fn is_modified(&self, _: &AppContext) -> bool {
false false
} }
fn save(&self, _: &mut ViewContext<Self>) -> Option<Task<anyhow::Result<()>>> { fn save(&self, _: &mut ViewContext<Self>) -> LocalBoxFuture<'static, anyhow::Result<()>> {
None Box::pin(async { Ok(()) })
} }
} }
@ -45,7 +45,7 @@ pub trait ItemViewHandle: Send + Sync {
fn id(&self) -> usize; fn id(&self) -> usize;
fn to_any(&self) -> AnyViewHandle; fn to_any(&self) -> AnyViewHandle;
fn is_modified(&self, ctx: &AppContext) -> bool; fn is_modified(&self, ctx: &AppContext) -> bool;
fn save(&self, ctx: &mut MutableAppContext) -> Option<Task<anyhow::Result<()>>>; fn save(&self, ctx: &mut MutableAppContext) -> LocalBoxFuture<'static, anyhow::Result<()>>;
} }
impl<T: ItemView> ItemViewHandle for ViewHandle<T> { impl<T: ItemView> ItemViewHandle for ViewHandle<T> {
@ -71,21 +71,21 @@ impl<T: ItemView> ItemViewHandle for ViewHandle<T> {
fn set_parent_pane(&self, pane: &ViewHandle<Pane>, app: &mut MutableAppContext) { fn set_parent_pane(&self, pane: &ViewHandle<Pane>, app: &mut MutableAppContext) {
pane.update(app, |_, ctx| { pane.update(app, |_, ctx| {
ctx.subscribe_to_view(self, |pane, item, event, ctx| { ctx.subscribe_to_view(self, |pane, item, event, ctx| {
match T::event_effect(event) { match T::to_workspace_event(event) {
ItemEventEffect::Activate => { Some(WorkspaceEvent::Activate) => {
if let Some(ix) = pane.item_index(&item) { if let Some(ix) = pane.item_index(&item) {
pane.activate_item(ix, ctx); pane.activate_item(ix, ctx);
pane.activate(ctx); pane.activate(ctx);
} }
} }
ItemEventEffect::ChangeTab => ctx.notify(), Some(WorkspaceEvent::TabStateChanged) => ctx.notify(),
_ => {} _ => {}
} }
}) })
}) })
} }
fn save(&self, ctx: &mut MutableAppContext) -> Option<Task<anyhow::Result<()>>> { fn save(&self, ctx: &mut MutableAppContext) -> LocalBoxFuture<'static, anyhow::Result<()>> {
self.update(ctx, |item, ctx| item.save(ctx)) self.update(ctx, |item, ctx| item.save(ctx))
} }
@ -240,15 +240,14 @@ impl WorkspaceView {
pub fn save_active_item(&mut self, _: &(), ctx: &mut ViewContext<Self>) { pub fn save_active_item(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
self.active_pane.update(ctx, |pane, ctx| { self.active_pane.update(ctx, |pane, ctx| {
if let Some(item) = pane.active_item() { if let Some(item) = pane.active_item() {
if let Some(task) = item.save(ctx.app_mut()) { let task = item.save(ctx.app_mut());
ctx.spawn(task, |_, result, _| { ctx.spawn(task, |_, result, _| {
if let Err(e) = result { if let Err(e) = result {
// TODO - present this error to the user // TODO - present this error to the user
error!("failed to save item: {:?}, ", e); error!("failed to save item: {:?}, ", e);
} }
}) })
.detach(); .detach()
}
} }
}); });
} }