Settings refactor (#38367)

Co-Authored-By: Ben K <ben@zed.dev>
Co-Authored-By: Anthony <anthony@zed.dev>
Co-Authored-By: Mikayla <mikayla@zed.dev>

Release Notes:

- settings: Major internal changes to settings. The primary user-facing
effect is that some settings which did not make sense in project
settings files are no-longer read from there. (For example the inline
blame settings)

---------

Co-authored-by: Ben Kunkle <ben@zed.dev>
Co-authored-by: Mikayla Maki <mikayla.c.maki@gmail.com>
Co-authored-by: Anthony <anthony@zed.dev>
This commit is contained in:
Conrad Irwin
2025-09-18 16:47:23 +00:00
committed by GitHub
co-authored by Ben Kunkle Mikayla Maki Anthony
parent 0a9023bce0
commit fcdab160f9
219 changed files with 11697 additions and 11894 deletions
+57 -49
View File
@@ -31,7 +31,7 @@ use release_channel::{AppVersion, ReleaseChannel};
use rpc::proto::{AnyTypedEnvelope, EnvelopedMessage, PeerId, RequestMessage};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsKey, SettingsSources, SettingsUi};
use settings::{Settings, SettingsContent, SettingsKey, SettingsUi};
use std::{
any::TypeId,
convert::TryFrom,
@@ -50,7 +50,7 @@ use telemetry::Telemetry;
use thiserror::Error;
use tokio::net::TcpStream;
use url::Url;
use util::{ConnectionResult, ResultExt};
use util::{ConnectionResult, MergeFrom, ResultExt};
pub use rpc::*;
pub use telemetry_events::Event;
@@ -96,29 +96,33 @@ actions!(
]
);
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, SettingsUi, SettingsKey)]
#[settings_key(None)]
pub struct ClientSettingsContent {
server_url: Option<String>,
}
#[derive(Deserialize)]
pub struct ClientSettings {
pub server_url: String,
}
impl Settings for ClientSettings {
type FileContent = ClientSettingsContent;
fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
let mut result = sources.json_merge::<Self>()?;
fn from_defaults(content: &settings::SettingsContent, _cx: &mut App) -> Self {
if let Some(server_url) = &*ZED_SERVER_URL {
result.server_url.clone_from(server_url)
return Self {
server_url: server_url.clone(),
};
}
Self {
server_url: content.server_url.clone().unwrap(),
}
Ok(result)
}
fn import_from_vscode(_vscode: &settings::VsCodeSettings, _current: &mut Self::FileContent) {}
fn refine(&mut self, content: &settings::SettingsContent, _: &mut App) {
if ZED_SERVER_URL.is_some() {
return;
}
if let Some(server_url) = content.server_url.clone() {
self.server_url = server_url;
}
}
fn import_from_vscode(_vscode: &settings::VsCodeSettings, _current: &mut SettingsContent) {}
}
#[derive(Default, Clone, Serialize, Deserialize, JsonSchema, SettingsUi, SettingsKey)]
@@ -147,19 +151,19 @@ impl ProxySettings {
}
impl Settings for ProxySettings {
type FileContent = ProxySettingsContent;
fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
Ok(Self {
proxy: sources
.user
.or(sources.server)
.and_then(|value| value.proxy.clone())
.or(sources.default.proxy.clone()),
})
fn from_defaults(content: &settings::SettingsContent, _cx: &mut App) -> Self {
Self {
proxy: content.proxy.clone(),
}
}
fn import_from_vscode(vscode: &settings::VsCodeSettings, current: &mut Self::FileContent) {
fn refine(&mut self, content: &settings::SettingsContent, _: &mut App) {
if let Some(proxy) = content.proxy.clone() {
self.proxy = Some(proxy)
}
}
fn import_from_vscode(vscode: &settings::VsCodeSettings, current: &mut SettingsContent) {
vscode.string_setting("http.proxy", &mut current.proxy);
}
}
@@ -538,37 +542,41 @@ pub struct TelemetrySettings {
pub metrics: bool,
}
/// Control what info is collected by Zed.
#[derive(Default, Clone, Serialize, Deserialize, JsonSchema, Debug, SettingsUi, SettingsKey)]
#[settings_key(key = "telemetry")]
pub struct TelemetrySettingsContent {
/// Send debug info like crash reports.
///
/// Default: true
pub diagnostics: Option<bool>,
/// Send anonymized usage data like what languages you're using Zed with.
///
/// Default: true
pub metrics: Option<bool>,
}
impl settings::Settings for TelemetrySettings {
type FileContent = TelemetrySettingsContent;
fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
sources.json_merge()
fn from_defaults(content: &SettingsContent, _cx: &mut App) -> Self {
Self {
diagnostics: content.telemetry.as_ref().unwrap().diagnostics.unwrap(),
metrics: content.telemetry.as_ref().unwrap().metrics.unwrap(),
}
}
fn import_from_vscode(vscode: &settings::VsCodeSettings, current: &mut Self::FileContent) {
vscode.enum_setting("telemetry.telemetryLevel", &mut current.metrics, |s| {
fn refine(&mut self, content: &SettingsContent, _cx: &mut App) {
let Some(telemetry) = &content.telemetry else {
return;
};
self.diagnostics.merge_from(&telemetry.diagnostics);
self.metrics.merge_from(&telemetry.metrics);
}
fn import_from_vscode(vscode: &settings::VsCodeSettings, current: &mut SettingsContent) {
let mut telemetry = settings::TelemetrySettingsContent::default();
vscode.enum_setting("telemetry.telemetryLevel", &mut telemetry.metrics, |s| {
Some(s == "all")
});
vscode.enum_setting("telemetry.telemetryLevel", &mut current.diagnostics, |s| {
Some(matches!(s, "all" | "error" | "crash"))
});
vscode.enum_setting(
"telemetry.telemetryLevel",
&mut telemetry.diagnostics,
|s| Some(matches!(s, "all" | "error" | "crash")),
);
// we could translate telemetry.telemetryLevel, but just because users didn't want
// to send microsoft telemetry doesn't mean they don't want to send it to zed. their
// all/error/crash/off correspond to combinations of our "diagnostics" and "metrics".
if let Some(diagnostics) = telemetry.diagnostics {
current.telemetry.get_or_insert_default().diagnostics = Some(diagnostics)
}
if let Some(metrics) = telemetry.metrics {
current.telemetry.get_or_insert_default().metrics = Some(metrics)
}
}
}