Option to auto-close deleted files with no unsaved edits (#31920)

Closes #27982

Release Notes:

- Added `close_on_file_delete` setting (off by default) to allow closing
open files after they have been deleted on disk

---------

Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
This commit is contained in:
Ben Brandt 2025-06-03 13:18:29 +02:00 committed by GitHub
parent 3077abf9cf
commit b74477d12e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 393 additions and 5 deletions

View file

@ -856,10 +856,36 @@ impl<T: Item> ItemHandle for Entity<T> {
ItemEvent::UpdateTab => {
workspace.update_item_dirty_state(item, window, cx);
pane.update(cx, |_, cx| {
cx.emit(pane::Event::ChangeItemTitle);
cx.notify();
});
if item.has_deleted_file(cx)
&& !item.is_dirty(cx)
&& item.workspace_settings(cx).close_on_file_delete
{
let item_id = item.item_id();
let close_item_task = pane.update(cx, |pane, cx| {
pane.close_item_by_id(
item_id,
crate::SaveIntent::Close,
window,
cx,
)
});
cx.spawn_in(window, {
let pane = pane.clone();
async move |_workspace, cx| {
close_item_task.await?;
pane.update(cx, |pane, _cx| {
pane.nav_history_mut().remove_item(item_id);
})
}
})
.detach_and_log_err(cx);
} else {
pane.update(cx, |_, cx| {
cx.emit(pane::Event::ChangeItemTitle);
cx.notify();
});
}
}
ItemEvent::Edit => {
@ -1303,6 +1329,7 @@ pub mod test {
pub is_dirty: bool,
pub is_singleton: bool,
pub has_conflict: bool,
pub has_deleted_file: bool,
pub project_items: Vec<Entity<TestProjectItem>>,
pub nav_history: Option<ItemNavHistory>,
pub tab_descriptions: Option<Vec<&'static str>>,
@ -1382,6 +1409,7 @@ pub mod test {
reload_count: 0,
is_dirty: false,
has_conflict: false,
has_deleted_file: false,
project_items: Vec::new(),
is_singleton: true,
nav_history: None,
@ -1409,6 +1437,10 @@ pub mod test {
self
}
pub fn set_has_deleted_file(&mut self, deleted: bool) {
self.has_deleted_file = deleted;
}
pub fn with_dirty(mut self, dirty: bool) -> Self {
self.is_dirty = dirty;
self
@ -1546,6 +1578,7 @@ pub mod test {
is_dirty: self.is_dirty,
is_singleton: self.is_singleton,
has_conflict: self.has_conflict,
has_deleted_file: self.has_deleted_file,
project_items: self.project_items.clone(),
nav_history: None,
tab_descriptions: None,
@ -1564,6 +1597,10 @@ pub mod test {
self.has_conflict
}
fn has_deleted_file(&self, _: &App) -> bool {
self.has_deleted_file
}
fn can_save(&self, cx: &App) -> bool {
!self.project_items.is_empty()
&& self