Add close clean items command

Joseph Lyons created

Change summary

assets/keymaps/default.json  |  1 
crates/workspace/src/pane.rs | 55 ++++++++++++++++++++++++-------------
2 files changed, 37 insertions(+), 19 deletions(-)

Detailed changes

assets/keymaps/default.json 🔗

@@ -21,6 +21,7 @@
             "alt-cmd-right": "pane::ActivateNextItem",
             "cmd-w": "pane::CloseActiveItem",
             "alt-cmd-t": "pane::CloseInactiveItems",
+            "cmd-k u": "pane::CloseCleanItems",
             "cmd-k cmd-w": "pane::CloseAllItems",
             "cmd-shift-w": "workspace::CloseWindow",
             "cmd-s": "workspace::Save",

crates/workspace/src/pane.rs 🔗

@@ -44,6 +44,7 @@ actions!(
         ActivateLastItem,
         CloseActiveItem,
         CloseInactiveItems,
+        CloseCleanItems,
         CloseAllItems,
         ReopenClosedItem,
         SplitLeft,
@@ -123,6 +124,7 @@ pub fn init(cx: &mut MutableAppContext) {
     });
     cx.add_async_action(Pane::close_active_item);
     cx.add_async_action(Pane::close_inactive_items);
+    cx.add_async_action(Pane::close_clean_items);
     cx.add_async_action(Pane::close_all_items);
     cx.add_async_action(|workspace: &mut Workspace, action: &CloseItem, cx| {
         let pane = action.pane.upgrade(cx)?;
@@ -263,6 +265,7 @@ pub enum ReorderBehavior {
 enum ItemType {
     Active,
     Inactive,
+    Clean,
     All,
 }
 
@@ -723,6 +726,14 @@ impl Pane {
         Self::close_main(workspace, ItemType::All, cx)
     }
 
+    pub fn close_clean_items(
+        workspace: &mut Workspace,
+        _: &CloseCleanItems,
+        cx: &mut ViewContext<Workspace>,
+    ) -> Option<Task<Result<()>>> {
+        Self::close_main(workspace, ItemType::Clean, cx)
+    }
+
     fn close_main(
         workspace: &mut Workspace,
         close_item_type: ItemType,
@@ -731,26 +742,32 @@ impl Pane {
         let pane_handle = workspace.active_pane().clone();
         let pane = pane_handle.read(cx);
         if pane.items.is_empty() {
-            None
-        } else {
-            let active_item_id = pane.items[pane.active_item_index].id();
-            let task =
-                Self::close_items(
-                    workspace,
-                    pane_handle,
-                    cx,
-                    move |item_id| match close_item_type {
-                        ItemType::Active => item_id == active_item_id,
-                        ItemType::Inactive => item_id != active_item_id,
-                        ItemType::All => true,
-                    },
-                );
-
-            Some(cx.foreground().spawn(async move {
-                task.await?;
-                Ok(())
-            }))
+            return None;
         }
+
+        let active_item_id = pane.items[pane.active_item_index].id();
+        let clean_buffers: Vec<_> = pane
+            .items()
+            .filter(|item| !item.is_dirty(cx))
+            .map(|item| item.id())
+            .collect();
+        let task =
+            Self::close_items(
+                workspace,
+                pane_handle,
+                cx,
+                move |item_id| match close_item_type {
+                    ItemType::Active => item_id == active_item_id,
+                    ItemType::Inactive => item_id != active_item_id,
+                    ItemType::Clean => clean_buffers.contains(&item_id),
+                    ItemType::All => true,
+                },
+            );
+
+        Some(cx.foreground().spawn(async move {
+            task.await?;
+            Ok(())
+        }))
     }
 
     pub fn close_item(