From e2e147ab0e7dbf6775f726230fef302b032fedd1 Mon Sep 17 00:00:00 2001 From: Julia Ryan Date: Thu, 7 Aug 2025 12:52:54 -0500 Subject: [PATCH] Add OS specific settings (#35756) Release Notes: - Settings can now be configured per operating system with the new top-level fields: `"macos"`/`"windows"`/`"linux"`. These will override user level settings, but are lower precedence than _release channel_ settings. --- crates/auto_update/src/auto_update.rs | 13 +++++++---- crates/go_to_line/src/cursor_position.rs | 12 ++++++---- crates/settings/src/settings_store.rs | 29 ++++++++++++++++++++++-- crates/theme/src/settings.rs | 1 + 4 files changed, 45 insertions(+), 10 deletions(-) diff --git a/crates/auto_update/src/auto_update.rs b/crates/auto_update/src/auto_update.rs index d62a9cdbe3..074aaa6fea 100644 --- a/crates/auto_update/src/auto_update.rs +++ b/crates/auto_update/src/auto_update.rs @@ -134,10 +134,15 @@ impl Settings for AutoUpdateSetting { type FileContent = Option; fn load(sources: SettingsSources, _: &mut App) -> Result { - let auto_update = [sources.server, sources.release_channel, sources.user] - .into_iter() - .find_map(|value| value.copied().flatten()) - .unwrap_or(sources.default.ok_or_else(Self::missing_default)?); + let auto_update = [ + sources.server, + sources.release_channel, + sources.operating_system, + sources.user, + ] + .into_iter() + .find_map(|value| value.copied().flatten()) + .unwrap_or(sources.default.ok_or_else(Self::missing_default)?); Ok(Self(auto_update.0)) } diff --git a/crates/go_to_line/src/cursor_position.rs b/crates/go_to_line/src/cursor_position.rs index 322a791b13..29064eb29c 100644 --- a/crates/go_to_line/src/cursor_position.rs +++ b/crates/go_to_line/src/cursor_position.rs @@ -308,10 +308,14 @@ impl Settings for LineIndicatorFormat { type FileContent = Option; fn load(sources: SettingsSources, _: &mut App) -> anyhow::Result { - let format = [sources.release_channel, sources.user] - .into_iter() - .find_map(|value| value.copied().flatten()) - .unwrap_or(sources.default.ok_or_else(Self::missing_default)?); + let format = [ + sources.release_channel, + sources.operating_system, + sources.user, + ] + .into_iter() + .find_map(|value| value.copied().flatten()) + .unwrap_or(sources.default.ok_or_else(Self::missing_default)?); Ok(format.0) } diff --git a/crates/settings/src/settings_store.rs b/crates/settings/src/settings_store.rs index bc42d2c886..fbc10f5860 100644 --- a/crates/settings/src/settings_store.rs +++ b/crates/settings/src/settings_store.rs @@ -16,6 +16,7 @@ use serde_json::{Value, json}; use smallvec::SmallVec; use std::{ any::{Any, TypeId, type_name}, + env, fmt::Debug, ops::Range, path::{Path, PathBuf}, @@ -126,6 +127,8 @@ pub struct SettingsSources<'a, T> { pub user: Option<&'a T>, /// The user settings for the current release channel. pub release_channel: Option<&'a T>, + /// The user settings for the current operating system. + pub operating_system: Option<&'a T>, /// The settings associated with an enabled settings profile pub profile: Option<&'a T>, /// The server's settings. @@ -147,6 +150,7 @@ impl<'a, T: Serialize> SettingsSources<'a, T> { .chain(self.extensions) .chain(self.user) .chain(self.release_channel) + .chain(self.operating_system) .chain(self.profile) .chain(self.server) .chain(self.project.iter().copied()) @@ -336,6 +340,11 @@ impl SettingsStore { .log_err(); } + let mut os_settings_value = None; + if let Some(os_settings) = &self.raw_user_settings.get(env::consts::OS) { + os_settings_value = setting_value.deserialize_setting(os_settings).log_err(); + } + let mut profile_value = None; if let Some(active_profile) = cx.try_global::() { if let Some(profiles) = self.raw_user_settings.get("profiles") { @@ -366,6 +375,7 @@ impl SettingsStore { extensions: extension_value.as_ref(), user: user_value.as_ref(), release_channel: release_channel_value.as_ref(), + operating_system: os_settings_value.as_ref(), profile: profile_value.as_ref(), server: server_value.as_ref(), project: &[], @@ -1092,7 +1102,7 @@ impl SettingsStore { "$schema": meta_schema, "title": "Zed Settings", "unevaluatedProperties": false, - // ZedSettings + settings overrides for each release stage / profiles + // ZedSettings + settings overrides for each release stage / OS / profiles "allOf": [ zed_settings_ref, { @@ -1101,6 +1111,9 @@ impl SettingsStore { "nightly": zed_settings_override_ref, "stable": zed_settings_override_ref, "preview": zed_settings_override_ref, + "linux": zed_settings_override_ref, + "macos": zed_settings_override_ref, + "windows": zed_settings_override_ref, "profiles": { "type": "object", "description": "Configures any number of settings profiles.", @@ -1164,6 +1177,13 @@ impl SettingsStore { } } + let mut os_settings = None; + if let Some(settings) = &self.raw_user_settings.get(env::consts::OS) { + if let Some(settings) = setting_value.deserialize_setting(settings).log_err() { + os_settings = Some(settings); + } + } + let mut profile_settings = None; if let Some(active_profile) = cx.try_global::() { if let Some(profiles) = self.raw_user_settings.get("profiles") { @@ -1183,7 +1203,8 @@ impl SettingsStore { global: global_settings.as_ref(), extensions: extension_settings.as_ref(), user: user_settings.as_ref(), - release_channel: release_channel_settings.as_ref(), + release_channel: os_settings.as_ref(), + operating_system: os_settings.as_ref(), profile: profile_settings.as_ref(), server: server_settings.as_ref(), project: &[], @@ -1237,6 +1258,7 @@ impl SettingsStore { extensions: extension_settings.as_ref(), user: user_settings.as_ref(), release_channel: release_channel_settings.as_ref(), + operating_system: os_settings.as_ref(), profile: profile_settings.as_ref(), server: server_settings.as_ref(), project: &project_settings_stack.iter().collect::>(), @@ -1363,6 +1385,9 @@ impl AnySettingValue for SettingValue { release_channel: values .release_channel .map(|value| value.0.downcast_ref::().unwrap()), + operating_system: values + .operating_system + .map(|value| value.0.downcast_ref::().unwrap()), profile: values .profile .map(|value| value.0.downcast_ref::().unwrap()), diff --git a/crates/theme/src/settings.rs b/crates/theme/src/settings.rs index 20c837f287..6d19494f40 100644 --- a/crates/theme/src/settings.rs +++ b/crates/theme/src/settings.rs @@ -867,6 +867,7 @@ impl settings::Settings for ThemeSettings { .user .into_iter() .chain(sources.release_channel) + .chain(sources.operating_system) .chain(sources.profile) .chain(sources.server) {