From 40748b0a154e5fa05610662fd454b96f3a0ae67c Mon Sep 17 00:00:00 2001 From: Thorsten Ball Date: Mon, 24 Jun 2024 14:56:22 +0200 Subject: [PATCH] autosave: Respect project autosave settings per file (#13369) This fixes #13316 by checking whether there are any local workspace settings for a given file. Release Notes: - Fixed `autosave` settings in project-specific settings file being ignored. ([#13316](https://github.com/zed-industries/zed/issues/13316)). Co-authored-by: Bennet --- crates/workspace/src/item.rs | 24 ++++++++++++++++++++---- crates/workspace/src/pane.rs | 15 +++++++-------- crates/workspace/src/workspace.rs | 10 +++++----- crates/worktree/src/worktree.rs | 6 ++++++ 4 files changed, 38 insertions(+), 17 deletions(-) diff --git a/crates/workspace/src/item.rs b/crates/workspace/src/item.rs index 5956fdd0f9..48b8fb1d1e 100644 --- a/crates/workspace/src/item.rs +++ b/crates/workspace/src/item.rs @@ -20,7 +20,7 @@ use gpui::{ use project::{Project, ProjectEntryId, ProjectPath}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use settings::{Settings, SettingsSources}; +use settings::{Settings, SettingsLocation, SettingsSources}; use smallvec::SmallVec; use std::{ any::{Any, TypeId}, @@ -331,6 +331,7 @@ pub trait ItemHandle: 'static + Send { fn show_toolbar(&self, cx: &AppContext) -> bool; fn pixel_position_of_cursor(&self, cx: &AppContext) -> Option>; fn downgrade_item(&self) -> Box; + fn workspace_settings<'a>(&self, cx: &'a AppContext) -> &'a WorkspaceSettings; } pub trait WeakItemHandle: Send + Sync { @@ -401,6 +402,20 @@ impl ItemHandle for View { result } + fn workspace_settings<'a>(&self, cx: &'a AppContext) -> &'a WorkspaceSettings { + if let Some(project_path) = self.project_path(cx) { + WorkspaceSettings::get( + Some(SettingsLocation { + worktree_id: project_path.worktree_id.into(), + path: &project_path.path, + }), + cx, + ) + } else { + WorkspaceSettings::get_global(cx) + } + } + fn project_entry_ids(&self, cx: &AppContext) -> SmallVec<[ProjectEntryId; 3]> { let mut result = SmallVec::new(); self.read(cx).for_each_project_item(cx, &mut |_, item| { @@ -567,7 +582,8 @@ impl ItemHandle for View { } ItemEvent::Edit => { - let autosave = WorkspaceSettings::get_global(cx).autosave; + let autosave = item.workspace_settings(cx).autosave; + if let AutosaveSetting::AfterDelay { milliseconds } = autosave { let delay = Duration::from_millis(milliseconds); let item = item.clone(); @@ -584,8 +600,8 @@ impl ItemHandle for View { )); cx.on_blur(&self.focus_handle(cx), move |workspace, cx| { - if WorkspaceSettings::get_global(cx).autosave == AutosaveSetting::OnFocusChange { - if let Some(item) = weak_item.upgrade() { + if let Some(item) = weak_item.upgrade() { + if item.workspace_settings(cx).autosave == AutosaveSetting::OnFocusChange { Pane::autosave_item(&item, workspace.project.clone(), cx) .detach_and_log_err(cx); } diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index d940bee2ef..087cfd6bef 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -1421,7 +1421,7 @@ impl Pane { if save_intent == SaveIntent::Close { let will_autosave = cx.update(|cx| { matches!( - WorkspaceSettings::get_global(cx).autosave, + item.workspace_settings(cx).autosave, AutosaveSetting::OnFocusChange | AutosaveSetting::OnWindowChange ) && Self::can_autosave_item(item, cx) })?; @@ -1490,13 +1490,12 @@ impl Pane { project: Model, cx: &mut WindowContext, ) -> Task> { - let format = if let AutosaveSetting::AfterDelay { .. } = - WorkspaceSettings::get_global(cx).autosave - { - false - } else { - true - }; + let format = + if let AutosaveSetting::AfterDelay { .. } = item.workspace_settings(cx).autosave { + false + } else { + true + }; if Self::can_autosave_item(item, cx) { item.save(format, project, cx) } else { diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index e3f478765c..f156669956 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -3502,11 +3502,11 @@ impl Workspace { if let Some(item) = pane.active_item() { item.workspace_deactivated(cx); } - if matches!( - WorkspaceSettings::get_global(cx).autosave, - AutosaveSetting::OnWindowChange | AutosaveSetting::OnFocusChange - ) { - for item in pane.items() { + for item in pane.items() { + if matches!( + item.workspace_settings(cx).autosave, + AutosaveSetting::OnWindowChange | AutosaveSetting::OnFocusChange + ) { Pane::autosave_item(item.as_ref(), self.project.clone(), cx) .detach_and_log_err(cx); } diff --git a/crates/worktree/src/worktree.rs b/crates/worktree/src/worktree.rs index 7aeae0a065..2c856cf69c 100644 --- a/crates/worktree/src/worktree.rs +++ b/crates/worktree/src/worktree.rs @@ -70,6 +70,12 @@ pub const FS_WATCH_LATENCY: Duration = Duration::from_millis(100); #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, PartialOrd, Ord)] pub struct WorktreeId(usize); +impl From for usize { + fn from(value: WorktreeId) -> Self { + value.0 + } +} + /// A set of local or remote files that are being opened as part of a project. /// Responsible for tracking related FS (for local)/collab (for remote) events and corresponding updates. /// Stores git repositories data and the diagnostics for the file(s).