diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index 1a7129fa0a40424e80e8927bfa0978bbc4e002e7..32d727962e0331eb5d59b63bbf5aea6f67455d35 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -952,13 +952,6 @@ mod flatpak { pub fn try_restart_to_host() { if let Some(flatpak_dir) = get_flatpak_dir() { let mut args = vec!["/usr/bin/flatpak-spawn".into(), "--host".into()]; - - for (name, value) in env::vars() { - if name.starts_with("ZED_") { - args.push(format!("--env={}={}", name, value).into()); - } - } - args.append(&mut get_xdg_env_args()); args.push("--env=ZED_UPDATE_EXPLANATION=Please use flatpak to update zed".into()); args.push( diff --git a/crates/tab_switcher/src/tab_switcher.rs b/crates/tab_switcher/src/tab_switcher.rs index 0fb13c85d21797e4d57728c88fc8bb014a898f78..f4a7c9d202e54f9239ba5d611a6c92a5b6e3bfc4 100644 --- a/crates/tab_switcher/src/tab_switcher.rs +++ b/crates/tab_switcher/src/tab_switcher.rs @@ -591,15 +591,29 @@ impl TabSwitcherDelegate { let Some(workspace) = self.workspace.upgrade() else { return; }; - workspace.update(cx, |workspace, cx| { - workspace.close_items_with_project_path( - &project_path, - SaveIntent::Close, - true, - window, - cx, - ); - }); + let panes_and_items: Vec<_> = workspace + .read(cx) + .panes() + .iter() + .map(|pane| { + let items_to_close: Vec<_> = pane + .read(cx) + .items() + .filter(|item| item.project_path(cx) == Some(project_path.clone())) + .map(|item| item.item_id()) + .collect(); + (pane.clone(), items_to_close) + }) + .collect(); + + for (pane, items_to_close) in panes_and_items { + for item_id in items_to_close { + pane.update(cx, |pane, cx| { + pane.close_item_by_id(item_id, SaveIntent::Close, window, cx) + .detach_and_log_err(cx); + }); + } + } } else { let Some(pane) = tab_match.pane.upgrade() else { return; diff --git a/crates/vim/src/command.rs b/crates/vim/src/command.rs index bb74cb1e73f78f82ed97dd94b52f33875a65aa27..423c3b387b197edd2d8e86398b09157fdcb7711a 100644 --- a/crates/vim/src/command.rs +++ b/crates/vim/src/command.rs @@ -1627,12 +1627,12 @@ fn generate_commands(_: &App) -> Vec { VimCommand::new(("cq", "uit"), zed_actions::Quit), VimCommand::new( ("bd", "elete"), - workspace::CloseItemInAllPanes { + workspace::CloseActiveItem { save_intent: Some(SaveIntent::Close), close_pinned: false, }, ) - .bang(workspace::CloseItemInAllPanes { + .bang(workspace::CloseActiveItem { save_intent: Some(SaveIntent::Skip), close_pinned: true, }), diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 8ea32dbf39e9a2df67f9121f818bdead84a56954..f025131758760d6c4db5250e2bbdb12a50d4ee01 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -782,10 +782,6 @@ impl Pane { self.active_item_index } - pub fn is_active_item_pinned(&self) -> bool { - self.is_tab_pinned(self.active_item_index) - } - pub fn activation_history(&self) -> &[ActivationHistoryEntry] { &self.activation_history } @@ -1624,26 +1620,6 @@ impl Pane { }) } - pub fn close_items_for_project_path( - &mut self, - project_path: &ProjectPath, - save_intent: SaveIntent, - close_pinned: bool, - window: &mut Window, - cx: &mut Context, - ) -> Task> { - let pinned_item_ids = self.pinned_item_ids(); - let matching_item_ids: Vec<_> = self - .items() - .filter(|item| item.project_path(cx).as_ref() == Some(project_path)) - .map(|item| item.item_id()) - .collect(); - self.close_items(window, cx, save_intent, move |item_id| { - matching_item_ids.contains(&item_id) - && (close_pinned || !pinned_item_ids.contains(&item_id)) - }) - } - pub fn close_other_items( &mut self, action: &CloseOtherItems, diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 12d3642b6d62abead277bdcce4f9a0c664c8cb45..8dff340e264abd583c471b95d96c90e14486a2c5 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -385,17 +385,6 @@ pub struct CloseInactiveTabsAndPanes { pub save_intent: Option, } -/// Closes the active item across all panes. -#[derive(Clone, PartialEq, Debug, Deserialize, Default, JsonSchema, Action)] -#[action(namespace = workspace)] -#[serde(deny_unknown_fields)] -pub struct CloseItemInAllPanes { - #[serde(default)] - pub save_intent: Option, - #[serde(default)] - pub close_pinned: bool, -} - /// Sends a sequence of keystrokes to the active element. #[derive(Clone, Deserialize, PartialEq, JsonSchema, Action)] #[action(namespace = workspace)] @@ -3298,61 +3287,6 @@ impl Workspace { } } - /// Closes the active item across all panes. - pub fn close_item_in_all_panes( - &mut self, - action: &CloseItemInAllPanes, - window: &mut Window, - cx: &mut Context, - ) { - let Some(active_item) = self.active_pane().read(cx).active_item() else { - return; - }; - - let save_intent = action.save_intent.unwrap_or(SaveIntent::Close); - let close_pinned = action.close_pinned; - - if let Some(project_path) = active_item.project_path(cx) { - self.close_items_with_project_path( - &project_path, - save_intent, - close_pinned, - window, - cx, - ); - } else if close_pinned || !self.active_pane().read(cx).is_active_item_pinned() { - let item_id = active_item.item_id(); - self.active_pane().update(cx, |pane, cx| { - pane.close_item_by_id(item_id, save_intent, window, cx) - .detach_and_log_err(cx); - }); - } - } - - /// Closes all items with the given project path across all panes. - pub fn close_items_with_project_path( - &mut self, - project_path: &ProjectPath, - save_intent: SaveIntent, - close_pinned: bool, - window: &mut Window, - cx: &mut Context, - ) { - let panes = self.panes().to_vec(); - for pane in panes { - pane.update(cx, |pane, cx| { - pane.close_items_for_project_path( - project_path, - save_intent, - close_pinned, - window, - cx, - ) - .detach_and_log_err(cx); - }); - } - } - fn close_all_internal( &mut self, retain_active_pane: bool, @@ -6230,7 +6164,6 @@ impl Workspace { )) .on_action(cx.listener(Self::close_inactive_items_and_panes)) .on_action(cx.listener(Self::close_all_items_and_panes)) - .on_action(cx.listener(Self::close_item_in_all_panes)) .on_action(cx.listener(Self::save_all)) .on_action(cx.listener(Self::send_keystrokes)) .on_action(cx.listener(Self::add_folder_to_project)) @@ -12007,101 +11940,6 @@ mod tests { }) } - #[gpui::test] - async fn test_close_item_in_all_panes(cx: &mut TestAppContext) { - init_test(cx); - - let fs = FakeFs::new(cx.executor()); - fs.insert_tree("/root", json!({ "test.txt": "" })).await; - - let project = Project::test(fs, ["root".as_ref()], cx).await; - let (workspace, cx) = - cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx)); - - let pane_a = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); - // Add item to pane A with project path - let item_a = cx.new(|cx| { - TestItem::new(cx).with_project_items(&[TestProjectItem::new(1, "test.txt", cx)]) - }); - workspace.update_in(cx, |workspace, window, cx| { - workspace.add_item_to_active_pane(Box::new(item_a.clone()), None, true, window, cx) - }); - - // Split to create pane B - let pane_b = workspace.update_in(cx, |workspace, window, cx| { - workspace.split_pane(pane_a.clone(), SplitDirection::Right, window, cx) - }); - - // Add item with SAME project path to pane B, and pin it - let item_b = cx.new(|cx| { - TestItem::new(cx).with_project_items(&[TestProjectItem::new(1, "test.txt", cx)]) - }); - pane_b.update_in(cx, |pane, window, cx| { - pane.add_item(Box::new(item_b.clone()), true, true, None, window, cx); - pane.set_pinned_count(1); - }); - - assert_eq!(pane_a.read_with(cx, |pane, _| pane.items_len()), 1); - assert_eq!(pane_b.read_with(cx, |pane, _| pane.items_len()), 1); - - // close_pinned: false should only close the unpinned copy - workspace.update_in(cx, |workspace, window, cx| { - workspace.close_item_in_all_panes( - &CloseItemInAllPanes { - save_intent: Some(SaveIntent::Close), - close_pinned: false, - }, - window, - cx, - ) - }); - cx.executor().run_until_parked(); - - let item_count_a = pane_a.read_with(cx, |pane, _| pane.items_len()); - let item_count_b = pane_b.read_with(cx, |pane, _| pane.items_len()); - assert_eq!(item_count_a, 0, "Unpinned item in pane A should be closed"); - assert_eq!(item_count_b, 1, "Pinned item in pane B should remain"); - - // Split again, seeing as closing the previous item also closed its - // pane, so only pane remains, which does not allow us to properly test - // that both items close when `close_pinned: true`. - let pane_c = workspace.update_in(cx, |workspace, window, cx| { - workspace.split_pane(pane_b.clone(), SplitDirection::Right, window, cx) - }); - - // Add an item with the same project path to pane C so that - // close_item_in_all_panes can determine what to close across all panes - // (it reads the active item from the active pane, and split_pane - // creates an empty pane). - let item_c = cx.new(|cx| { - TestItem::new(cx).with_project_items(&[TestProjectItem::new(1, "test.txt", cx)]) - }); - pane_c.update_in(cx, |pane, window, cx| { - pane.add_item(Box::new(item_c.clone()), true, true, None, window, cx); - }); - - // close_pinned: true should close the pinned copy too - workspace.update_in(cx, |workspace, window, cx| { - let panes_count = workspace.panes().len(); - assert_eq!(panes_count, 2, "Workspace should have two panes (B and C)"); - - workspace.close_item_in_all_panes( - &CloseItemInAllPanes { - save_intent: Some(SaveIntent::Close), - close_pinned: true, - }, - window, - cx, - ) - }); - cx.executor().run_until_parked(); - - let item_count_b = pane_b.read_with(cx, |pane, _| pane.items_len()); - let item_count_c = pane_c.read_with(cx, |pane, _| pane.items_len()); - assert_eq!(item_count_b, 0, "Pinned item in pane B should be closed"); - assert_eq!(item_count_c, 0, "Unpinned item in pane C should be closed"); - } - mod register_project_item_tests { use super::*;