Merge remote-tracking branch 'origin/main' into chat-again

This commit is contained in:
Nathan Sobo 2023-09-11 12:08:01 -06:00
commit fe6f0a253b
164 changed files with 7012 additions and 3586 deletions

View file

@ -171,6 +171,7 @@ pub trait Item: View {
None
}
}
fn as_searchable(&self, _: &ViewHandle<Self>) -> Option<Box<dyn SearchableItemHandle>> {
None
}
@ -473,8 +474,14 @@ impl<T: Item> ItemHandle for ViewHandle<T> {
for item_event in T::to_item_events(event).into_iter() {
match item_event {
ItemEvent::CloseItem => {
pane.update(cx, |pane, cx| pane.close_item_by_id(item.id(), cx))
.detach_and_log_err(cx);
pane.update(cx, |pane, cx| {
pane.close_item_by_id(
item.id(),
crate::SaveBehavior::PromptOnWrite,
cx,
)
})
.detach_and_log_err(cx);
return;
}

View file

@ -25,8 +25,8 @@ use gpui::{
keymap_matcher::KeymapContext,
platform::{CursorStyle, MouseButton, NavigationDirection, PromptLevel},
Action, AnyViewHandle, AnyWeakViewHandle, AppContext, AsyncAppContext, Entity, EventContext,
LayoutContext, ModelHandle, MouseRegion, PaintContext, Quad, Task, View, ViewContext,
ViewHandle, WeakViewHandle, WindowContext,
ModelHandle, MouseRegion, Quad, Task, View, ViewContext, ViewHandle, WeakViewHandle,
WindowContext,
};
use project::{Project, ProjectEntryId, ProjectPath};
use serde::Deserialize;
@ -43,6 +43,19 @@ use std::{
};
use theme::{Theme, ThemeSettings};
#[derive(PartialEq, Clone, Copy, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub enum SaveBehavior {
/// ask before overwriting conflicting files (used by default with %s)
PromptOnConflict,
/// ask before writing any file that wouldn't be auto-saved (used by default with %w)
PromptOnWrite,
/// never prompt, write on conflict (used with vim's :w!)
SilentlyOverwrite,
/// skip all save-related behaviour (used with vim's :cq)
DontSave,
}
#[derive(Clone, Deserialize, PartialEq)]
pub struct ActivateItem(pub usize);
@ -64,13 +77,17 @@ pub struct CloseItemsToTheRightById {
pub pane: WeakViewHandle<Pane>,
}
#[derive(Clone, PartialEq, Debug, Deserialize, Default)]
pub struct CloseActiveItem {
pub save_behavior: Option<SaveBehavior>,
}
actions!(
pane,
[
ActivatePrevItem,
ActivateNextItem,
ActivateLastItem,
CloseActiveItem,
CloseInactiveItems,
CloseCleanItems,
CloseItemsToTheLeft,
@ -86,7 +103,7 @@ actions!(
]
);
impl_actions!(pane, [ActivateItem]);
impl_actions!(pane, [ActivateItem, CloseActiveItem]);
const MAX_NAVIGATION_HISTORY_LEN: usize = 1024;
@ -696,22 +713,29 @@ impl Pane {
pub fn close_active_item(
&mut self,
_: &CloseActiveItem,
action: &CloseActiveItem,
cx: &mut ViewContext<Self>,
) -> Option<Task<Result<()>>> {
if self.items.is_empty() {
return None;
}
let active_item_id = self.items[self.active_item_index].id();
Some(self.close_item_by_id(active_item_id, cx))
Some(self.close_item_by_id(
active_item_id,
action.save_behavior.unwrap_or(SaveBehavior::PromptOnWrite),
cx,
))
}
pub fn close_item_by_id(
&mut self,
item_id_to_close: usize,
save_behavior: SaveBehavior,
cx: &mut ViewContext<Self>,
) -> Task<Result<()>> {
self.close_items(cx, move |view_id| view_id == item_id_to_close)
self.close_items(cx, save_behavior, move |view_id| {
view_id == item_id_to_close
})
}
pub fn close_inactive_items(
@ -724,7 +748,11 @@ impl Pane {
}
let active_item_id = self.items[self.active_item_index].id();
Some(self.close_items(cx, move |item_id| item_id != active_item_id))
Some(
self.close_items(cx, SaveBehavior::PromptOnWrite, move |item_id| {
item_id != active_item_id
}),
)
}
pub fn close_clean_items(
@ -737,7 +765,11 @@ impl Pane {
.filter(|item| !item.is_dirty(cx))
.map(|item| item.id())
.collect();
Some(self.close_items(cx, move |item_id| item_ids.contains(&item_id)))
Some(
self.close_items(cx, SaveBehavior::PromptOnWrite, move |item_id| {
item_ids.contains(&item_id)
}),
)
}
pub fn close_items_to_the_left(
@ -762,7 +794,9 @@ impl Pane {
.take_while(|item| item.id() != item_id)
.map(|item| item.id())
.collect();
self.close_items(cx, move |item_id| item_ids.contains(&item_id))
self.close_items(cx, SaveBehavior::PromptOnWrite, move |item_id| {
item_ids.contains(&item_id)
})
}
pub fn close_items_to_the_right(
@ -788,7 +822,9 @@ impl Pane {
.take_while(|item| item.id() != item_id)
.map(|item| item.id())
.collect();
self.close_items(cx, move |item_id| item_ids.contains(&item_id))
self.close_items(cx, SaveBehavior::PromptOnWrite, move |item_id| {
item_ids.contains(&item_id)
})
}
pub fn close_all_items(
@ -800,12 +836,13 @@ impl Pane {
return None;
}
Some(self.close_items(cx, move |_| true))
Some(self.close_items(cx, SaveBehavior::PromptOnWrite, |_| true))
}
pub fn close_items(
&mut self,
cx: &mut ViewContext<Pane>,
save_behavior: SaveBehavior,
should_close: impl 'static + Fn(usize) -> bool,
) -> Task<Result<()>> {
// Find the items to close.
@ -858,8 +895,15 @@ impl Pane {
.any(|id| saved_project_items_ids.insert(*id));
if should_save
&& !Self::save_item(project.clone(), &pane, item_ix, &*item, true, &mut cx)
.await?
&& !Self::save_item(
project.clone(),
&pane,
item_ix,
&*item,
save_behavior,
&mut cx,
)
.await?
{
break;
}
@ -954,13 +998,17 @@ impl Pane {
pane: &WeakViewHandle<Pane>,
item_ix: usize,
item: &dyn ItemHandle,
should_prompt_for_save: bool,
save_behavior: SaveBehavior,
cx: &mut AsyncAppContext,
) -> Result<bool> {
const CONFLICT_MESSAGE: &str =
"This file has changed on disk since you started editing it. Do you want to overwrite it?";
const DIRTY_MESSAGE: &str = "This file contains unsaved edits. Do you want to save it?";
if save_behavior == SaveBehavior::DontSave {
return Ok(true);
}
let (has_conflict, is_dirty, can_save, is_singleton) = cx.read(|cx| {
(
item.has_conflict(cx),
@ -971,18 +1019,22 @@ impl Pane {
});
if has_conflict && can_save {
let mut answer = pane.update(cx, |pane, cx| {
pane.activate_item(item_ix, true, true, cx);
cx.prompt(
PromptLevel::Warning,
CONFLICT_MESSAGE,
&["Overwrite", "Discard", "Cancel"],
)
})?;
match answer.next().await {
Some(0) => pane.update(cx, |_, cx| item.save(project, cx))?.await?,
Some(1) => pane.update(cx, |_, cx| item.reload(project, cx))?.await?,
_ => return Ok(false),
if save_behavior == SaveBehavior::SilentlyOverwrite {
pane.update(cx, |_, cx| item.save(project, cx))?.await?;
} else {
let mut answer = pane.update(cx, |pane, cx| {
pane.activate_item(item_ix, true, true, cx);
cx.prompt(
PromptLevel::Warning,
CONFLICT_MESSAGE,
&["Overwrite", "Discard", "Cancel"],
)
})?;
match answer.next().await {
Some(0) => pane.update(cx, |_, cx| item.save(project, cx))?.await?,
Some(1) => pane.update(cx, |_, cx| item.reload(project, cx))?.await?,
_ => return Ok(false),
}
}
} else if is_dirty && (can_save || is_singleton) {
let will_autosave = cx.read(|cx| {
@ -991,7 +1043,7 @@ impl Pane {
AutosaveSetting::OnFocusChange | AutosaveSetting::OnWindowChange
) && Self::can_autosave_item(&*item, cx)
});
let should_save = if should_prompt_for_save && !will_autosave {
let should_save = if save_behavior == SaveBehavior::PromptOnWrite && !will_autosave {
let mut answer = pane.update(cx, |pane, cx| {
pane.activate_item(item_ix, true, true, cx);
cx.prompt(
@ -1113,7 +1165,12 @@ impl Pane {
AnchorCorner::TopLeft,
if is_active_item {
vec![
ContextMenuItem::action("Close Active Item", CloseActiveItem),
ContextMenuItem::action(
"Close Active Item",
CloseActiveItem {
save_behavior: None,
},
),
ContextMenuItem::action("Close Inactive Items", CloseInactiveItems),
ContextMenuItem::action("Close Clean Items", CloseCleanItems),
ContextMenuItem::action("Close Items To The Left", CloseItemsToTheLeft),
@ -1128,8 +1185,12 @@ impl Pane {
move |cx| {
if let Some(pane) = pane.upgrade(cx) {
pane.update(cx, |pane, cx| {
pane.close_item_by_id(target_item_id, cx)
.detach_and_log_err(cx);
pane.close_item_by_id(
target_item_id,
SaveBehavior::PromptOnWrite,
cx,
)
.detach_and_log_err(cx);
})
}
}
@ -1278,7 +1339,12 @@ impl Pane {
.on_click(MouseButton::Middle, {
let item_id = item.id();
move |_, pane, cx| {
pane.close_item_by_id(item_id, cx).detach_and_log_err(cx);
pane.close_item_by_id(
item_id,
SaveBehavior::PromptOnWrite,
cx,
)
.detach_and_log_err(cx);
}
})
.on_down(
@ -1440,10 +1506,10 @@ impl Pane {
None
};
Canvas::new(move |scene, bounds, _, _, _| {
Canvas::new(move |bounds, _, _, cx| {
if let Some(color) = icon_color {
let square = RectF::new(bounds.origin(), vec2f(diameter, diameter));
scene.push_quad(Quad {
cx.scene().push_quad(Quad {
bounds: square,
background: Some(color),
border: Default::default(),
@ -1486,7 +1552,8 @@ impl Pane {
cx.window_context().defer(move |cx| {
if let Some(pane) = pane.upgrade(cx) {
pane.update(cx, |pane, cx| {
pane.close_item_by_id(item_id, cx).detach_and_log_err(cx);
pane.close_item_by_id(item_id, SaveBehavior::PromptOnWrite, cx)
.detach_and_log_err(cx);
});
}
});
@ -1999,7 +2066,7 @@ impl<V: 'static> Element<V> for PaneBackdrop<V> {
&mut self,
constraint: gpui::SizeConstraint,
view: &mut V,
cx: &mut LayoutContext<V>,
cx: &mut ViewContext<V>,
) -> (Vector2F, Self::LayoutState) {
let size = self.child.layout(constraint, view, cx);
(size, ())
@ -2007,25 +2074,24 @@ impl<V: 'static> Element<V> for PaneBackdrop<V> {
fn paint(
&mut self,
scene: &mut gpui::SceneBuilder,
bounds: RectF,
visible_bounds: RectF,
_: &mut Self::LayoutState,
view: &mut V,
cx: &mut PaintContext<V>,
cx: &mut ViewContext<V>,
) -> Self::PaintState {
let background = theme::current(cx).editor.background;
let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();
scene.push_quad(gpui::Quad {
cx.scene().push_quad(gpui::Quad {
bounds: RectF::new(bounds.origin(), bounds.size()),
background: Some(background),
..Default::default()
});
let child_view_id = self.child_view;
scene.push_mouse_region(
cx.scene().push_mouse_region(
MouseRegion::new::<Self>(child_view_id, 0, visible_bounds).on_down(
gpui::platform::MouseButton::Left,
move |_, _: &mut V, cx| {
@ -2035,10 +2101,9 @@ impl<V: 'static> Element<V> for PaneBackdrop<V> {
),
);
scene.paint_layer(Some(bounds), |scene| {
self.child
.paint(scene, bounds.origin(), visible_bounds, view, cx)
})
cx.scene().push_layer(Some(bounds));
self.child.paint(bounds.origin(), visible_bounds, view, cx);
cx.scene().pop_layer();
}
fn rect_for_text_range(
@ -2089,7 +2154,14 @@ mod tests {
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
pane.update(cx, |pane, cx| {
assert!(pane.close_active_item(&CloseActiveItem, cx).is_none())
assert!(pane
.close_active_item(
&CloseActiveItem {
save_behavior: None
},
cx
)
.is_none())
});
}
@ -2339,31 +2411,59 @@ mod tests {
add_labeled_item(&pane, "1", false, cx);
assert_item_labels(&pane, ["A", "B", "1*", "C", "D"], cx);
pane.update(cx, |pane, cx| pane.close_active_item(&CloseActiveItem, cx))
.unwrap()
.await
.unwrap();
pane.update(cx, |pane, cx| {
pane.close_active_item(
&CloseActiveItem {
save_behavior: None,
},
cx,
)
})
.unwrap()
.await
.unwrap();
assert_item_labels(&pane, ["A", "B*", "C", "D"], cx);
pane.update(cx, |pane, cx| pane.activate_item(3, false, false, cx));
assert_item_labels(&pane, ["A", "B", "C", "D*"], cx);
pane.update(cx, |pane, cx| pane.close_active_item(&CloseActiveItem, cx))
.unwrap()
.await
.unwrap();
pane.update(cx, |pane, cx| {
pane.close_active_item(
&CloseActiveItem {
save_behavior: None,
},
cx,
)
})
.unwrap()
.await
.unwrap();
assert_item_labels(&pane, ["A", "B*", "C"], cx);
pane.update(cx, |pane, cx| pane.close_active_item(&CloseActiveItem, cx))
.unwrap()
.await
.unwrap();
pane.update(cx, |pane, cx| {
pane.close_active_item(
&CloseActiveItem {
save_behavior: None,
},
cx,
)
})
.unwrap()
.await
.unwrap();
assert_item_labels(&pane, ["A", "C*"], cx);
pane.update(cx, |pane, cx| pane.close_active_item(&CloseActiveItem, cx))
.unwrap()
.await
.unwrap();
pane.update(cx, |pane, cx| {
pane.close_active_item(
&CloseActiveItem {
save_behavior: None,
},
cx,
)
})
.unwrap()
.await
.unwrap();
assert_item_labels(&pane, ["A*"], cx);
}

View file

@ -50,7 +50,7 @@ where
Stack::new()
.with_child(render_child(state, cx))
.with_children(drag_position.map(|drag_position| {
Canvas::new(move |scene, bounds, _, _, cx| {
Canvas::new(move |bounds, _, _, cx| {
if bounds.contains_point(drag_position) {
let overlay_region = split_margin
.and_then(|split_margin| {
@ -60,14 +60,15 @@ where
.map(|(dir, margin)| dir.along_edge(bounds, margin))
.unwrap_or(bounds);
scene.paint_stacking_context(None, None, |scene| {
scene.push_quad(Quad {
bounds: overlay_region,
background: Some(overlay_color(cx)),
border: Default::default(),
corner_radii: Default::default(),
});
cx.scene().push_stacking_context(None, None);
let background = overlay_color(cx);
cx.scene().push_quad(Quad {
bounds: overlay_region,
background: Some(background),
border: Default::default(),
corner_radii: Default::default(),
});
cx.scene().pop_stacking_context();
}
})
}))

View file

@ -9,7 +9,7 @@ use gpui::{
elements::*,
geometry::{rect::RectF, vector::Vector2F},
platform::{CursorStyle, MouseButton},
AnyViewHandle, Axis, Border, ModelHandle, ViewContext, ViewHandle,
AnyViewHandle, Axis, ModelHandle, ViewContext, ViewHandle,
};
use project::Project;
use serde::Deserialize;
@ -594,8 +594,8 @@ mod element {
json::{self, ToJson},
platform::{CursorStyle, MouseButton},
scene::MouseDrag,
AnyElement, Axis, CursorRegion, Element, EventContext, LayoutContext, MouseRegion,
PaintContext, RectFExt, SceneBuilder, SizeConstraint, Vector2FExt, ViewContext,
AnyElement, Axis, CursorRegion, Element, EventContext, MouseRegion, RectFExt,
SizeConstraint, Vector2FExt, ViewContext,
};
use crate::{
@ -641,7 +641,7 @@ mod element {
remaining_flex: &mut f32,
cross_axis_max: &mut f32,
view: &mut Workspace,
cx: &mut LayoutContext<Workspace>,
cx: &mut ViewContext<Workspace>,
) {
let flexes = self.flexes.borrow();
let cross_axis = self.axis.invert();
@ -789,7 +789,7 @@ mod element {
&mut self,
constraint: SizeConstraint,
view: &mut Workspace,
cx: &mut LayoutContext<Workspace>,
cx: &mut ViewContext<Workspace>,
) -> (Vector2F, Self::LayoutState) {
debug_assert!(self.children.len() == self.flexes.borrow().len());
@ -851,19 +851,18 @@ mod element {
fn paint(
&mut self,
scene: &mut SceneBuilder,
bounds: RectF,
visible_bounds: RectF,
remaining_space: &mut Self::LayoutState,
view: &mut Workspace,
cx: &mut PaintContext<Workspace>,
cx: &mut ViewContext<Workspace>,
) -> Self::PaintState {
let can_resize = settings::get::<WorkspaceSettings>(cx).active_pane_magnification == 1.;
let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();
let overflowing = *remaining_space < 0.;
if overflowing {
scene.push_layer(Some(visible_bounds));
cx.scene().push_layer(Some(visible_bounds));
}
let mut child_origin = bounds.origin();
@ -874,7 +873,7 @@ mod element {
let mut children_iter = self.children.iter_mut().enumerate().peekable();
while let Some((ix, child)) = children_iter.next() {
let child_start = child_origin.clone();
child.paint(scene, child_origin, visible_bounds, view, cx);
child.paint(child_origin, visible_bounds, view, cx);
bounding_boxes.push(Some(RectF::new(child_origin, child.size())));
@ -884,7 +883,7 @@ mod element {
}
if can_resize && children_iter.peek().is_some() {
scene.push_stacking_context(None, None);
cx.scene().push_stacking_context(None, None);
let handle_origin = match self.axis {
Axis::Horizontal => child_origin - vec2f(HANDLE_HITBOX_SIZE / 2., 0.0),
@ -907,7 +906,7 @@ mod element {
Axis::Vertical => CursorStyle::ResizeUpDown,
};
scene.push_cursor_region(CursorRegion {
cx.scene().push_cursor_region(CursorRegion {
bounds: handle_bounds,
style,
});
@ -940,14 +939,14 @@ mod element {
}
}
});
scene.push_mouse_region(mouse_region);
cx.scene().push_mouse_region(mouse_region);
scene.pop_stacking_context();
cx.scene().pop_stacking_context();
}
}
if overflowing {
scene.pop_layer();
cx.scene().pop_layer();
}
}

View file

@ -73,14 +73,14 @@ impl View for SharedScreen {
let frame = self.frame.clone();
MouseEventHandler::new::<Focus, _>(0, cx, |_, cx| {
Canvas::new(move |scene, bounds, _, _, _| {
Canvas::new(move |bounds, _, _, cx| {
if let Some(frame) = frame.clone() {
let size = constrain_size_preserving_aspect_ratio(
bounds.size(),
vec2f(frame.width() as f32, frame.height() as f32),
);
let origin = bounds.origin() + (bounds.size() / 2.) - size / 2.;
scene.push_surface(gpui::platform::mac::Surface {
cx.scene().push_surface(gpui::platform::mac::Surface {
bounds: RectF::new(origin, size),
image_buffer: frame.image(),
});

View file

@ -8,8 +8,8 @@ use gpui::{
vector::{vec2f, Vector2F},
},
json::{json, ToJson},
AnyElement, AnyViewHandle, Entity, LayoutContext, PaintContext, SceneBuilder, SizeConstraint,
Subscription, View, ViewContext, ViewHandle, WindowContext,
AnyElement, AnyViewHandle, Entity, SizeConstraint, Subscription, View, ViewContext, ViewHandle,
WindowContext,
};
pub trait StatusItemView: View {
@ -208,7 +208,7 @@ impl Element<StatusBar> for StatusBarElement {
&mut self,
mut constraint: SizeConstraint,
view: &mut StatusBar,
cx: &mut LayoutContext<StatusBar>,
cx: &mut ViewContext<StatusBar>,
) -> (Vector2F, Self::LayoutState) {
let max_width = constraint.max.x();
constraint.min = vec2f(0., constraint.min.y());
@ -226,23 +226,20 @@ impl Element<StatusBar> for StatusBarElement {
fn paint(
&mut self,
scene: &mut SceneBuilder,
bounds: RectF,
visible_bounds: RectF,
_: &mut Self::LayoutState,
view: &mut StatusBar,
cx: &mut PaintContext<StatusBar>,
cx: &mut ViewContext<StatusBar>,
) -> Self::PaintState {
let origin_y = bounds.upper_right().y();
let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();
let left_origin = vec2f(bounds.lower_left().x(), origin_y);
self.left
.paint(scene, left_origin, visible_bounds, view, cx);
self.left.paint(left_origin, visible_bounds, view, cx);
let right_origin = vec2f(bounds.upper_right().x() - self.right.size().x(), origin_y);
self.right
.paint(scene, right_origin, visible_bounds, view, cx);
self.right.paint(right_origin, visible_bounds, view, cx);
}
fn rect_for_text_range(

View file

@ -1308,13 +1308,15 @@ impl Workspace {
}
Ok(this
.update(&mut cx, |this, cx| this.save_all_internal(true, cx))?
.update(&mut cx, |this, cx| {
this.save_all_internal(SaveBehavior::PromptOnWrite, cx)
})?
.await?)
})
}
fn save_all(&mut self, _: &SaveAll, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
let save_all = self.save_all_internal(false, cx);
let save_all = self.save_all_internal(SaveBehavior::PromptOnConflict, cx);
Some(cx.foreground().spawn(async move {
save_all.await?;
Ok(())
@ -1323,7 +1325,7 @@ impl Workspace {
fn save_all_internal(
&mut self,
should_prompt_to_save: bool,
save_behaviour: SaveBehavior,
cx: &mut ViewContext<Self>,
) -> Task<Result<bool>> {
if self.project.read(cx).is_read_only() {
@ -1358,7 +1360,7 @@ impl Workspace {
&pane,
ix,
&*item,
should_prompt_to_save,
save_behaviour,
&mut cx,
)
.await?
@ -3626,13 +3628,13 @@ fn notify_of_new_dock(workspace: &WeakViewHandle<Workspace>, cx: &mut AsyncAppCo
"Looking for the dock? Try ctrl-`!\nshift-escape now zooms your pane.",
text,
)
.with_custom_runs(vec![26..32, 34..46], |_, bounds, scene, cx| {
.with_custom_runs(vec![26..32, 34..46], |_, bounds, cx| {
let code_span_background_color = settings::get::<ThemeSettings>(cx)
.theme
.editor
.document_highlight_read_background;
scene.push_quad(gpui::Quad {
cx.scene().push_quad(gpui::Quad {
bounds,
background: Some(code_span_background_color),
border: Default::default(),
@ -4358,7 +4360,9 @@ mod tests {
let item1_id = item1.id();
let item3_id = item3.id();
let item4_id = item4.id();
pane.close_items(cx, move |id| [item1_id, item3_id, item4_id].contains(&id))
pane.close_items(cx, SaveBehavior::PromptOnWrite, move |id| {
[item1_id, item3_id, item4_id].contains(&id)
})
});
cx.foreground().run_until_parked();
@ -4493,7 +4497,9 @@ mod tests {
// once for project entry 0, and once for project entry 2. After those two
// prompts, the task should complete.
let close = left_pane.update(cx, |pane, cx| pane.close_items(cx, |_| true));
let close = left_pane.update(cx, |pane, cx| {
pane.close_items(cx, SaveBehavior::PromptOnWrite, move |_| true)
});
cx.foreground().run_until_parked();
left_pane.read_with(cx, |pane, cx| {
assert_eq!(
@ -4609,9 +4615,11 @@ mod tests {
item.is_dirty = true;
});
pane.update(cx, |pane, cx| pane.close_items(cx, move |id| id == item_id))
.await
.unwrap();
pane.update(cx, |pane, cx| {
pane.close_items(cx, SaveBehavior::PromptOnWrite, move |id| id == item_id)
})
.await
.unwrap();
assert!(!window.has_pending_prompt(cx));
item.read_with(cx, |item, _| assert_eq!(item.save_count, 5));
@ -4630,8 +4638,9 @@ mod tests {
item.read_with(cx, |item, _| assert_eq!(item.save_count, 5));
// Ensure autosave is prevented for deleted files also when closing the buffer.
let _close_items =
pane.update(cx, |pane, cx| pane.close_items(cx, move |id| id == item_id));
let _close_items = pane.update(cx, |pane, cx| {
pane.close_items(cx, SaveBehavior::PromptOnWrite, move |id| id == item_id)
});
deterministic.run_until_parked();
assert!(window.has_pending_prompt(cx));
item.read_with(cx, |item, _| assert_eq!(item.save_count, 5));