paths: Replace `lazy_static!` with `OnceLock` (#13213)

Marshall Bowers created

This PR replaces the `lazy_static!` usages in the `paths` crate with
`OnceLock` from the standard library.

This allows us to drop the `lazy_static` dependency from this crate.

The paths are now exposed as accessor functions that reference a private
static value.

Release Notes:

- N/A

Change summary

Cargo.lock                                                      |   1 
crates/assistant/src/assistant.rs                               |   3 
crates/assistant/src/assistant_panel.rs                         |   6 
crates/assistant/src/context_store.rs                           |   8 
crates/assistant/src/prompt_library.rs                          |   3 
crates/cli/src/main.rs                                          |   2 
crates/client/src/client.rs                                     |   2 
crates/client/src/telemetry.rs                                  |   2 
crates/copilot/src/copilot.rs                                   |   8 
crates/db/src/db.rs                                             |   6 
crates/extension/src/extension_store.rs                         |   3 
crates/fs/src/fs.rs                                             |   2 
crates/inline_completion_button/src/inline_completion_button.rs |   2 
crates/languages/src/json.rs                                    |  10 
crates/node_runtime/src/node_runtime.rs                         |   2 
crates/paths/Cargo.toml                                         |   1 
crates/paths/src/paths.rs                                       | 315 ++
crates/prettier/src/prettier.rs                                 |   8 
crates/project/src/prettier_support.rs                          |  12 
crates/project/src/project.rs                                   |  11 
crates/rustdoc/src/store.rs                                     |   6 
crates/settings/src/settings_file.rs                            |   4 
crates/supermaven_api/src/supermaven_api.rs                     |  10 
crates/zed/src/main.rs                                          |  29 
crates/zed/src/reliability.rs                                   |  10 
crates/zed/src/zed.rs                                           |  22 
crates/zed/src/zed/open_listener.rs                             |   2 
27 files changed, 320 insertions(+), 170 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -7399,7 +7399,6 @@ name = "paths"
 version = "0.1.0"
 dependencies = [
  "dirs 4.0.0",
- "lazy_static",
  "util",
 ]
 

crates/assistant/src/assistant.rs 🔗

@@ -21,7 +21,6 @@ pub(crate) use context_store::*;
 use gpui::{actions, AppContext, Global, SharedString, UpdateGlobal};
 pub(crate) use inline_assistant::*;
 pub(crate) use model_selector::*;
-use paths::EMBEDDINGS_DIR;
 use rustdoc::RustdocStore;
 use semantic_index::{CloudEmbeddingProvider, SemanticIndex};
 use serde::{Deserialize, Serialize};
@@ -271,7 +270,7 @@ pub fn init(client: Arc<Client>, cx: &mut AppContext) {
         async move {
             let embedding_provider = CloudEmbeddingProvider::new(client.clone());
             let semantic_index = SemanticIndex::new(
-                EMBEDDINGS_DIR.join("semantic-index-db.0.mdb"),
+                paths::embeddings_dir().join("semantic-index-db.0.mdb"),
                 Arc::new(embedding_provider),
                 &mut cx,
             )

crates/assistant/src/assistant_panel.rs 🔗

@@ -39,7 +39,7 @@ use language::{
     LspAdapterDelegate, OffsetRangeExt as _, Point, ToOffset as _,
 };
 use multi_buffer::MultiBufferRow;
-use paths::CONTEXTS_DIR;
+use paths::contexts_dir;
 use picker::{Picker, PickerDelegate};
 use project::{Project, ProjectLspAdapterDelegate, ProjectTransaction};
 use rustdoc::{CrateName, RustdocStore};
@@ -2042,7 +2042,7 @@ impl Context {
                     let mut discriminant = 1;
                     let mut new_path;
                     loop {
-                        new_path = CONTEXTS_DIR.join(&format!(
+                        new_path = contexts_dir().join(&format!(
                             "{} - {}.zed.json",
                             summary.trim(),
                             discriminant
@@ -2056,7 +2056,7 @@ impl Context {
                     new_path
                 };
 
-                fs.create_dir(CONTEXTS_DIR.as_ref()).await?;
+                fs.create_dir(contexts_dir().as_ref()).await?;
                 fs.atomic_write(path.clone(), serde_json::to_string(&context).unwrap())
                     .await?;
                 this.update(&mut cx, |this, _| this.path = Some(path))?;

crates/assistant/src/context_store.rs 🔗

@@ -6,7 +6,7 @@ use fs::Fs;
 use futures::StreamExt;
 use fuzzy::StringMatchCandidate;
 use gpui::{AppContext, Model, ModelContext, Task};
-use paths::CONTEXTS_DIR;
+use paths::contexts_dir;
 use regex::Regex;
 use serde::{Deserialize, Serialize};
 use std::{cmp::Reverse, ffi::OsStr, path::PathBuf, sync::Arc, time::Duration};
@@ -76,7 +76,7 @@ impl ContextStore {
     pub fn new(fs: Arc<dyn Fs>, cx: &mut AppContext) -> Task<Result<Model<Self>>> {
         cx.spawn(|mut cx| async move {
             const CONTEXT_WATCH_DURATION: Duration = Duration::from_millis(100);
-            let (mut events, _) = fs.watch(&CONTEXTS_DIR, CONTEXT_WATCH_DURATION).await;
+            let (mut events, _) = fs.watch(contexts_dir(), CONTEXT_WATCH_DURATION).await;
 
             let this = cx.new_model(|cx: &mut ModelContext<Self>| Self {
                 contexts_metadata: Vec::new(),
@@ -181,9 +181,9 @@ impl ContextStore {
     fn reload(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
         let fs = self.fs.clone();
         cx.spawn(|this, mut cx| async move {
-            fs.create_dir(&CONTEXTS_DIR).await?;
+            fs.create_dir(contexts_dir()).await?;
 
-            let mut paths = fs.read_dir(&CONTEXTS_DIR).await?;
+            let mut paths = fs.read_dir(contexts_dir()).await?;
             let mut contexts = Vec::<SavedContextMetadata>::new();
             while let Some(path) = paths.next().await {
                 let path = path?;

crates/assistant/src/prompt_library.rs 🔗

@@ -20,7 +20,6 @@ use gpui::{
 use heed::{types::SerdeBincode, Database, RoTxn};
 use language::{language_settings::SoftWrap, Buffer, LanguageRegistry};
 use parking_lot::RwLock;
-use paths::PROMPTS_DIR;
 use picker::{Picker, PickerDelegate};
 use rope::Rope;
 use serde::{Deserialize, Serialize};
@@ -49,7 +48,7 @@ actions!(
 /// Init starts loading the PromptStore in the background and assigns
 /// a shared future to a global.
 pub fn init(cx: &mut AppContext) {
-    let db_path = PROMPTS_DIR.join("prompts-library-db.0.mdb");
+    let db_path = paths::prompts_dir().join("prompts-library-db.0.mdb");
     let prompt_store_future = PromptStore::new(db_path, cx.background_executor().clone())
         .then(|result| future::ready(result.map(Arc::new).map_err(Arc::new)))
         .boxed()

crates/cli/src/main.rs 🔗

@@ -220,7 +220,7 @@ mod linux {
         }
 
         fn launch(&self, ipc_url: String) -> anyhow::Result<()> {
-            let sock_path = paths::SUPPORT_DIR.join(format!("zed-{}.sock", *RELEASE_CHANNEL));
+            let sock_path = paths::support_dir().join(format!("zed-{}.sock", *RELEASE_CHANNEL));
             let sock = UnixDatagram::unbound()?;
             if sock.connect(&sock_path).is_err() {
                 self.boot_background(ipc_url)?;

crates/client/src/client.rs 🔗

@@ -509,7 +509,7 @@ impl Client {
         let credentials_provider: Arc<dyn CredentialsProvider + Send + Sync + 'static> =
             if use_zed_development_auth {
                 Arc::new(DevelopmentCredentialsProvider {
-                    path: paths::CONFIG_DIR.join("development_auth"),
+                    path: paths::config_dir().join("development_auth"),
                 })
             } else {
                 Arc::new(KeychainCredentialsProvider)

crates/client/src/telemetry.rs 🔗

@@ -223,7 +223,7 @@ impl Telemetry {
                 let state = state.clone();
                 async move {
                     if let Some(tempfile) =
-                        NamedTempFile::new_in(paths::CONFIG_DIR.as_path()).log_err()
+                        NamedTempFile::new_in(paths::config_dir().as_path()).log_err()
                     {
                         state.lock().log_file = Some(tempfile);
                     }

crates/copilot/src/copilot.rs 🔗

@@ -968,7 +968,7 @@ fn uri_for_buffer(buffer: &Model<Buffer>, cx: &AppContext) -> lsp::Url {
 }
 
 async fn clear_copilot_dir() {
-    remove_matching(&paths::COPILOT_DIR, |_| true).await
+    remove_matching(paths::copilot_dir(), |_| true).await
 }
 
 async fn get_copilot_lsp(http: Arc<dyn HttpClient>) -> anyhow::Result<PathBuf> {
@@ -979,7 +979,7 @@ async fn get_copilot_lsp(http: Arc<dyn HttpClient>) -> anyhow::Result<PathBuf> {
         let release =
             latest_github_release("zed-industries/copilot", true, false, http.clone()).await?;
 
-        let version_dir = &*paths::COPILOT_DIR.join(format!("copilot-{}", release.tag_name));
+        let version_dir = &paths::copilot_dir().join(format!("copilot-{}", release.tag_name));
 
         fs::create_dir_all(version_dir).await?;
         let server_path = version_dir.join(SERVER_PATH);
@@ -1003,7 +1003,7 @@ async fn get_copilot_lsp(http: Arc<dyn HttpClient>) -> anyhow::Result<PathBuf> {
             let archive = Archive::new(decompressed_bytes);
             archive.unpack(dist_dir).await?;
 
-            remove_matching(&paths::COPILOT_DIR, |entry| entry != version_dir).await;
+            remove_matching(paths::copilot_dir(), |entry| entry != version_dir).await;
         }
 
         Ok(server_path)
@@ -1016,7 +1016,7 @@ async fn get_copilot_lsp(http: Arc<dyn HttpClient>) -> anyhow::Result<PathBuf> {
             // Fetch a cached binary, if it exists
             maybe!(async {
                 let mut last_version_dir = None;
-                let mut entries = fs::read_dir(paths::COPILOT_DIR.as_path()).await?;
+                let mut entries = fs::read_dir(paths::copilot_dir()).await?;
                 while let Some(entry) = entries.next().await {
                     let entry = entry?;
                     if entry.file_type().await?.is_dir() {

crates/db/src/db.rs 🔗

@@ -7,7 +7,7 @@ use anyhow::Context;
 use gpui::AppContext;
 pub use indoc::indoc;
 pub use lazy_static;
-pub use paths::DB_DIR;
+pub use paths::database_dir;
 pub use smol;
 pub use sqlez;
 pub use sqlez_macros;
@@ -145,7 +145,7 @@ macro_rules! define_connection {
 
         #[cfg(not(any(test, feature = "test-support")))]
         $crate::lazy_static::lazy_static! {
-            pub static ref $id: $t = $t($crate::smol::block_on($crate::open_db(&$crate::DB_DIR, &$crate::RELEASE_CHANNEL)));
+            pub static ref $id: $t = $t($crate::smol::block_on($crate::open_db($crate::database_dir(), &$crate::RELEASE_CHANNEL)));
         }
     };
     (pub static ref $id:ident: $t:ident<$($d:ty),+> = $migrations:expr;) => {
@@ -176,7 +176,7 @@ macro_rules! define_connection {
 
         #[cfg(not(any(test, feature = "test-support")))]
         $crate::lazy_static::lazy_static! {
-            pub static ref $id: $t = $t($crate::smol::block_on($crate::open_db(&$crate::DB_DIR, &$crate::RELEASE_CHANNEL)));
+            pub static ref $id: $t = $t($crate::smol::block_on($crate::open_db($crate::database_dir(), &$crate::RELEASE_CHANNEL)));
         }
     };
 }

crates/extension/src/extension_store.rs 🔗

@@ -36,7 +36,6 @@ use language::{
     LanguageConfig, LanguageMatcher, LanguageQueries, LanguageRegistry, QUERY_FILENAME_PREFIXES,
 };
 use node_runtime::NodeRuntime;
-use paths::EXTENSIONS_DIR;
 use project::ContextProviderWithTasks;
 use release_channel::ReleaseChannel;
 use semantic_version::SemanticVersion;
@@ -180,7 +179,7 @@ pub fn init(
 
     let store = cx.new_model(move |cx| {
         ExtensionStore::new(
-            EXTENSIONS_DIR.clone(),
+            paths::extensions_dir().clone(),
             None,
             fs,
             client.http_client().clone(),

crates/fs/src/fs.rs 🔗

@@ -325,7 +325,7 @@ impl Fs for RealFs {
                 // Use the directory of the destination as temp dir to avoid
                 // invalid cross-device link error, and XDG_CACHE_DIR for fallback.
                 // See https://github.com/zed-industries/zed/pull/8437 for more details.
-                NamedTempFile::new_in(path.parent().unwrap_or(&paths::TEMP_DIR))
+                NamedTempFile::new_in(path.parent().unwrap_or(&paths::temp_dir()))
             } else {
                 NamedTempFile::new()
             }?;

crates/inline_completion_button/src/inline_completion_button.rs 🔗

@@ -369,7 +369,7 @@ async fn configure_disabled_globs(
 ) -> Result<()> {
     let settings_editor = workspace
         .update(&mut cx, |_, cx| {
-            create_and_open_local_file(&paths::SETTINGS, cx, || {
+            create_and_open_local_file(paths::settings_file(), cx, || {
                 settings::initial_user_settings_content().as_ref().into()
             })
         })?

crates/languages/src/json.rs 🔗

@@ -98,19 +98,19 @@ impl JsonLspAdapter {
                     },
                     {
                         "fileMatch": [
-                            schema_file_match(&paths::SETTINGS),
-                            &*paths::LOCAL_SETTINGS_RELATIVE_PATH,
+                            schema_file_match(paths::settings_file()),
+                            paths::local_settings_file_relative_path()
                         ],
                         "schema": settings_schema,
                     },
                     {
-                        "fileMatch": [schema_file_match(&paths::KEYMAP)],
+                        "fileMatch": [schema_file_match(paths::keymap_file())],
                         "schema": KeymapFile::generate_json_schema(&action_names),
                     },
                     {
                         "fileMatch": [
-                            schema_file_match(&paths::TASKS),
-                            &*paths::LOCAL_TASKS_RELATIVE_PATH,
+                            schema_file_match(paths::tasks_file()),
+                            paths::local_tasks_file_relative_path()
                         ],
                         "schema": tasks_schema,
                     }

crates/node_runtime/src/node_runtime.rs 🔗

@@ -138,7 +138,7 @@ impl RealNodeRuntime {
         };
 
         let folder_name = format!("node-{VERSION}-{os}-{arch}");
-        let node_containing_dir = paths::SUPPORT_DIR.join("node");
+        let node_containing_dir = paths::support_dir().join("node");
         let node_dir = node_containing_dir.join(folder_name);
         let node_binary = node_dir.join(NODE_PATH);
         let npm_file = node_dir.join(NPM_PATH);

crates/paths/Cargo.toml 🔗

@@ -13,5 +13,4 @@ path = "src/paths.rs"
 
 [dependencies]
 dirs.workspace = true
-lazy_static.workspace = true
 util.workspace = true

crates/paths/src/paths.rs 🔗

@@ -1,92 +1,243 @@
 //! Paths to locations used by Zed.
 
 use std::path::{Path, PathBuf};
+use std::sync::OnceLock;
 
 use util::paths::HOME;
 
-lazy_static::lazy_static! {
-    pub static ref CONFIG_DIR: PathBuf = if cfg!(target_os = "windows") {
-        dirs::config_dir()
-            .expect("failed to determine RoamingAppData directory")
-            .join("Zed")
-    } else if cfg!(target_os = "linux") {
-        if let Ok(flatpak_xdg_config) = std::env::var("FLATPAK_XDG_CONFIG_HOME") {
-           flatpak_xdg_config.into()
-        } else {
-            dirs::config_dir().expect("failed to determine XDG_CONFIG_HOME directory")
-        }.join("zed")
-    } else {
+/// Returns the path to the configuration directory used by Zed.
+pub fn config_dir() -> &'static PathBuf {
+    static CONFIG_DIR: OnceLock<PathBuf> = OnceLock::new();
+    CONFIG_DIR.get_or_init(|| {
+        if cfg!(target_os = "windows") {
+            return dirs::config_dir()
+                .expect("failed to determine RoamingAppData directory")
+                .join("Zed");
+        }
+
+        if cfg!(target_os = "linux") {
+            return if let Ok(flatpak_xdg_config) = std::env::var("FLATPAK_XDG_CONFIG_HOME") {
+                flatpak_xdg_config.into()
+            } else {
+                dirs::config_dir().expect("failed to determine XDG_CONFIG_HOME directory")
+            }
+            .join("zed");
+        }
+
         HOME.join(".config").join("zed")
-    };
-    pub static ref CONTEXTS_DIR: PathBuf = if cfg!(target_os = "macos") {
-        CONFIG_DIR.join("conversations")
-    } else {
-        SUPPORT_DIR.join("conversations")
-    };
-    pub static ref PROMPTS_DIR: PathBuf = if cfg!(target_os = "macos") {
-        CONFIG_DIR.join("prompts")
-    } else {
-        SUPPORT_DIR.join("prompts")
-    };
-    pub static ref EMBEDDINGS_DIR: PathBuf = if cfg!(target_os = "macos") {
-        CONFIG_DIR.join("embeddings")
-    } else {
-        SUPPORT_DIR.join("embeddings")
-    };
-    pub static ref THEMES_DIR: PathBuf = CONFIG_DIR.join("themes");
-
-    pub static ref SUPPORT_DIR: PathBuf = if cfg!(target_os = "macos") {
-        HOME.join("Library/Application Support/Zed")
-    } else if cfg!(target_os = "linux") {
-        if let Ok(flatpak_xdg_data) = std::env::var("FLATPAK_XDG_DATA_HOME") {
-            flatpak_xdg_data.into()
+    })
+}
+
+/// Returns the path to the support directory used by Zed.
+pub fn support_dir() -> &'static PathBuf {
+    static SUPPORT_DIR: OnceLock<PathBuf> = OnceLock::new();
+    SUPPORT_DIR.get_or_init(|| {
+        if cfg!(target_os = "macos") {
+            return HOME.join("Library/Application Support/Zed");
+        }
+
+        if cfg!(target_os = "linux") {
+            return if let Ok(flatpak_xdg_data) = std::env::var("FLATPAK_XDG_DATA_HOME") {
+                flatpak_xdg_data.into()
+            } else {
+                dirs::data_local_dir().expect("failed to determine XDG_DATA_HOME directory")
+            }
+            .join("zed");
+        }
+
+        if cfg!(target_os = "windows") {
+            return dirs::data_local_dir()
+                .expect("failed to determine LocalAppData directory")
+                .join("Zed");
+        }
+
+        config_dir().clone()
+    })
+}
+
+/// Returns the path to the temp directory used by Zed.
+pub fn temp_dir() -> &'static PathBuf {
+    static TEMP_DIR: OnceLock<PathBuf> = OnceLock::new();
+    TEMP_DIR.get_or_init(|| {
+        if cfg!(target_os = "windows") {
+            return dirs::cache_dir()
+                .expect("failed to determine LocalAppData directory")
+                .join("Zed");
+        }
+
+        if cfg!(target_os = "linux") {
+            return if let Ok(flatpak_xdg_cache) = std::env::var("FLATPAK_XDG_CACHE_HOME") {
+                flatpak_xdg_cache.into()
+            } else {
+                dirs::cache_dir().expect("failed to determine XDG_CACHE_HOME directory")
+            }
+            .join("zed");
+        }
+
+        HOME.join(".cache").join("zed")
+    })
+}
+
+/// Returns the path to the logs directory.
+pub fn logs_dir() -> &'static PathBuf {
+    static LOGS_DIR: OnceLock<PathBuf> = OnceLock::new();
+    LOGS_DIR.get_or_init(|| {
+        if cfg!(target_os = "macos") {
+            HOME.join("Library/Logs/Zed")
+        } else {
+            support_dir().join("logs")
+        }
+    })
+}
+
+/// Returns the path to the `Zed.log` file.
+pub fn log_file() -> &'static PathBuf {
+    static LOG_FILE: OnceLock<PathBuf> = OnceLock::new();
+    LOG_FILE.get_or_init(|| logs_dir().join("Zed.log"))
+}
+
+/// Returns the path to the `Zed.log.old` file.
+pub fn old_log_file() -> &'static PathBuf {
+    static OLD_LOG_FILE: OnceLock<PathBuf> = OnceLock::new();
+    OLD_LOG_FILE.get_or_init(|| logs_dir().join("Zed.log.old"))
+}
+
+/// Returns the path to the database directory.
+pub fn database_dir() -> &'static PathBuf {
+    static DATABASE_DIR: OnceLock<PathBuf> = OnceLock::new();
+    DATABASE_DIR.get_or_init(|| support_dir().join("db"))
+}
+
+/// Returns the path to the crashes directory, if it exists for the current platform.
+pub fn crashes_dir() -> &'static Option<PathBuf> {
+    static CRASHES_DIR: OnceLock<Option<PathBuf>> = OnceLock::new();
+    CRASHES_DIR.get_or_init(|| {
+        cfg!(target_os = "macos").then_some(HOME.join("Library/Logs/DiagnosticReports"))
+    })
+}
+
+/// Returns the path to the retired crashes directory, if it exists for the current platform.
+pub fn crashes_retired_dir() -> &'static Option<PathBuf> {
+    static CRASHES_RETIRED_DIR: OnceLock<Option<PathBuf>> = OnceLock::new();
+    CRASHES_RETIRED_DIR.get_or_init(|| crashes_dir().as_ref().map(|dir| dir.join("Retired")))
+}
+
+/// Returns the path to the `settings.json` file.
+pub fn settings_file() -> &'static PathBuf {
+    static SETTINGS_FILE: OnceLock<PathBuf> = OnceLock::new();
+    SETTINGS_FILE.get_or_init(|| config_dir().join("settings.json"))
+}
+
+/// Returns the path to the `keymap.json` file.
+pub fn keymap_file() -> &'static PathBuf {
+    static KEYMAP_FILE: OnceLock<PathBuf> = OnceLock::new();
+    KEYMAP_FILE.get_or_init(|| config_dir().join("keymap.json"))
+}
+
+/// Returns the path to the `tasks.json` file.
+pub fn tasks_file() -> &'static PathBuf {
+    static TASKS_FILE: OnceLock<PathBuf> = OnceLock::new();
+    TASKS_FILE.get_or_init(|| config_dir().join("tasks.json"))
+}
+
+/// Returns the path to the extensions directory.
+///
+/// This is where installed extensions are stored.
+pub fn extensions_dir() -> &'static PathBuf {
+    static EXTENSIONS_DIR: OnceLock<PathBuf> = OnceLock::new();
+    EXTENSIONS_DIR.get_or_init(|| support_dir().join("extensions"))
+}
+
+/// Returns the path to the themes directory.
+///
+/// This is where themes that are not provided by extensions are stored.
+pub fn themes_dir() -> &'static PathBuf {
+    static THEMES_DIR: OnceLock<PathBuf> = OnceLock::new();
+    THEMES_DIR.get_or_init(|| config_dir().join("themes"))
+}
+
+/// Returns the path to the contexts directory.
+///
+/// This is where the saved contexts from the Assistant are stored.
+pub fn contexts_dir() -> &'static PathBuf {
+    static CONTEXTS_DIR: OnceLock<PathBuf> = OnceLock::new();
+    CONTEXTS_DIR.get_or_init(|| {
+        if cfg!(target_os = "macos") {
+            config_dir().join("conversations")
         } else {
-            dirs::data_local_dir().expect("failed to determine XDG_DATA_HOME directory")
-        }.join("zed")
-    } else if cfg!(target_os = "windows") {
-        dirs::data_local_dir()
-            .expect("failed to determine LocalAppData directory")
-            .join("Zed")
-    } else {
-        CONFIG_DIR.clone()
-    };
-    pub static ref LOGS_DIR: PathBuf = if cfg!(target_os = "macos") {
-        HOME.join("Library/Logs/Zed")
-    } else {
-        SUPPORT_DIR.join("logs")
-    };
-    pub static ref EXTENSIONS_DIR: PathBuf = SUPPORT_DIR.join("extensions");
-    pub static ref LANGUAGES_DIR: PathBuf = SUPPORT_DIR.join("languages");
-    pub static ref COPILOT_DIR: PathBuf = SUPPORT_DIR.join("copilot");
-    pub static ref SUPERMAVEN_DIR: PathBuf = SUPPORT_DIR.join("supermaven");
-    pub static ref DEFAULT_PRETTIER_DIR: PathBuf = SUPPORT_DIR.join("prettier");
-    pub static ref DB_DIR: PathBuf = SUPPORT_DIR.join("db");
-    pub static ref CRASHES_DIR: Option<PathBuf> = cfg!(target_os = "macos")
-        .then_some(HOME.join("Library/Logs/DiagnosticReports"));
-    pub static ref CRASHES_RETIRED_DIR: Option<PathBuf> = CRASHES_DIR
-        .as_ref()
-        .map(|dir| dir.join("Retired"));
-
-    pub static ref SETTINGS: PathBuf = CONFIG_DIR.join("settings.json");
-    pub static ref KEYMAP: PathBuf = CONFIG_DIR.join("keymap.json");
-    pub static ref TASKS: PathBuf = CONFIG_DIR.join("tasks.json");
-    pub static ref LAST_USERNAME: PathBuf = CONFIG_DIR.join("last-username.txt");
-    pub static ref LOG: PathBuf = LOGS_DIR.join("Zed.log");
-    pub static ref OLD_LOG: PathBuf = LOGS_DIR.join("Zed.log.old");
-    pub static ref LOCAL_SETTINGS_RELATIVE_PATH: &'static Path = Path::new(".zed/settings.json");
-    pub static ref LOCAL_TASKS_RELATIVE_PATH: &'static Path = Path::new(".zed/tasks.json");
-    pub static ref LOCAL_VSCODE_TASKS_RELATIVE_PATH: &'static Path = Path::new(".vscode/tasks.json");
-    pub static ref TEMP_DIR: PathBuf = if cfg!(target_os = "windows") {
-        dirs::cache_dir()
-            .expect("failed to determine LocalAppData directory")
-            .join("Zed")
-    } else if cfg!(target_os = "linux") {
-        if let Ok(flatpak_xdg_cache) = std::env::var("FLATPAK_XDG_CACHE_HOME") {
-            flatpak_xdg_cache.into()
+            support_dir().join("conversations")
+        }
+    })
+}
+
+/// Returns the path to the contexts directory.
+///
+/// This is where the prompts for use with the Assistant are stored.
+pub fn prompts_dir() -> &'static PathBuf {
+    static PROMPTS_DIR: OnceLock<PathBuf> = OnceLock::new();
+    PROMPTS_DIR.get_or_init(|| {
+        if cfg!(target_os = "macos") {
+            config_dir().join("prompts")
         } else {
-            dirs::cache_dir().expect("failed to determine XDG_CACHE_HOME directory")
-        }.join("zed")
-    } else {
-        HOME.join(".cache").join("zed")
-    };
+            support_dir().join("prompts")
+        }
+    })
+}
+
+/// Returns the path to the semantic search's embeddings directory.
+///
+/// This is where the embeddings used to power semantic search are stored.
+pub fn embeddings_dir() -> &'static PathBuf {
+    static EMBEDDINGS_DIR: OnceLock<PathBuf> = OnceLock::new();
+    EMBEDDINGS_DIR.get_or_init(|| {
+        if cfg!(target_os = "macos") {
+            config_dir().join("embeddings")
+        } else {
+            support_dir().join("embeddings")
+        }
+    })
+}
+
+/// Returns the path to the languages directory.
+///
+/// This is where language servers are downloaded to for languages built-in to Zed.
+pub fn languages_dir() -> &'static PathBuf {
+    static LANGUAGES_DIR: OnceLock<PathBuf> = OnceLock::new();
+    LANGUAGES_DIR.get_or_init(|| support_dir().join("languages"))
+}
+
+/// Returns the path to the Copilot directory.
+pub fn copilot_dir() -> &'static PathBuf {
+    static COPILOT_DIR: OnceLock<PathBuf> = OnceLock::new();
+    COPILOT_DIR.get_or_init(|| support_dir().join("copilot"))
+}
+
+/// Returns the path to the Supermaven directory.
+pub fn supermaven_dir() -> &'static PathBuf {
+    static SUPERMAVEN_DIR: OnceLock<PathBuf> = OnceLock::new();
+    SUPERMAVEN_DIR.get_or_init(|| support_dir().join("supermaven"))
+}
+
+/// Returns the path to the default Prettier directory.
+pub fn default_prettier_dir() -> &'static PathBuf {
+    static DEFAULT_PRETTIER_DIR: OnceLock<PathBuf> = OnceLock::new();
+    DEFAULT_PRETTIER_DIR.get_or_init(|| support_dir().join("prettier"))
+}
+
+/// Returns the relative path to a `settings.json` file within a project.
+pub fn local_settings_file_relative_path() -> &'static Path {
+    static LOCAL_SETTINGS_FILE_RELATIVE_PATH: OnceLock<&Path> = OnceLock::new();
+    LOCAL_SETTINGS_FILE_RELATIVE_PATH.get_or_init(|| Path::new(".zed/settings.json"))
+}
+
+/// Returns the relative path to a `tasks.json` file within a project.
+pub fn local_tasks_file_relative_path() -> &'static Path {
+    static LOCAL_TASKS_FILE_RELATIVE_PATH: OnceLock<&Path> = OnceLock::new();
+    LOCAL_TASKS_FILE_RELATIVE_PATH.get_or_init(|| Path::new(".zed/tasks.json"))
+}
+
+/// Returns the relative path to a `.vscode/tasks.json` file within a project.
+pub fn local_vscode_tasks_file_relative_path() -> &'static Path {
+    static LOCAL_VSCODE_TASKS_FILE_RELATIVE_PATH: OnceLock<&Path> = OnceLock::new();
+    LOCAL_VSCODE_TASKS_FILE_RELATIVE_PATH.get_or_init(|| Path::new(".vscode/tasks.json"))
 }

crates/prettier/src/prettier.rs 🔗

@@ -5,7 +5,7 @@ use gpui::{AsyncAppContext, Model};
 use language::{language_settings::language_settings, Buffer, Diff};
 use lsp::{LanguageServer, LanguageServerId};
 use node_runtime::NodeRuntime;
-use paths::DEFAULT_PRETTIER_DIR;
+use paths::default_prettier_dir;
 use serde::{Deserialize, Serialize};
 use std::{
     ops::ControlFlow,
@@ -159,7 +159,7 @@ impl Prettier {
         _: AsyncAppContext,
     ) -> anyhow::Result<Self> {
         Ok(Self::Test(TestPrettier {
-            default: prettier_dir == DEFAULT_PRETTIER_DIR.as_path(),
+            default: prettier_dir == default_prettier_dir().as_path(),
             prettier_dir,
         }))
     }
@@ -178,7 +178,7 @@ impl Prettier {
             prettier_dir.is_dir(),
             "Prettier dir {prettier_dir:?} is not a directory"
         );
-        let prettier_server = DEFAULT_PRETTIER_DIR.join(PRETTIER_SERVER_FILE);
+        let prettier_server = default_prettier_dir().join(PRETTIER_SERVER_FILE);
         anyhow::ensure!(
             prettier_server.is_file(),
             "no prettier server package found at {prettier_server:?}"
@@ -206,7 +206,7 @@ impl Prettier {
             .context("prettier server initialization")?;
         Ok(Self::Real(RealPrettier {
             server,
-            default: prettier_dir == DEFAULT_PRETTIER_DIR.as_path(),
+            default: prettier_dir == default_prettier_dir().as_path(),
             prettier_dir,
         }))
     }

crates/project/src/prettier_support.rs 🔗

@@ -18,7 +18,7 @@ use language::{
 };
 use lsp::{LanguageServer, LanguageServerId};
 use node_runtime::NodeRuntime;
-use paths::DEFAULT_PRETTIER_DIR;
+use paths::default_prettier_dir;
 use prettier::Prettier;
 use util::{ResultExt, TryFutureExt};
 
@@ -252,7 +252,7 @@ fn start_default_prettier(
                 }
                 let new_default_prettier = project.update(&mut cx, |project, cx| {
                     let new_default_prettier =
-                        start_prettier(node, DEFAULT_PRETTIER_DIR.clone(), worktree_id, cx);
+                        start_prettier(node, default_prettier_dir().clone(), worktree_id, cx);
                     project.default_prettier.prettier =
                         PrettierInstallation::Installed(PrettierInstance {
                             attempt: 0,
@@ -267,7 +267,7 @@ fn start_default_prettier(
                 None => {
                     let new_default_prettier = project.update(&mut cx, |project, cx| {
                         let new_default_prettier =
-                            start_prettier(node, DEFAULT_PRETTIER_DIR.clone(), worktree_id, cx);
+                            start_prettier(node, default_prettier_dir().clone(), worktree_id, cx);
                         project.default_prettier.prettier =
                             PrettierInstallation::Installed(PrettierInstance {
                                 attempt: instance.attempt + 1,
@@ -380,7 +380,7 @@ async fn install_prettier_packages(
     .await
     .context("fetching latest npm versions")?;
 
-    let default_prettier_dir = DEFAULT_PRETTIER_DIR.as_path();
+    let default_prettier_dir = default_prettier_dir().as_path();
     match fs.metadata(default_prettier_dir).await.with_context(|| {
         format!("fetching FS metadata for default prettier dir {default_prettier_dir:?}")
     })? {
@@ -406,7 +406,7 @@ async fn install_prettier_packages(
 }
 
 async fn save_prettier_server_file(fs: &dyn Fs) -> anyhow::Result<()> {
-    let prettier_wrapper_path = DEFAULT_PRETTIER_DIR.join(prettier::PRETTIER_SERVER_FILE);
+    let prettier_wrapper_path = default_prettier_dir().join(prettier::PRETTIER_SERVER_FILE);
     fs.save(
         &prettier_wrapper_path,
         &text::Rope::from(prettier::PRETTIER_SERVER_JS),
@@ -423,7 +423,7 @@ async fn save_prettier_server_file(fs: &dyn Fs) -> anyhow::Result<()> {
 }
 
 async fn should_write_prettier_server_file(fs: &dyn Fs) -> bool {
-    let prettier_wrapper_path = DEFAULT_PRETTIER_DIR.join(prettier::PRETTIER_SERVER_FILE);
+    let prettier_wrapper_path = default_prettier_dir().join(prettier::PRETTIER_SERVER_FILE);
     if !fs.is_file(&prettier_wrapper_path).await {
         return true;
     }

crates/project/src/project.rs 🔗

@@ -67,7 +67,8 @@ use lsp_command::*;
 use node_runtime::NodeRuntime;
 use parking_lot::{Mutex, RwLock};
 use paths::{
-    LOCAL_SETTINGS_RELATIVE_PATH, LOCAL_TASKS_RELATIVE_PATH, LOCAL_VSCODE_TASKS_RELATIVE_PATH,
+    local_settings_file_relative_path, local_tasks_file_relative_path,
+    local_vscode_tasks_file_relative_path,
 };
 use postage::watch;
 use prettier_support::{DefaultPrettier, PrettierInstance};
@@ -8176,10 +8177,10 @@ impl Project {
                 }
             };
 
-            if abs_path.ends_with(&*LOCAL_SETTINGS_RELATIVE_PATH) {
+            if abs_path.ends_with(local_settings_file_relative_path()) {
                 let settings_dir = Arc::from(
                     path.ancestors()
-                        .nth(LOCAL_SETTINGS_RELATIVE_PATH.components().count())
+                        .nth(local_settings_file_relative_path().components().count())
                         .unwrap(),
                 );
                 let fs = self.fs.clone();
@@ -8193,7 +8194,7 @@ impl Project {
                         },
                     )
                 });
-            } else if abs_path.ends_with(&*LOCAL_TASKS_RELATIVE_PATH) {
+            } else if abs_path.ends_with(local_tasks_file_relative_path()) {
                 self.task_inventory().update(cx, |task_inventory, cx| {
                     if removed {
                         task_inventory.remove_local_static_source(&abs_path);
@@ -8213,7 +8214,7 @@ impl Project {
                         );
                     }
                 })
-            } else if abs_path.ends_with(&*LOCAL_VSCODE_TASKS_RELATIVE_PATH) {
+            } else if abs_path.ends_with(local_vscode_tasks_file_relative_path()) {
                 self.task_inventory().update(cx, |task_inventory, cx| {
                     if removed {
                         task_inventory.remove_local_static_source(&abs_path);

crates/rustdoc/src/store.rs 🔗

@@ -12,7 +12,6 @@ use gpui::{AppContext, BackgroundExecutor, Global, ReadGlobal, Task, UpdateGloba
 use heed::types::SerdeBincode;
 use heed::Database;
 use parking_lot::RwLock;
-use paths::SUPPORT_DIR;
 use serde::{Deserialize, Serialize};
 use util::ResultExt;
 
@@ -57,7 +56,10 @@ impl RustdocStore {
             .spawn({
                 let executor = executor.clone();
                 async move {
-                    RustdocDatabase::new(SUPPORT_DIR.join("docs/rust/rustdoc-db.0.mdb"), executor)
+                    RustdocDatabase::new(
+                        paths::support_dir().join("docs/rust/rustdoc-db.0.mdb"),
+                        executor,
+                    )
                 }
             })
             .then(|result| future::ready(result.map(Arc::new).map_err(Arc::new)))

crates/settings/src/settings_file.rs 🔗

@@ -92,7 +92,7 @@ pub fn handle_settings_file_changes(
 }
 
 async fn load_settings(fs: &Arc<dyn Fs>) -> Result<String> {
-    match fs.load(&paths::SETTINGS).await {
+    match fs.load(paths::settings_file()).await {
         result @ Ok(_) => result,
         Err(err) => {
             if let Some(e) = err.downcast_ref::<std::io::Error>() {
@@ -115,7 +115,7 @@ pub fn update_settings_file<T: Settings>(
         let new_text = cx.read_global(|store: &SettingsStore, _cx| {
             store.new_text_for_update::<T>(old_text, update)
         })?;
-        let initial_path = paths::SETTINGS.as_path();
+        let initial_path = paths::settings_file().as_path();
         if fs.is_file(initial_path).await {
             let resolved_path = fs.canonicalize(initial_path).await.with_context(|| {
                 format!("Failed to canonicalize settings path {:?}", initial_path)

crates/supermaven_api/src/supermaven_api.rs 🔗

@@ -2,7 +2,7 @@ use anyhow::{anyhow, Context, Result};
 use futures::io::BufReader;
 use futures::{AsyncReadExt, Future};
 use http::{AsyncBody, HttpClient, Request as HttpRequest};
-use paths::SUPERMAVEN_DIR;
+use paths::supermaven_dir;
 use serde::{Deserialize, Serialize};
 use smol::fs::{self, File};
 use smol::stream::StreamExt;
@@ -212,7 +212,7 @@ pub async fn latest_release(
 }
 
 pub fn version_path(version: u64) -> PathBuf {
-    SUPERMAVEN_DIR.join(format!("sm-agent-{}", version))
+    supermaven_dir().join(format!("sm-agent-{}", version))
 }
 
 pub async fn has_version(version_path: &Path) -> bool {
@@ -225,12 +225,12 @@ pub fn get_supermaven_agent_path(
     client: Arc<dyn HttpClient>,
 ) -> impl Future<Output = Result<PathBuf>> {
     async move {
-        fs::create_dir_all(&*SUPERMAVEN_DIR)
+        fs::create_dir_all(supermaven_dir())
             .await
             .with_context(|| {
                 format!(
                     "Could not create Supermaven Agent Directory at {:?}",
-                    &*SUPERMAVEN_DIR
+                    supermaven_dir()
                 )
             })?;
 
@@ -278,7 +278,7 @@ pub fn get_supermaven_agent_path(
             .await?;
         }
 
-        let mut old_binary_paths = fs::read_dir(&*SUPERMAVEN_DIR).await?;
+        let mut old_binary_paths = fs::read_dir(supermaven_dir()).await?;
         while let Some(old_binary_path) = old_binary_paths.next().await {
             let old_binary_path = old_binary_path?;
             if old_binary_path.path() != binary_path {

crates/zed/src/main.rs 🔗

@@ -343,12 +343,12 @@ fn main() {
     let user_settings_file_rx = watch_config_file(
         &app.background_executor(),
         fs.clone(),
-        paths::SETTINGS.clone(),
+        paths::settings_file().clone(),
     );
     let user_keymap_file_rx = watch_config_file(
         &app.background_executor(),
         fs.clone(),
-        paths::KEYMAP.clone(),
+        paths::keymap_file().clone(),
     );
 
     let login_shell_env_loaded = if stdout_is_a_pty() {
@@ -399,7 +399,7 @@ fn main() {
         cx.update_http_client(client.http_client().clone());
         let mut languages =
             LanguageRegistry::new(login_shell_env_loaded, cx.background_executor().clone());
-        languages.set_language_server_download_dir(paths::LANGUAGES_DIR.clone());
+        languages.set_language_server_download_dir(paths::languages_dir().clone());
         let languages = Arc::new(languages);
         let node_runtime = RealNodeRuntime::new(client.http_client());
 
@@ -668,12 +668,12 @@ async fn restore_or_create_workspace(
 
 fn init_paths() -> anyhow::Result<()> {
     for path in [
-        &*paths::CONFIG_DIR,
-        &*paths::EXTENSIONS_DIR,
-        &*paths::LANGUAGES_DIR,
-        &*paths::DB_DIR,
-        &*paths::LOGS_DIR,
-        &*paths::TEMP_DIR,
+        paths::config_dir(),
+        paths::extensions_dir(),
+        paths::languages_dir(),
+        paths::database_dir(),
+        paths::logs_dir(),
+        paths::temp_dir(),
     ]
     .iter()
     {
@@ -693,15 +693,16 @@ fn init_logger() {
         const KIB: u64 = 1024;
         const MIB: u64 = 1024 * KIB;
         const MAX_LOG_BYTES: u64 = MIB;
-        if std::fs::metadata(&*paths::LOG).map_or(false, |metadata| metadata.len() > MAX_LOG_BYTES)
+        if std::fs::metadata(paths::log_file())
+            .map_or(false, |metadata| metadata.len() > MAX_LOG_BYTES)
         {
-            let _ = std::fs::rename(&*paths::LOG, &*paths::OLD_LOG);
+            let _ = std::fs::rename(paths::log_file(), paths::old_log_file());
         }
 
         match OpenOptions::new()
             .create(true)
             .append(true)
-            .open(&*paths::LOG)
+            .open(paths::log_file())
         {
             Ok(log_file) => {
                 let config = ConfigBuilder::new()
@@ -918,7 +919,7 @@ fn load_user_themes_in_background(fs: Arc<dyn fs::Fs>, cx: &mut AppContext) {
             if let Some(theme_registry) =
                 cx.update(|cx| ThemeRegistry::global(cx).clone()).log_err()
             {
-                let themes_dir = paths::THEMES_DIR.as_ref();
+                let themes_dir = paths::themes_dir().as_ref();
                 match fs
                     .metadata(themes_dir)
                     .await
@@ -949,7 +950,7 @@ fn watch_themes(fs: Arc<dyn fs::Fs>, cx: &mut AppContext) {
     use std::time::Duration;
     cx.spawn(|cx| async move {
         let (mut events, _) = fs
-            .watch(&paths::THEMES_DIR.clone(), Duration::from_millis(100))
+            .watch(paths::themes_dir(), Duration::from_millis(100))
             .await;
 
         while let Some(paths) = events.next().await {

crates/zed/src/reliability.rs 🔗

@@ -8,7 +8,7 @@ use http::Method;
 use isahc::config::Configurable;
 
 use http::{self, HttpClient, HttpClientWithUrl};
-use paths::{CRASHES_DIR, CRASHES_RETIRED_DIR};
+use paths::{crashes_dir, crashes_retired_dir};
 use release_channel::ReleaseChannel;
 use release_channel::RELEASE_CHANNEL;
 use settings::Settings;
@@ -113,7 +113,7 @@ pub fn init_panic_hook(
         if !is_pty {
             if let Some(panic_data_json) = serde_json::to_string(&panic_data).log_err() {
                 let timestamp = chrono::Utc::now().format("%Y_%m_%d %H_%M_%S").to_string();
-                let panic_file_path = paths::LOGS_DIR.join(format!("zed-{}.panic", timestamp));
+                let panic_file_path = paths::logs_dir().join(format!("zed-{}.panic", timestamp));
                 let panic_file = std::fs::OpenOptions::new()
                     .append(true)
                     .create(true)
@@ -368,7 +368,7 @@ async fn upload_previous_panics(
     telemetry_settings: client::TelemetrySettings,
 ) -> Result<Option<(i64, String)>> {
     let panic_report_url = http.build_zed_api_url("/telemetry/panics", &[])?;
-    let mut children = smol::fs::read_dir(&*paths::LOGS_DIR).await?;
+    let mut children = smol::fs::read_dir(paths::logs_dir()).await?;
 
     let mut most_recent_panic = None;
 
@@ -460,8 +460,8 @@ async fn upload_previous_crashes(
 
     let crash_report_url = http.build_zed_api_url("/telemetry/crashes", &[])?;
 
-    // crash directories are only set on MacOS
-    for dir in [&*CRASHES_DIR, &*CRASHES_RETIRED_DIR]
+    // Crash directories are only set on macOS.
+    for dir in [crashes_dir(), crashes_retired_dir()]
         .iter()
         .filter_map(|d| d.as_deref())
     {

crates/zed/src/zed.rs 🔗

@@ -36,7 +36,7 @@ use task::static_source::{StaticSource, TrackedFile};
 use theme::ActiveTheme;
 use workspace::notifications::NotificationId;
 
-use paths::{LOCAL_SETTINGS_RELATIVE_PATH, LOCAL_TASKS_RELATIVE_PATH};
+use paths::{local_settings_file_relative_path, local_tasks_file_relative_path};
 use terminal_view::terminal_panel::{self, TerminalPanel};
 use util::{asset_str, ResultExt};
 use uuid::Uuid;
@@ -178,11 +178,11 @@ pub fn initialize_workspace(app_state: Arc<AppState>, cx: &mut AppContext) {
                 let fs = app_state.fs.clone();
                 project.task_inventory().update(cx, |inventory, cx| {
                     let tasks_file_rx =
-                        watch_config_file(&cx.background_executor(), fs, paths::TASKS.clone());
+                        watch_config_file(&cx.background_executor(), fs, paths::tasks_file().clone());
                     inventory.add_source(
                         TaskSourceKind::AbsPath {
                             id_base: "global_tasks".into(),
-                            abs_path: paths::TASKS.clone(),
+                            abs_path: paths::tasks_file().clone(),
                         },
                         |tx, cx| StaticSource::new(TrackedFile::new(tasks_file_rx, tx, cx)),
                         cx,
@@ -341,13 +341,13 @@ pub fn initialize_workspace(app_state: Arc<AppState>, cx: &mut AppContext) {
             )
             .register_action(
                 move |_: &mut Workspace, _: &OpenKeymap, cx: &mut ViewContext<Workspace>| {
-                    open_settings_file(&paths::KEYMAP, Rope::default, cx);
+                    open_settings_file(paths::keymap_file(), Rope::default, cx);
                 },
             )
             .register_action(
                 move |_: &mut Workspace, _: &OpenSettings, cx: &mut ViewContext<Workspace>| {
                     open_settings_file(
-                        &paths::SETTINGS,
+                        paths::settings_file(),
                         || settings::initial_user_settings_content().as_ref().into(),
                         cx,
                     );
@@ -356,7 +356,7 @@ pub fn initialize_workspace(app_state: Arc<AppState>, cx: &mut AppContext) {
             .register_action(
                 move |_: &mut Workspace, _: &OpenTasks, cx: &mut ViewContext<Workspace>| {
                     open_settings_file(
-                        &paths::TASKS,
+                        paths::tasks_file(),
                         || settings::initial_tasks_content().as_ref().into(),
                         cx,
                     );
@@ -566,7 +566,7 @@ fn open_log_file(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) {
             let fs = workspace.app_state().fs.clone();
             cx.spawn(|workspace, mut cx| async move {
                 let (old_log, new_log) =
-                    futures::join!(fs.load(&paths::OLD_LOG), fs.load(&paths::LOG));
+                    futures::join!(fs.load(paths::old_log_file()), fs.load(paths::log_file()));
                 let log = match (old_log, new_log) {
                     (Err(_), Err(_)) => None,
                     (old_log, new_log) => {
@@ -602,7 +602,7 @@ fn open_log_file(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) {
                                     cx.new_view(|_| {
                                         MessageNotification::new(format!(
                                             "Unable to access/open log file at path {:?}",
-                                            paths::LOG.as_path()
+                                            paths::log_file().as_path()
                                         ))
                                     })
                                 },
@@ -715,7 +715,7 @@ fn open_local_settings_file(
 ) {
     open_local_file(
         workspace,
-        &LOCAL_SETTINGS_RELATIVE_PATH,
+        local_settings_file_relative_path(),
         initial_local_settings_content(),
         cx,
     )
@@ -728,7 +728,7 @@ fn open_local_tasks_file(
 ) {
     open_local_file(
         workspace,
-        &LOCAL_TASKS_RELATIVE_PATH,
+        local_tasks_file_relative_path(),
         initial_tasks_content(),
         cx,
     )
@@ -904,7 +904,7 @@ fn open_settings_file(
                 let worktree_creation_task = workspace.project().update(cx, |project, cx| {
                     // Set up a dedicated worktree for settings, since otherwise we're dropping and re-starting LSP servers for each file inside on every settings file close/open
                     // TODO: Do note that all other external files (e.g. drag and drop from OS) still have their worktrees released on file close, causing LSP servers' restarts.
-                    project.find_or_create_local_worktree(paths::CONFIG_DIR.as_path(), false, cx)
+                    project.find_or_create_local_worktree(paths::config_dir().as_path(), false, cx)
                 });
                 let settings_open_task = create_and_open_local_file(&abs_path, cx, default_content);
                 (worktree_creation_task, settings_open_task)

crates/zed/src/zed/open_listener.rs 🔗

@@ -114,7 +114,7 @@ pub fn listen_for_cli_connections(opener: OpenListener) -> Result<()> {
     use release_channel::RELEASE_CHANNEL_NAME;
     use std::os::unix::net::UnixDatagram;
 
-    let sock_path = paths::SUPPORT_DIR.join(format!("zed-{}.sock", *RELEASE_CHANNEL_NAME));
+    let sock_path = paths::support_dir().join(format!("zed-{}.sock", *RELEASE_CHANNEL_NAME));
     // remove the socket if the process listening on it has died
     if let Err(e) = UnixDatagram::unbound()?.connect(&sock_path) {
         if e.kind() == std::io::ErrorKind::ConnectionRefused {