## Context This PR introduces a `base` field for settings profiles to allow profiles to either overlay `user` settings or to overlay `default`, which is simply zed's defaults (user settings are skipped). I'm not entirely sure I love `default` because it's a bit confusing (there's a setting called `default` but the default is `user`). Another idea I had was `factory` (`user` (default) or `factory`) - curious to hear from the reviewers. This will be useful for those of us who need to quickly flip to a default state, or a default state with some customizations on top. Additionally, from what I can tell, VS Code's profile system is more in line with what this PR is offering in Zed - profiles overlay the default settings, not the user's customization layer. So this will be familiar for those users. I've had no issue with the migrator, code is pretty simple there, but would love for @smitbarmase to review the migration to make sure I'm not missing something. ## Self-Review Checklist <!-- Check before requesting review: --> - [X] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [ ] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [X] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - Improved the flexibility of settings profiles by offering a way for profiles to lay atop of zed defaults, skipping user settings all together. Settings Profiles now take the following form. ```json5 "Your Profile": { "base": "user" // or "default" "settings": { // ... }, }, ```
185 lines
5.1 KiB
Rust
185 lines
5.1 KiB
Rust
mod base_keymap_setting;
|
|
mod content_into_gpui;
|
|
mod editable_setting_control;
|
|
mod editorconfig_store;
|
|
mod keymap_file;
|
|
mod settings_file;
|
|
mod settings_store;
|
|
mod vscode_import;
|
|
|
|
pub use settings_macros::RegisterSetting;
|
|
|
|
pub mod settings_content {
|
|
pub use ::settings_content::*;
|
|
}
|
|
|
|
pub mod fallible_options {
|
|
pub use ::settings_content::{FallibleOption, parse_json};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
pub mod private {
|
|
pub use crate::settings_store::{RegisteredSetting, SettingValue};
|
|
pub use inventory;
|
|
}
|
|
|
|
use gpui::{App, Global};
|
|
|
|
use rust_embed::RustEmbed;
|
|
use std::env;
|
|
use std::{borrow::Cow, fmt, str};
|
|
use util::asset_str;
|
|
|
|
pub use ::settings_content::*;
|
|
pub use base_keymap_setting::*;
|
|
pub use content_into_gpui::IntoGpui;
|
|
pub use editable_setting_control::*;
|
|
pub use editorconfig_store::{
|
|
Editorconfig, EditorconfigEvent, EditorconfigProperties, EditorconfigStore,
|
|
};
|
|
pub use keymap_file::{
|
|
KeyBindingValidator, KeyBindingValidatorRegistration, KeybindSource, KeybindUpdateOperation,
|
|
KeybindUpdateTarget, KeymapFile, KeymapFileLoadResult,
|
|
};
|
|
pub use settings_file::*;
|
|
pub use settings_json::*;
|
|
pub use settings_store::{
|
|
DefaultSemanticTokenRules, InvalidSettingsError, LSP_SETTINGS_SCHEMA_URL_PREFIX,
|
|
LocalSettingsKind, LocalSettingsPath, MigrationStatus, Settings, SettingsFile,
|
|
SettingsJsonSchemaParams, SettingsKey, SettingsLocation, SettingsParseResult, SettingsStore,
|
|
};
|
|
|
|
pub use vscode_import::{VsCodeSettings, VsCodeSettingsSource};
|
|
|
|
pub use keymap_file::ActionSequence;
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
pub struct ActiveSettingsProfileName(pub String);
|
|
|
|
impl Global for ActiveSettingsProfileName {}
|
|
|
|
pub trait UserSettingsContentExt {
|
|
fn for_profile(&self, cx: &App) -> Option<&SettingsProfile>;
|
|
fn for_release_channel(&self) -> Option<&SettingsContent>;
|
|
fn for_os(&self) -> Option<&SettingsContent>;
|
|
}
|
|
|
|
impl UserSettingsContentExt for UserSettingsContent {
|
|
fn for_profile(&self, cx: &App) -> Option<&SettingsProfile> {
|
|
let Some(active_profile) = cx.try_global::<ActiveSettingsProfileName>() else {
|
|
return None;
|
|
};
|
|
self.profiles.get(&active_profile.0)
|
|
}
|
|
|
|
fn for_release_channel(&self) -> Option<&SettingsContent> {
|
|
self.release_channel_overrides
|
|
.get_by_key(release_channel::RELEASE_CHANNEL.dev_name())
|
|
}
|
|
|
|
fn for_os(&self) -> Option<&SettingsContent> {
|
|
self.platform_overrides.get_by_key(env::consts::OS)
|
|
}
|
|
}
|
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, PartialOrd, Ord, serde::Serialize)]
|
|
pub struct WorktreeId(usize);
|
|
|
|
impl From<WorktreeId> for usize {
|
|
fn from(value: WorktreeId) -> Self {
|
|
value.0
|
|
}
|
|
}
|
|
|
|
impl WorktreeId {
|
|
pub fn from_usize(handle_id: usize) -> Self {
|
|
Self(handle_id)
|
|
}
|
|
|
|
pub fn from_proto(id: u64) -> Self {
|
|
Self(id as usize)
|
|
}
|
|
|
|
pub fn to_proto(self) -> u64 {
|
|
self.0 as u64
|
|
}
|
|
|
|
pub fn to_usize(self) -> usize {
|
|
self.0
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for WorktreeId {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
std::fmt::Display::fmt(&self.0, f)
|
|
}
|
|
}
|
|
|
|
#[derive(RustEmbed)]
|
|
#[folder = "../../assets"]
|
|
#[include = "settings/*"]
|
|
#[include = "keymaps/*"]
|
|
#[exclude = "*.DS_Store"]
|
|
pub struct SettingsAssets;
|
|
|
|
pub fn init(cx: &mut App) {
|
|
let settings = SettingsStore::new(cx, &default_settings());
|
|
cx.set_global(settings);
|
|
SettingsStore::observe_active_settings_profile_name(cx).detach();
|
|
}
|
|
|
|
pub fn default_settings() -> Cow<'static, str> {
|
|
asset_str::<SettingsAssets>("settings/default.json")
|
|
}
|
|
|
|
pub fn default_semantic_token_rules() -> Cow<'static, str> {
|
|
asset_str::<SettingsAssets>("settings/default_semantic_token_rules.json")
|
|
}
|
|
|
|
#[cfg(target_os = "macos")]
|
|
pub const DEFAULT_KEYMAP_PATH: &str = "keymaps/default-macos.json";
|
|
|
|
#[cfg(target_os = "windows")]
|
|
pub const DEFAULT_KEYMAP_PATH: &str = "keymaps/default-windows.json";
|
|
|
|
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
|
|
pub const DEFAULT_KEYMAP_PATH: &str = "keymaps/default-linux.json";
|
|
|
|
pub fn default_keymap() -> Cow<'static, str> {
|
|
asset_str::<SettingsAssets>(DEFAULT_KEYMAP_PATH)
|
|
}
|
|
|
|
pub const VIM_KEYMAP_PATH: &str = "keymaps/vim.json";
|
|
|
|
pub fn vim_keymap() -> Cow<'static, str> {
|
|
asset_str::<SettingsAssets>(VIM_KEYMAP_PATH)
|
|
}
|
|
|
|
pub fn initial_user_settings_content() -> Cow<'static, str> {
|
|
asset_str::<SettingsAssets>("settings/initial_user_settings.json")
|
|
}
|
|
|
|
pub fn initial_server_settings_content() -> Cow<'static, str> {
|
|
asset_str::<SettingsAssets>("settings/initial_server_settings.json")
|
|
}
|
|
|
|
pub fn initial_project_settings_content() -> Cow<'static, str> {
|
|
asset_str::<SettingsAssets>("settings/initial_local_settings.json")
|
|
}
|
|
|
|
pub fn initial_keymap_content() -> Cow<'static, str> {
|
|
asset_str::<SettingsAssets>("keymaps/initial.json")
|
|
}
|
|
|
|
pub fn initial_tasks_content() -> Cow<'static, str> {
|
|
asset_str::<SettingsAssets>("settings/initial_tasks.json")
|
|
}
|
|
|
|
pub fn initial_debug_tasks_content() -> Cow<'static, str> {
|
|
asset_str::<SettingsAssets>("settings/initial_debug_tasks.json")
|
|
}
|
|
|
|
pub fn initial_local_debug_tasks_content() -> Cow<'static, str> {
|
|
asset_str::<SettingsAssets>("settings/initial_local_debug_tasks.json")
|
|
}
|