diff --git a/Cargo.lock b/Cargo.lock index c8ddeebb26a9ec2787b835996451a6fac11d659d..8df6dd15d3c0a695c2f6b16155fad7d900b79155 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -678,7 +678,7 @@ dependencies = [ "serde", "serde_json", "settings", - "strum 0.27.1", + "strum 0.27.2", "thiserror 2.0.12", "workspace-hack", ] @@ -2198,7 +2198,7 @@ dependencies = [ "schemars 1.0.1", "serde", "serde_json", - "strum 0.27.1", + "strum 0.27.2", "thiserror 2.0.12", "workspace-hack", ] @@ -3388,7 +3388,7 @@ dependencies = [ "pretty_assertions", "serde", "serde_json", - "strum 0.27.1", + "strum 0.27.2", "uuid", "workspace-hack", ] @@ -3403,7 +3403,7 @@ dependencies = [ "ordered-float 2.10.1", "rustc-hash 2.1.1", "serde", - "strum 0.27.1", + "strum 0.27.2", "workspace-hack", ] @@ -3598,7 +3598,7 @@ dependencies = [ "sha2", "smol", "sqlx", - "strum 0.27.1", + "strum 0.27.2", "subtle", "supermaven_api", "task", @@ -3783,7 +3783,7 @@ dependencies = [ "gpui", "inventory", "parking_lot", - "strum 0.27.1", + "strum 0.27.2", "theme", "workspace-hack", ] @@ -5462,7 +5462,7 @@ dependencies = [ "serde_json", "settings", "slotmap", - "strum 0.27.1", + "strum 0.27.2", "text", "tree-sitter", "tree-sitter-c", @@ -6074,7 +6074,7 @@ dependencies = [ "serde", "settings", "smallvec", - "strum 0.27.1", + "strum 0.27.2", "telemetry", "theme", "ui", @@ -7195,7 +7195,7 @@ dependencies = [ "serde", "serde_json", "settings", - "strum 0.27.1", + "strum 0.27.2", "telemetry", "theme", "time", @@ -7301,7 +7301,7 @@ dependencies = [ "serde", "serde_json", "settings", - "strum 0.27.1", + "strum 0.27.2", "workspace-hack", ] @@ -7408,7 +7408,7 @@ dependencies = [ "smallvec", "smol", "stacksafe", - "strum 0.27.1", + "strum 0.27.2", "sum_tree", "taffy", "thiserror 2.0.12", @@ -8059,7 +8059,7 @@ name = "icons" version = "0.1.0" dependencies = [ "serde", - "strum 0.27.1", + "strum 0.27.2", "workspace-hack", ] @@ -9041,7 +9041,7 @@ dependencies = [ "serde_json", "settings", "smol", - "strum 0.27.1", + "strum 0.27.2", "thiserror 2.0.12", "tiktoken-rs", "tokio", @@ -10192,7 +10192,7 @@ dependencies = [ "schemars 1.0.1", "serde", "serde_json", - "strum 0.27.1", + "strum 0.27.2", "workspace-hack", ] @@ -11109,7 +11109,7 @@ dependencies = [ "serde", "serde_json", "settings", - "strum 0.27.1", + "strum 0.27.2", "workspace-hack", ] @@ -11124,7 +11124,7 @@ dependencies = [ "serde", "serde_json", "settings", - "strum 0.27.1", + "strum 0.27.2", "thiserror 2.0.12", "workspace-hack", ] @@ -14418,7 +14418,7 @@ dependencies = [ "serde", "serde_json", "sha2", - "strum 0.27.1", + "strum 0.27.2", "tracing", "util", "workspace-hack", @@ -15427,7 +15427,7 @@ dependencies = [ "serde_with", "settings_macros", "smallvec", - "strum 0.27.1", + "strum 0.27.2", "tree-sitter", "tree-sitter-json", "unindent", @@ -15494,7 +15494,7 @@ dependencies = [ "serde", "session", "settings", - "strum 0.27.1", + "strum 0.27.2", "theme", "title_bar", "ui", @@ -16253,7 +16253,7 @@ dependencies = [ "settings", "simplelog", "story", - "strum 0.27.1", + "strum 0.27.2", "theme", "title_bar", "ui", @@ -16355,9 +16355,9 @@ dependencies = [ [[package]] name = "strum" -version = "0.27.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" dependencies = [ "strum_macros 0.27.1", ] @@ -17232,7 +17232,7 @@ dependencies = [ "serde_json", "serde_json_lenient", "settings", - "strum 0.27.1", + "strum 0.27.2", "thiserror 2.0.12", "util", "uuid", @@ -17266,7 +17266,7 @@ dependencies = [ "serde_json", "serde_json_lenient", "simplelog", - "strum 0.27.1", + "strum 0.27.2", "theme", "vscode_theme", "workspace-hack", @@ -18330,7 +18330,7 @@ dependencies = [ "settings", "smallvec", "story", - "strum 0.27.1", + "strum 0.27.2", "theme", "ui_macros", "util", @@ -18714,7 +18714,7 @@ dependencies = [ "anyhow", "schemars 1.0.1", "serde", - "strum 0.27.1", + "strum 0.27.2", "workspace-hack", ] @@ -20655,7 +20655,7 @@ dependencies = [ "settings", "smallvec", "sqlez", - "strum 0.27.1", + "strum 0.27.2", "task", "telemetry", "tempfile", @@ -20980,7 +20980,7 @@ dependencies = [ "anyhow", "schemars 1.0.1", "serde", - "strum 0.27.1", + "strum 0.27.2", "workspace-hack", ] @@ -21751,7 +21751,7 @@ dependencies = [ "serde", "serde_json", "settings", - "strum 0.27.1", + "strum 0.27.2", "telemetry", "telemetry_events", "theme", diff --git a/Cargo.toml b/Cargo.toml index 5482e20a1b2230b3c10ba043a2bf5c71d9a4cc25..3bc4123a0967a1f3bdc5d4d48d37ffedfbf372ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -651,7 +651,7 @@ sqlformat = "0.2" stacksafe = "0.1" streaming-iterator = "0.1" strsim = "0.11" -strum = { version = "0.27.0", features = ["derive"] } +strum = { version = "0.27.2", features = ["derive"] } subtle = "2.5.0" syn = { version = "2.0.101", features = ["full", "extra-traits", "visit-mut"] } sys-locale = "0.3.1" diff --git a/crates/settings/src/settings_content/theme.rs b/crates/settings/src/settings_content/theme.rs index 67cfff6da1051247b2f462c96febd0f09c882963..45640ae3ae37321498bb3dafd6d07b2ba1f2d92e 100644 --- a/crates/settings/src/settings_content/theme.rs +++ b/crates/settings/src/settings_content/theme.rs @@ -125,7 +125,18 @@ fn default_buffer_font_weight() -> Option { } /// Represents the selection of a theme, which can be either static or dynamic. -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq)] +#[derive( + Clone, + Debug, + Serialize, + Deserialize, + JsonSchema, + MergeFrom, + PartialEq, + Eq, + strum::EnumDiscriminants, +)] +#[strum_discriminants(derive(strum::VariantArray, strum::VariantNames, strum::FromRepr))] #[serde(untagged)] pub enum ThemeSelection { /// A static theme selection, represented by a single theme name. @@ -167,7 +178,18 @@ pub enum IconThemeSelection { /// /// `System` will select the theme based on the system's appearance. #[derive( - Debug, PartialEq, Eq, Clone, Copy, Default, Serialize, Deserialize, JsonSchema, MergeFrom, + Debug, + PartialEq, + Eq, + Clone, + Copy, + Default, + Serialize, + Deserialize, + JsonSchema, + MergeFrom, + strum::VariantArray, + strum::VariantNames, )] #[serde(rename_all = "snake_case")] pub enum ThemeMode { diff --git a/crates/settings/src/settings_store.rs b/crates/settings/src/settings_store.rs index 4731c38379f787b497354c3066f8f5eecb1332ca..559ed777c7aa86047f6acb33c8b358e0bd7b6e58 100644 --- a/crates/settings/src/settings_store.rs +++ b/crates/settings/src/settings_store.rs @@ -535,30 +535,30 @@ impl SettingsStore { /// Returns the first file found that contains the value. /// The value will only be None if no file contains the value. /// I.e. if no file contains the value, returns `(File::Default, None)` - pub fn get_value_from_file( - &self, + pub fn get_value_from_file<'a, T: 'a>( + &'a self, target_file: SettingsFile, - pick: fn(&SettingsContent) -> &Option, - ) -> (SettingsFile, Option<&T>) { + pick: fn(&'a SettingsContent) -> Option, + ) -> (SettingsFile, Option) { self.get_value_from_file_inner(target_file, pick, true) } /// Same as `Self::get_value_from_file` except that it does not include the current file. /// Therefore it returns the value that was potentially overloaded by the target file. - pub fn get_value_up_to_file( - &self, + pub fn get_value_up_to_file<'a, T: 'a>( + &'a self, target_file: SettingsFile, - pick: fn(&SettingsContent) -> &Option, - ) -> (SettingsFile, Option<&T>) { + pick: fn(&'a SettingsContent) -> Option, + ) -> (SettingsFile, Option) { self.get_value_from_file_inner(target_file, pick, false) } - fn get_value_from_file_inner( - &self, + fn get_value_from_file_inner<'a, T: 'a>( + &'a self, target_file: SettingsFile, - pick: fn(&SettingsContent) -> &Option, + pick: fn(&'a SettingsContent) -> Option, include_target_file: bool, - ) -> (SettingsFile, Option<&T>) { + ) -> (SettingsFile, Option) { // todo(settings_ui): Add a metadata field for overriding the "overrides" tag, for contextually different settings // e.g. disable AI isn't overridden, or a vec that gets extended instead or some such @@ -588,7 +588,7 @@ impl SettingsStore { let Some(content) = self.get_content_for_file(file.clone()) else { continue; }; - if let Some(value) = pick(content).as_ref() { + if let Some(value) = pick(content) { return (file, Some(value)); } } @@ -1774,11 +1774,16 @@ mod tests { ) .unwrap(); - fn get(content: &SettingsContent) -> &Option { - &content.project.all_languages.defaults.preferred_line_length + fn get(content: &SettingsContent) -> Option<&u32> { + content + .project + .all_languages + .defaults + .preferred_line_length + .as_ref() } - let default_value = get(&store.default_settings).unwrap(); + let default_value = *get(&store.default_settings).unwrap(); assert_eq!( store.get_value_from_file(SettingsFile::Project(local.clone()), get), @@ -1841,8 +1846,13 @@ mod tests { .into_arc(), ); - fn get(content: &SettingsContent) -> &Option { - &content.project.all_languages.defaults.preferred_line_length + fn get(content: &SettingsContent) -> Option<&u32> { + content + .project + .all_languages + .defaults + .preferred_line_length + .as_ref() } store diff --git a/crates/settings_ui/src/page_data.rs b/crates/settings_ui/src/page_data.rs index b54231580f269e9313eadceddacd2177d9f85fa7..26447445f99145afc1f9103726e9e99d87e8aca0 100644 --- a/crates/settings_ui/src/page_data.rs +++ b/crates/settings_ui/src/page_data.rs @@ -1,11 +1,12 @@ use gpui::App; use settings::{LanguageSettingsContent, SettingsContent}; use std::sync::Arc; +use strum::IntoDiscriminant as _; use ui::{IntoElement, SharedString}; use crate::{ - LOCAL, SettingField, SettingItem, SettingsFieldMetadata, SettingsPage, SettingsPageItem, - SubPageLink, USER, all_language_names, sub_page_stack, + DynamicItem, LOCAL, SettingField, SettingItem, SettingsFieldMetadata, SettingsPage, + SettingsPageItem, SubPageLink, USER, all_language_names, sub_page_stack, }; pub(crate) fn settings_data(cx: &App) -> Vec { @@ -18,8 +19,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Confirm Quit", description: "Confirm before quitting Zed", field: Box::new(SettingField { - pick: |settings_content| &settings_content.workspace.confirm_quit, - pick_mut: |settings_content| &mut settings_content.workspace.confirm_quit, + pick: |settings_content| settings_content.workspace.confirm_quit.as_ref(), + write: |settings_content, value| { + settings_content.workspace.confirm_quit = value; + }, }), metadata: None, files: USER, @@ -29,10 +32,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "What to do when using the 'close active item' action with no tabs", field: Box::new(SettingField { pick: |settings_content| { - &settings_content.workspace.when_closing_with_no_tabs + settings_content + .workspace + .when_closing_with_no_tabs + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.workspace.when_closing_with_no_tabs + write: |settings_content, value| { + settings_content.workspace.when_closing_with_no_tabs = value; }, }), metadata: None, @@ -42,9 +48,11 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "On Last Window Closed", description: "What to do when the last window is closed", field: Box::new(SettingField { - pick: |settings_content| &settings_content.workspace.on_last_window_closed, - pick_mut: |settings_content| { - &mut settings_content.workspace.on_last_window_closed + pick: |settings_content| { + settings_content.workspace.on_last_window_closed.as_ref() + }, + write: |settings_content, value| { + settings_content.workspace.on_last_window_closed = value; }, }), metadata: None, @@ -55,10 +63,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Use native OS dialogs for 'Open' and 'Save As'", field: Box::new(SettingField { pick: |settings_content| { - &settings_content.workspace.use_system_path_prompts + settings_content.workspace.use_system_path_prompts.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.workspace.use_system_path_prompts + write: |settings_content, value| { + settings_content.workspace.use_system_path_prompts = value; }, }), metadata: None, @@ -68,9 +76,11 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Use System Prompts", description: "Use native OS dialogs for confirmations", field: Box::new(SettingField { - pick: |settings_content| &settings_content.workspace.use_system_prompts, - pick_mut: |settings_content| { - &mut settings_content.workspace.use_system_prompts + pick: |settings_content| { + settings_content.workspace.use_system_prompts.as_ref() + }, + write: |settings_content, value| { + settings_content.workspace.use_system_prompts = value; }, }), metadata: None, @@ -80,9 +90,11 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Redact Private Values", description: "Hide the values of variables in private files", field: Box::new(SettingField { - pick: |settings_content| &settings_content.editor.redact_private_values, - pick_mut: |settings_content| { - &mut settings_content.editor.redact_private_values + pick: |settings_content| { + settings_content.editor.redact_private_values.as_ref() + }, + write: |settings_content, value| { + settings_content.editor.redact_private_values = value; }, }), metadata: None, @@ -94,10 +106,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { field: Box::new( SettingField { pick: |settings_content| { - &settings_content.project.worktree.private_files + settings_content.project.worktree.private_files.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.project.worktree.private_files + write: |settings_content, value| { + settings_content.project.worktree.private_files = value; }, } .unimplemented(), @@ -110,15 +122,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Restore Unsaved Buffers", description: "Whether or not to restore unsaved buffers on restart", field: Box::new(SettingField { - pick: |settings_content| match settings_content.session.as_ref() { - Some(session) => &session.restore_unsaved_buffers, - None => &None, + pick: |settings_content| { + settings_content + .session + .as_ref() + .and_then(|session| session.restore_unsaved_buffers.as_ref()) }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .session .get_or_insert_default() - .restore_unsaved_buffers + .restore_unsaved_buffers = value; }, }), metadata: None, @@ -128,9 +142,11 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Restore On Startup", description: "What to restore from the previous session when opening Zed", field: Box::new(SettingField { - pick: |settings_content| &settings_content.workspace.restore_on_startup, - pick_mut: |settings_content| { - &mut settings_content.workspace.restore_on_startup + pick: |settings_content| { + settings_content.workspace.restore_on_startup.as_ref() + }, + write: |settings_content, value| { + settings_content.workspace.restore_on_startup = value; }, }), metadata: None, @@ -144,9 +160,11 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Which settings should be activated only in Preview build of Zed", field: Box::new( SettingField { - pick: |settings_content| &settings_content.workspace.use_system_prompts, - pick_mut: |settings_content| { - &mut settings_content.workspace.use_system_prompts + pick: |settings_content| { + settings_content.workspace.use_system_prompts.as_ref() + }, + write: |settings_content, value| { + settings_content.workspace.use_system_prompts = value; }, } .unimplemented(), @@ -159,9 +177,11 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Any number of settings profiles that are temporarily applied on top of your existing user settings", field: Box::new( SettingField { - pick: |settings_content| &settings_content.workspace.use_system_prompts, - pick_mut: |settings_content| { - &mut settings_content.workspace.use_system_prompts + pick: |settings_content| { + settings_content.workspace.use_system_prompts.as_ref() + }, + write: |settings_content, value| { + settings_content.workspace.use_system_prompts = value; }, } .unimplemented(), @@ -174,17 +194,16 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Send debug information like crash reports", field: Box::new(SettingField { pick: |settings_content| { - if let Some(telemetry) = &settings_content.telemetry { - &telemetry.diagnostics - } else { - &None - } + settings_content + .telemetry + .as_ref() + .and_then(|telemetry| telemetry.diagnostics.as_ref()) }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .telemetry .get_or_insert_default() - .diagnostics + .diagnostics = value; }, }), metadata: None, @@ -195,14 +214,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Send anonymized usage data like what languages you're using Zed with", field: Box::new(SettingField { pick: |settings_content| { - if let Some(telemetry) = &settings_content.telemetry { - &telemetry.metrics - } else { - &None - } + settings_content + .telemetry + .as_ref() + .and_then(|telemetry| telemetry.metrics.as_ref()) }, - pick_mut: |settings_content| { - &mut settings_content.telemetry.get_or_insert_default().metrics + write: |settings_content, value| { + settings_content.telemetry.get_or_insert_default().metrics = value; }, }), metadata: None, @@ -213,8 +231,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Auto Update", description: "Whether or not to automatically check for updates", field: Box::new(SettingField { - pick: |settings_content| &settings_content.auto_update, - pick_mut: |settings_content| &mut settings_content.auto_update, + pick: |settings_content| settings_content.auto_update.as_ref(), + write: |settings_content, value| { + settings_content.auto_update = value; + }, }), metadata: None, files: USER, @@ -225,19 +245,167 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Appearance", items: vec![ SettingsPageItem::SectionHeader("Theme"), - // todo(settings_ui): Figure out how we want to add these - SettingsPageItem::SettingItem(SettingItem { - files: USER, - title: "Theme Mode", - description: "How to select the theme", - field: Box::new( - SettingField { - pick: |settings_content| &settings_content.theme.theme, - pick_mut: |settings_content| &mut settings_content.theme.theme, + SettingsPageItem::DynamicItem(DynamicItem { + discriminant: SettingItem { + files: USER, + title: "Theme Mode", + description: "How to select the theme", + field: Box::new(SettingField { + pick: |settings_content| { + Some(&<::Discriminant as strum::VariantArray>::VARIANTS[ + settings_content + .theme + .theme + .as_ref()? + .discriminant() as usize]) + }, + write: |settings_content, value| { + let Some(value) = value else { + return; + }; + let settings_value = settings_content.theme.theme.as_mut().expect("Has Default"); + *settings_value = match value { + settings::ThemeSelectionDiscriminants::Static => { + let name = match settings_value { + settings::ThemeSelection::Static(_) => return, + settings::ThemeSelection::Dynamic { mode, light, dark } => { + match mode { + theme::ThemeMode::Light => light.clone(), + theme::ThemeMode::Dark => dark.clone(), + theme::ThemeMode::System => dark.clone(), // no cx, can't determine correct choice + } + }, + }; + settings::ThemeSelection::Static(name) + }, + settings::ThemeSelectionDiscriminants::Dynamic => { + let static_name = match settings_value { + settings::ThemeSelection::Static(theme_name) => theme_name.clone(), + settings::ThemeSelection::Dynamic {..} => return, + }; + + settings::ThemeSelection::Dynamic { + mode: settings::ThemeMode::System, + light: static_name.clone(), + dark: static_name, + } + }, + }; + }, + }), + metadata: None, + }, + pick_discriminant: |settings_content| { + Some(settings_content.theme.theme.as_ref()?.discriminant() as usize) + }, + fields: <::Discriminant as strum::VariantArray>::VARIANTS.into_iter().map(|variant| { + match variant { + settings::ThemeSelectionDiscriminants::Static => vec![ + SettingItem { + files: USER, + title: "Theme Name", + description: "The Name Of The Theme To Use", + field: Box::new(SettingField { + pick: |settings_content| { + match settings_content.theme.theme.as_ref() { + Some(settings::ThemeSelection::Static(name)) => Some(name), + _ => None + } + }, + write: |settings_content, value| { + let Some(value) = value else { + return; + }; + match settings_content + .theme + .theme.as_mut() { + Some(settings::ThemeSelection::Static(theme_name)) => *theme_name = value, + _ => return + } + }, + }), + metadata: None, + } + ], + settings::ThemeSelectionDiscriminants::Dynamic => vec![ + SettingItem { + files: USER, + title: "Mode", + description: "How To Determine Whether to Use a Light or Dark Theme", + field: Box::new(SettingField { + pick: |settings_content| { + match settings_content.theme.theme.as_ref() { + Some(settings::ThemeSelection::Dynamic { mode, ..}) => Some(mode), + _ => None + } + }, + write: |settings_content, value| { + let Some(value) = value else { + return; + }; + match settings_content + .theme + .theme.as_mut() { + Some(settings::ThemeSelection::Dynamic{ mode, ..}) => *mode = value, + _ => return + } + }, + }), + metadata: None, + }, + SettingItem { + files: USER, + title: "Light Theme", + description: "The Theme To Use When Mode Is Set To Light, Or When Mode Is Set To System And The System Is In Light Mode", + field: Box::new(SettingField { + pick: |settings_content| { + match settings_content.theme.theme.as_ref() { + Some(settings::ThemeSelection::Dynamic { light, ..}) => Some(light), + _ => None + } + }, + write: |settings_content, value| { + let Some(value) = value else { + return; + }; + match settings_content + .theme + .theme.as_mut() { + Some(settings::ThemeSelection::Dynamic{ light, ..}) => *light = value, + _ => return + } + }, + }), + metadata: None, + }, + SettingItem { + files: USER, + title: "Dark Theme", + description: "The Theme To Use When Mode Is Set To Dark, Or When Mode Is Set To System And The System Is In Dark Mode", + field: Box::new(SettingField { + pick: |settings_content| { + match settings_content.theme.theme.as_ref() { + Some(settings::ThemeSelection::Dynamic { dark, ..}) => Some(dark), + _ => None + } + }, + write: |settings_content, value| { + let Some(value) = value else { + return; + }; + match settings_content + .theme + .theme.as_mut() { + Some(settings::ThemeSelection::Dynamic{ dark, ..}) => *dark = value, + _ => return + } + }, + }), + metadata: None, + } + ], } - .unimplemented(), - ), - metadata: None, + }).collect(), }), SettingsPageItem::SettingItem(SettingItem { files: USER, @@ -247,8 +415,8 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Choose the icon theme for file explorer", field: Box::new( SettingField { - pick: |settings_content| &settings_content.theme.icon_theme, - pick_mut: |settings_content| &mut settings_content.theme.icon_theme, + pick: |settings_content| settings_content.theme.icon_theme.as_ref(), + write: |settings_content, value|{ settings_content.theme.icon_theme = value;}, } .unimplemented(), ), @@ -259,8 +427,8 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Font Family", description: "Font family for editor text", field: Box::new(SettingField { - pick: |settings_content| &settings_content.theme.buffer_font_family, - pick_mut: |settings_content| &mut settings_content.theme.buffer_font_family, + pick: |settings_content| settings_content.theme.buffer_font_family.as_ref(), + write: |settings_content, value|{ settings_content.theme.buffer_font_family = value;}, }), metadata: None, files: USER, @@ -269,8 +437,8 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Font Size", description: "Font size for editor text", field: Box::new(SettingField { - pick: |settings_content| &settings_content.theme.buffer_font_size, - pick_mut: |settings_content| &mut settings_content.theme.buffer_font_size, + pick: |settings_content| settings_content.theme.buffer_font_size.as_ref(), + write: |settings_content, value|{ settings_content.theme.buffer_font_size = value;}, }), metadata: None, files: USER, @@ -279,8 +447,8 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Font Weight", description: "Font weight for editor text (100-900)", field: Box::new(SettingField { - pick: |settings_content| &settings_content.theme.buffer_font_weight, - pick_mut: |settings_content| &mut settings_content.theme.buffer_font_weight, + pick: |settings_content| settings_content.theme.buffer_font_weight.as_ref(), + write: |settings_content, value|{ settings_content.theme.buffer_font_weight = value;}, }), metadata: None, files: USER, @@ -292,9 +460,12 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Line height for editor text", field: Box::new( SettingField { - pick: |settings_content| &settings_content.theme.buffer_line_height, - pick_mut: |settings_content| { - &mut settings_content.theme.buffer_line_height + pick: |settings_content| { + settings_content.theme.buffer_line_height.as_ref() + }, + write: |settings_content, value| { + settings_content.theme.buffer_line_height = value; + }, } .unimplemented(), @@ -307,9 +478,12 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "The OpenType features to enable for rendering in text buffers.", field: Box::new( SettingField { - pick: |settings_content| &settings_content.theme.buffer_font_features, - pick_mut: |settings_content| { - &mut settings_content.theme.buffer_font_features + pick: |settings_content| { + settings_content.theme.buffer_font_features.as_ref() + }, + write: |settings_content, value| { + settings_content.theme.buffer_font_features = value; + }, } .unimplemented(), @@ -322,9 +496,12 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "The font fallbacks to use for rendering in text buffers.", field: Box::new( SettingField { - pick: |settings_content| &settings_content.theme.buffer_font_fallbacks, - pick_mut: |settings_content| { - &mut settings_content.theme.buffer_font_fallbacks + pick: |settings_content| { + settings_content.theme.buffer_font_fallbacks.as_ref() + }, + write: |settings_content, value| { + settings_content.theme.buffer_font_fallbacks = value; + }, } .unimplemented(), @@ -336,8 +513,8 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Font Family", description: "Font family for UI elements", field: Box::new(SettingField { - pick: |settings_content| &settings_content.theme.ui_font_family, - pick_mut: |settings_content| &mut settings_content.theme.ui_font_family, + pick: |settings_content| settings_content.theme.ui_font_family.as_ref(), + write: |settings_content, value|{ settings_content.theme.ui_font_family = value;}, }), metadata: None, files: USER, @@ -346,8 +523,8 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Font Size", description: "Font size for UI elements", field: Box::new(SettingField { - pick: |settings_content| &settings_content.theme.ui_font_size, - pick_mut: |settings_content| &mut settings_content.theme.ui_font_size, + pick: |settings_content| settings_content.theme.ui_font_size.as_ref(), + write: |settings_content, value|{ settings_content.theme.ui_font_size = value;}, }), metadata: None, files: USER, @@ -356,8 +533,8 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Font Weight", description: "Font weight for UI elements (100-900)", field: Box::new(SettingField { - pick: |settings_content| &settings_content.theme.ui_font_weight, - pick_mut: |settings_content| &mut settings_content.theme.ui_font_weight, + pick: |settings_content| settings_content.theme.ui_font_weight.as_ref(), + write: |settings_content, value|{ settings_content.theme.ui_font_weight = value;}, }), metadata: None, files: USER, @@ -368,9 +545,12 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "The OpenType features to enable for rendering in UI elements.", field: Box::new( SettingField { - pick: |settings_content| &settings_content.theme.ui_font_features, - pick_mut: |settings_content| { - &mut settings_content.theme.ui_font_features + pick: |settings_content| { + settings_content.theme.ui_font_features.as_ref() + }, + write: |settings_content, value| { + settings_content.theme.ui_font_features = value; + }, } .unimplemented(), @@ -383,9 +563,12 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "The font fallbacks to use for rendering in the UI.", field: Box::new( SettingField { - pick: |settings_content| &settings_content.theme.ui_font_fallbacks, - pick_mut: |settings_content| { - &mut settings_content.theme.ui_font_fallbacks + pick: |settings_content| { + settings_content.theme.ui_font_fallbacks.as_ref() + }, + write: |settings_content, value| { + settings_content.theme.ui_font_fallbacks = value; + }, } .unimplemented(), @@ -398,13 +581,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Font size for agent response text in the agent panel. Falls back to the regular UI font size.", field: Box::new(SettingField { pick: |settings_content| { - if settings_content.theme.agent_ui_font_size.is_some() { - &settings_content.theme.agent_ui_font_size - } else { - &settings_content.theme.ui_font_size - } + settings_content + .theme + .agent_ui_font_size + .as_ref() + .or(settings_content.theme.ui_font_size.as_ref()) }, - pick_mut: |settings_content| &mut settings_content.theme.agent_ui_font_size, + write: |settings_content, value|{ settings_content.theme.agent_ui_font_size = value;}, }), metadata: None, files: USER, @@ -413,9 +596,16 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Buffer Font Size", description: "Font size for user messages text in the agent panel", field: Box::new(SettingField { - pick: |settings_content| &settings_content.theme.agent_buffer_font_size, - pick_mut: |settings_content| { - &mut settings_content.theme.agent_buffer_font_size + pick: |settings_content| { + settings_content + .theme + .agent_buffer_font_size + .as_ref() + .or(settings_content.theme.buffer_font_size.as_ref()) + }, + write: |settings_content, value| { + settings_content.theme.agent_buffer_font_size = value; + }, }), metadata: None, @@ -426,9 +616,12 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Multi Cursor Modifier", description: "Modifier key for adding multiple cursors", field: Box::new(SettingField { - pick: |settings_content| &settings_content.editor.multi_cursor_modifier, - pick_mut: |settings_content| { - &mut settings_content.editor.multi_cursor_modifier + pick: |settings_content| { + settings_content.editor.multi_cursor_modifier.as_ref() + }, + write: |settings_content, value| { + settings_content.editor.multi_cursor_modifier = value; + }, }), metadata: None, @@ -438,8 +631,8 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Cursor Blink", description: "Whether the cursor blinks in the editor", field: Box::new(SettingField { - pick: |settings_content| &settings_content.editor.cursor_blink, - pick_mut: |settings_content| &mut settings_content.editor.cursor_blink, + pick: |settings_content| settings_content.editor.cursor_blink.as_ref(), + write: |settings_content, value|{ settings_content.editor.cursor_blink = value;}, }), metadata: None, files: USER, @@ -448,8 +641,8 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Cursor Shape", description: "Cursor shape for the editor", field: Box::new(SettingField { - pick: |settings_content| &settings_content.editor.cursor_shape, - pick_mut: |settings_content| &mut settings_content.editor.cursor_shape, + pick: |settings_content| settings_content.editor.cursor_shape.as_ref(), + write: |settings_content, value|{ settings_content.editor.cursor_shape = value;}, }), metadata: None, files: USER, @@ -458,8 +651,8 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Hide Mouse", description: "When to hide the mouse cursor", field: Box::new(SettingField { - pick: |settings_content| &settings_content.editor.hide_mouse, - pick_mut: |settings_content| &mut settings_content.editor.hide_mouse, + pick: |settings_content| settings_content.editor.hide_mouse.as_ref(), + write: |settings_content, value|{ settings_content.editor.hide_mouse = value;}, }), metadata: None, files: USER, @@ -469,9 +662,12 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Unnecessary Code Fade", description: "How much to fade out unused code (0.0 - 0.9)", field: Box::new(SettingField { - pick: |settings_content| &settings_content.theme.unnecessary_code_fade, - pick_mut: |settings_content| { - &mut settings_content.theme.unnecessary_code_fade + pick: |settings_content| { + settings_content.theme.unnecessary_code_fade.as_ref() + }, + write: |settings_content, value| { + settings_content.theme.unnecessary_code_fade = value; + }, }), metadata: None, @@ -481,9 +677,12 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Current Line Highlight", description: "How to highlight the current line", field: Box::new(SettingField { - pick: |settings_content| &settings_content.editor.current_line_highlight, - pick_mut: |settings_content| { - &mut settings_content.editor.current_line_highlight + pick: |settings_content| { + settings_content.editor.current_line_highlight.as_ref() + }, + write: |settings_content, value| { + settings_content.editor.current_line_highlight = value; + }, }), metadata: None, @@ -493,9 +692,12 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Selection Highlight", description: "Highlight all occurrences of selected text", field: Box::new(SettingField { - pick: |settings_content| &settings_content.editor.selection_highlight, - pick_mut: |settings_content| { - &mut settings_content.editor.selection_highlight + pick: |settings_content| { + settings_content.editor.selection_highlight.as_ref() + }, + write: |settings_content, value| { + settings_content.editor.selection_highlight = value; + }, }), metadata: None, @@ -505,8 +707,8 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Rounded Selection", description: "Whether the text selection should have rounded corners", field: Box::new(SettingField { - pick: |settings_content| &settings_content.editor.rounded_selection, - pick_mut: |settings_content| &mut settings_content.editor.rounded_selection, + pick: |settings_content| settings_content.editor.rounded_selection.as_ref(), + write: |settings_content, value|{ settings_content.editor.rounded_selection = value;}, }), metadata: None, files: USER, @@ -516,10 +718,14 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "The minimum APCA perceptual contrast to maintain when rendering text over highlight backgrounds", field: Box::new(SettingField { pick: |settings_content| { - &settings_content.editor.minimum_contrast_for_highlights + settings_content + .editor + .minimum_contrast_for_highlights + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.editor.minimum_contrast_for_highlights + write: |settings_content, value| { + settings_content.editor.minimum_contrast_for_highlights = value; + }, }), metadata: None, @@ -531,18 +737,20 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show wrap guides (vertical rulers)", field: Box::new(SettingField { pick: |settings_content| { - &settings_content + settings_content .project .all_languages .defaults .show_wrap_guides + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content + .project .all_languages .defaults - .show_wrap_guides + .show_wrap_guides = value; }, }), metadata: None, @@ -555,10 +763,16 @@ pub(crate) fn settings_data(cx: &App) -> Vec { field: Box::new( SettingField { pick: |settings_content| { - &settings_content.project.all_languages.defaults.wrap_guides + settings_content + .project + .all_languages + .defaults + .wrap_guides + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.project.all_languages.defaults.wrap_guides + write: |settings_content, value| { + settings_content.project.all_languages.defaults.wrap_guides = value; + }, } .unimplemented(), @@ -576,8 +790,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Base Keymap", description: "The name of a base set of key bindings to use", field: Box::new(SettingField { - pick: |settings_content| &settings_content.base_keymap, - pick_mut: |settings_content| &mut settings_content.base_keymap, + pick: |settings_content| settings_content.base_keymap.as_ref(), + write: |settings_content, value| { + settings_content.base_keymap = value; + }, }), metadata: Some(Box::new(SettingsFieldMetadata { should_do_titlecase: Some(false), @@ -592,8 +808,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Vim Mode", description: "Enable vim modes and key bindings", field: Box::new(SettingField { - pick: |settings_content| &settings_content.vim_mode, - pick_mut: |settings_content| &mut settings_content.vim_mode, + pick: |settings_content| settings_content.vim_mode.as_ref(), + write: |settings_content, value| { + settings_content.vim_mode = value; + }, }), metadata: None, files: USER, @@ -602,8 +820,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Helix Mode", description: "Enable helix modes and key bindings", field: Box::new(SettingField { - pick: |settings_content| &settings_content.helix_mode, - pick_mut: |settings_content| &mut settings_content.helix_mode, + pick: |settings_content| settings_content.helix_mode.as_ref(), + write: |settings_content, value| { + settings_content.helix_mode = value; + }, }), metadata: None, files: USER, @@ -620,9 +840,11 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "When to Auto Save Buffer Changes", field: Box::new( SettingField { - pick: |settings_content| &settings_content.workspace.autosave, - pick_mut: |settings_content| { - &mut settings_content.workspace.autosave + pick: |settings_content| { + settings_content.workspace.autosave.as_ref() + }, + write: |settings_content, value| { + settings_content.workspace.autosave = value; }, } .unimplemented(), @@ -636,10 +858,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "What to do when multibuffer is double-clicked in some of its excerpts", field: Box::new(SettingField { pick: |settings_content| { - &settings_content.editor.double_click_in_multibuffer + settings_content.editor.double_click_in_multibuffer.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.editor.double_click_in_multibuffer + write: |settings_content, value| { + settings_content.editor.double_click_in_multibuffer = value; }, }), metadata: None, @@ -649,9 +871,11 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Expand Excerpt Lines", description: "How many lines to expand the multibuffer excerpts by default", field: Box::new(SettingField { - pick: |settings_content| &settings_content.editor.expand_excerpt_lines, - pick_mut: |settings_content| { - &mut settings_content.editor.expand_excerpt_lines + pick: |settings_content| { + settings_content.editor.expand_excerpt_lines.as_ref() + }, + write: |settings_content, value| { + settings_content.editor.expand_excerpt_lines = value; }, }), metadata: None, @@ -661,9 +885,11 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Excerpt Context Lines", description: "How many lines of context to provide in multibuffer excerpts by default", field: Box::new(SettingField { - pick: |settings_content| &settings_content.editor.excerpt_context_lines, - pick_mut: |settings_content| { - &mut settings_content.editor.excerpt_context_lines + pick: |settings_content| { + settings_content.editor.excerpt_context_lines.as_ref() + }, + write: |settings_content, value| { + settings_content.editor.excerpt_context_lines = value; }, }), metadata: None, @@ -674,17 +900,18 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Default depth to expand outline items in the current file", field: Box::new(SettingField { pick: |settings_content| { - if let Some(outline_panel) = &settings_content.outline_panel { - &outline_panel.expand_outlines_with_depth - } else { - &None - } + settings_content + .outline_panel + .as_ref() + .and_then(|outline_panel| { + outline_panel.expand_outlines_with_depth.as_ref() + }) }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .outline_panel .get_or_insert_default() - .expand_outlines_with_depth + .expand_outlines_with_depth = value; }, }), metadata: None, @@ -696,10 +923,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether the editor will scroll beyond the last line", field: Box::new(SettingField { pick: |settings_content| { - &settings_content.editor.scroll_beyond_last_line + settings_content.editor.scroll_beyond_last_line.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.editor.scroll_beyond_last_line + write: |settings_content, value| { + settings_content.editor.scroll_beyond_last_line = value; }, }), metadata: None, @@ -710,10 +937,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "The number of lines to keep above/below the cursor when auto-scrolling", field: Box::new(SettingField { pick: |settings_content| { - &settings_content.editor.vertical_scroll_margin + settings_content.editor.vertical_scroll_margin.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.editor.vertical_scroll_margin + write: |settings_content, value| { + settings_content.editor.vertical_scroll_margin = value; }, }), metadata: None, @@ -724,10 +951,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "The number of characters to keep on either side when scrolling with the mouse", field: Box::new(SettingField { pick: |settings_content| { - &settings_content.editor.horizontal_scroll_margin + settings_content.editor.horizontal_scroll_margin.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.editor.horizontal_scroll_margin + write: |settings_content, value| { + settings_content.editor.horizontal_scroll_margin = value; }, }), metadata: None, @@ -737,9 +964,11 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Scroll Sensitivity", description: "Scroll sensitivity multiplier for both horizontal and vertical scrolling", field: Box::new(SettingField { - pick: |settings_content| &settings_content.editor.scroll_sensitivity, - pick_mut: |settings_content| { - &mut settings_content.editor.scroll_sensitivity + pick: |settings_content| { + settings_content.editor.scroll_sensitivity.as_ref() + }, + write: |settings_content, value| { + settings_content.editor.scroll_sensitivity = value; }, }), metadata: None, @@ -750,10 +979,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Fast Scroll sensitivity multiplier for both horizontal and vertical scrolling", field: Box::new(SettingField { pick: |settings_content| { - &settings_content.editor.fast_scroll_sensitivity + settings_content.editor.fast_scroll_sensitivity.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.editor.fast_scroll_sensitivity + write: |settings_content, value| { + settings_content.editor.fast_scroll_sensitivity = value; }, }), metadata: None, @@ -763,9 +992,11 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Autoscroll On Clicks", description: "Whether to scroll when clicking near the edge of the visible text area", field: Box::new(SettingField { - pick: |settings_content| &settings_content.editor.autoscroll_on_clicks, - pick_mut: |settings_content| { - &mut settings_content.editor.autoscroll_on_clicks + pick: |settings_content| { + settings_content.editor.autoscroll_on_clicks.as_ref() + }, + write: |settings_content, value| { + settings_content.editor.autoscroll_on_clicks = value; }, }), metadata: None, @@ -776,9 +1007,11 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Auto Signature Help", description: "Automatically show a signature help pop-up", field: Box::new(SettingField { - pick: |settings_content| &settings_content.editor.auto_signature_help, - pick_mut: |settings_content| { - &mut settings_content.editor.auto_signature_help + pick: |settings_content| { + settings_content.editor.auto_signature_help.as_ref() + }, + write: |settings_content, value| { + settings_content.editor.auto_signature_help = value; }, }), metadata: None, @@ -789,10 +1022,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show the signature help pop-up after completions or bracket pairs are inserted", field: Box::new(SettingField { pick: |settings_content| { - &settings_content.editor.show_signature_help_after_edits + settings_content + .editor + .show_signature_help_after_edits + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.editor.show_signature_help_after_edits + write: |settings_content, value| { + settings_content.editor.show_signature_help_after_edits = value; }, }), metadata: None, @@ -802,9 +1038,11 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Snippet Sort Order", description: "Determines how snippets are sorted relative to other completion items", field: Box::new(SettingField { - pick: |settings_content| &settings_content.editor.snippet_sort_order, - pick_mut: |settings_content| { - &mut settings_content.editor.snippet_sort_order + pick: |settings_content| { + settings_content.editor.snippet_sort_order.as_ref() + }, + write: |settings_content, value| { + settings_content.editor.snippet_sort_order = value; }, }), metadata: None, @@ -815,9 +1053,11 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Enabled", description: "Show the informational hover box when moving the mouse over symbols in the editor", field: Box::new(SettingField { - pick: |settings_content| &settings_content.editor.hover_popover_enabled, - pick_mut: |settings_content| { - &mut settings_content.editor.hover_popover_enabled + pick: |settings_content| { + settings_content.editor.hover_popover_enabled.as_ref() + }, + write: |settings_content, value| { + settings_content.editor.hover_popover_enabled = value; }, }), metadata: None, @@ -828,9 +1068,11 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Delay", description: "Time to wait in milliseconds before showing the informational hover box", field: Box::new(SettingField { - pick: |settings_content| &settings_content.editor.hover_popover_delay, - pick_mut: |settings_content| { - &mut settings_content.editor.hover_popover_delay + pick: |settings_content| { + settings_content.editor.hover_popover_delay.as_ref() + }, + write: |settings_content, value| { + settings_content.editor.hover_popover_delay = value; }, }), metadata: None, @@ -842,20 +1084,18 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Enable drag and drop selection", field: Box::new(SettingField { pick: |settings_content| { - if let Some(drag_and_drop) = - &settings_content.editor.drag_and_drop_selection - { - &drag_and_drop.enabled - } else { - &None - } + settings_content + .editor + .drag_and_drop_selection + .as_ref() + .and_then(|drag_and_drop| drag_and_drop.enabled.as_ref()) }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .drag_and_drop_selection .get_or_insert_default() - .enabled + .enabled = value; }, }), metadata: None, @@ -866,20 +1106,18 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Delay in milliseconds before drag and drop selection starts", field: Box::new(SettingField { pick: |settings_content| { - if let Some(drag_and_drop) = - &settings_content.editor.drag_and_drop_selection - { - &drag_and_drop.delay - } else { - &None - } + settings_content + .editor + .drag_and_drop_selection + .as_ref() + .and_then(|drag_and_drop| drag_and_drop.delay.as_ref()) }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .drag_and_drop_selection .get_or_insert_default() - .delay + .delay = value; }, }), metadata: None, @@ -891,18 +1129,18 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show line numbers in the gutter", field: Box::new(SettingField { pick: |settings_content| { - if let Some(gutter) = &settings_content.editor.gutter { - &gutter.line_numbers - } else { - &None - } + settings_content + .editor + .gutter + .as_ref() + .and_then(|gutter| gutter.line_numbers.as_ref()) }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .gutter .get_or_insert_default() - .line_numbers + .line_numbers = value; }, }), metadata: None, @@ -912,9 +1150,11 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Relative Line Numbers", description: "Whether the line numbers in the editor's gutter are relative or not", field: Box::new(SettingField { - pick: |settings_content| &settings_content.editor.relative_line_numbers, - pick_mut: |settings_content| { - &mut settings_content.editor.relative_line_numbers + pick: |settings_content| { + settings_content.editor.relative_line_numbers.as_ref() + }, + write: |settings_content, value| { + settings_content.editor.relative_line_numbers = value; }, }), metadata: None, @@ -925,18 +1165,18 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show runnable buttons in the gutter", field: Box::new(SettingField { pick: |settings_content| { - if let Some(gutter) = &settings_content.editor.gutter { - &gutter.runnables - } else { - &None - } + settings_content + .editor + .gutter + .as_ref() + .and_then(|gutter| gutter.runnables.as_ref()) }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .gutter .get_or_insert_default() - .runnables + .runnables = value; }, }), metadata: None, @@ -947,18 +1187,18 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show breakpoints in the gutter", field: Box::new(SettingField { pick: |settings_content| { - if let Some(gutter) = &settings_content.editor.gutter { - &gutter.breakpoints - } else { - &None - } + settings_content + .editor + .gutter + .as_ref() + .and_then(|gutter| gutter.breakpoints.as_ref()) }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .gutter .get_or_insert_default() - .breakpoints + .breakpoints = value; }, }), metadata: None, @@ -969,14 +1209,15 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show code folding controls in the gutter", field: Box::new(SettingField { pick: |settings_content| { - if let Some(gutter) = &settings_content.editor.gutter { - &gutter.folds - } else { - &None - } + settings_content + .editor + .gutter + .as_ref() + .and_then(|gutter| gutter.folds.as_ref()) }, - pick_mut: |settings_content| { - &mut settings_content.editor.gutter.get_or_insert_default().folds + write: |settings_content, value| { + settings_content.editor.gutter.get_or_insert_default().folds = + value; }, }), metadata: None, @@ -987,18 +1228,18 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Minimum number of characters to reserve space for in the gutter", field: Box::new(SettingField { pick: |settings_content| { - if let Some(gutter) = &settings_content.editor.gutter { - &gutter.min_line_number_digits - } else { - &None - } + settings_content + .editor + .gutter + .as_ref() + .and_then(|gutter| gutter.min_line_number_digits.as_ref()) }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .gutter .get_or_insert_default() - .min_line_number_digits + .min_line_number_digits = value; }, }), metadata: None, @@ -1008,9 +1249,11 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Inline Code Actions", description: "Show code action button at start of buffer line", field: Box::new(SettingField { - pick: |settings_content| &settings_content.editor.inline_code_actions, - pick_mut: |settings_content| { - &mut settings_content.editor.inline_code_actions + pick: |settings_content| { + settings_content.editor.inline_code_actions.as_ref() + }, + write: |settings_content, value| { + settings_content.editor.inline_code_actions = value; }, }), metadata: None, @@ -1022,18 +1265,14 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "When to show the scrollbar in the editor", field: Box::new(SettingField { pick: |settings_content| { - if let Some(scrollbar) = &settings_content.editor.scrollbar { - &scrollbar.show - } else { - &None - } + settings_content.editor.scrollbar.as_ref()?.show.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .scrollbar .get_or_insert_default() - .show + .show = value; }, }), metadata: None, @@ -1044,18 +1283,14 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show cursor positions in the scrollbar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(scrollbar) = &settings_content.editor.scrollbar { - &scrollbar.cursors - } else { - &None - } + settings_content.editor.scrollbar.as_ref()?.cursors.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .scrollbar .get_or_insert_default() - .cursors + .cursors = value; }, }), metadata: None, @@ -1066,18 +1301,19 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show git diff indicators in the scrollbar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(scrollbar) = &settings_content.editor.scrollbar { - &scrollbar.git_diff - } else { - &None - } + settings_content + .editor + .scrollbar + .as_ref()? + .git_diff + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .scrollbar .get_or_insert_default() - .git_diff + .git_diff = value; }, }), metadata: None, @@ -1088,18 +1324,19 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show buffer search result indicators in the scrollbar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(scrollbar) = &settings_content.editor.scrollbar { - &scrollbar.search_results - } else { - &None - } + settings_content + .editor + .scrollbar + .as_ref()? + .search_results + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .scrollbar .get_or_insert_default() - .search_results + .search_results = value; }, }), metadata: None, @@ -1110,18 +1347,19 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show selected text occurrences in the scrollbar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(scrollbar) = &settings_content.editor.scrollbar { - &scrollbar.selected_text - } else { - &None - } + settings_content + .editor + .scrollbar + .as_ref()? + .selected_text + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .scrollbar .get_or_insert_default() - .selected_text + .selected_text = value; }, }), metadata: None, @@ -1132,18 +1370,19 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show selected symbol occurrences in the scrollbar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(scrollbar) = &settings_content.editor.scrollbar { - &scrollbar.selected_symbol - } else { - &None - } + settings_content + .editor + .scrollbar + .as_ref()? + .selected_symbol + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .scrollbar .get_or_insert_default() - .selected_symbol + .selected_symbol = value; }, }), metadata: None, @@ -1154,18 +1393,19 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Which diagnostic indicators to show in the scrollbar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(scrollbar) = &settings_content.editor.scrollbar { - &scrollbar.diagnostics - } else { - &None - } + settings_content + .editor + .scrollbar + .as_ref()? + .diagnostics + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .scrollbar .get_or_insert_default() - .diagnostics + .diagnostics = value; }, }), metadata: None, @@ -1176,24 +1416,23 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "When false, forcefully disables the horizontal scrollbar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(scrollbar) = &settings_content.editor.scrollbar { - if let Some(axes) = &scrollbar.axes { - &axes.horizontal - } else { - &None - } - } else { - &None - } + settings_content + .editor + .scrollbar + .as_ref()? + .axes + .as_ref()? + .horizontal + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .scrollbar .get_or_insert_default() .axes .get_or_insert_default() - .horizontal + .horizontal = value; }, }), metadata: None, @@ -1204,24 +1443,23 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "When false, forcefully disables the vertical scrollbar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(scrollbar) = &settings_content.editor.scrollbar { - if let Some(axes) = &scrollbar.axes { - &axes.vertical - } else { - &None - } - } else { - &None - } + settings_content + .editor + .scrollbar + .as_ref()? + .axes + .as_ref()? + .vertical + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .scrollbar .get_or_insert_default() .axes .get_or_insert_default() - .vertical + .vertical = value; }, }), metadata: None, @@ -1233,14 +1471,11 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "When to show the minimap in the editor", field: Box::new(SettingField { pick: |settings_content| { - if let Some(minimap) = &settings_content.editor.minimap { - &minimap.show - } else { - &None - } + settings_content.editor.minimap.as_ref()?.show.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.editor.minimap.get_or_insert_default().show + write: |settings_content, value| { + settings_content.editor.minimap.get_or_insert_default().show = + value; }, }), metadata: None, @@ -1251,18 +1486,19 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Where to show the minimap in the editor", field: Box::new(SettingField { pick: |settings_content| { - if let Some(minimap) = &settings_content.editor.minimap { - &minimap.display_in - } else { - &None - } + settings_content + .editor + .minimap + .as_ref()? + .display_in + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .minimap .get_or_insert_default() - .display_in + .display_in = value; }, }), metadata: None, @@ -1273,18 +1509,14 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "When to show the minimap thumb", field: Box::new(SettingField { pick: |settings_content| { - if let Some(minimap) = &settings_content.editor.minimap { - &minimap.thumb - } else { - &None - } + settings_content.editor.minimap.as_ref()?.thumb.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .minimap .get_or_insert_default() - .thumb + .thumb = value; }, }), metadata: None, @@ -1295,18 +1527,19 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Border style for the minimap's scrollbar thumb", field: Box::new(SettingField { pick: |settings_content| { - if let Some(minimap) = &settings_content.editor.minimap { - &minimap.thumb_border - } else { - &None - } + settings_content + .editor + .minimap + .as_ref()? + .thumb_border + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .minimap .get_or_insert_default() - .thumb_border + .thumb_border = value; }, }), metadata: None, @@ -1317,20 +1550,19 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "How to highlight the current line in the minimap", field: Box::new(SettingField { pick: |settings_content| { - if let Some(minimap) = &settings_content.editor.minimap - && minimap.current_line_highlight.is_some() - { - &minimap.current_line_highlight - } else { - &settings_content.editor.current_line_highlight - } + settings_content + .editor + .minimap + .as_ref() + .and_then(|minimap| minimap.current_line_highlight.as_ref()) + .or(settings_content.editor.current_line_highlight.as_ref()) }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .minimap .get_or_insert_default() - .current_line_highlight + .current_line_highlight = value; }, }), metadata: None, @@ -1341,18 +1573,19 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Maximum number of columns to display in the minimap", field: Box::new(SettingField { pick: |settings_content| { - if let Some(minimap) = &settings_content.editor.minimap { - &minimap.max_width_columns - } else { - &None - } + settings_content + .editor + .minimap + .as_ref()? + .max_width_columns + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .minimap .get_or_insert_default() - .max_width_columns + .max_width_columns = value; }, }), metadata: None, @@ -1364,18 +1597,19 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show breadcrumbs", field: Box::new(SettingField { pick: |settings_content| { - if let Some(toolbar) = &settings_content.editor.toolbar { - &toolbar.breadcrumbs - } else { - &None - } + settings_content + .editor + .toolbar + .as_ref()? + .breadcrumbs + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .toolbar .get_or_insert_default() - .breadcrumbs + .breadcrumbs = value; }, }), metadata: None, @@ -1386,18 +1620,19 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show quick action buttons (e.g., search, selection, editor controls, etc.)", field: Box::new(SettingField { pick: |settings_content| { - if let Some(toolbar) = &settings_content.editor.toolbar { - &toolbar.quick_actions - } else { - &None - } + settings_content + .editor + .toolbar + .as_ref()? + .quick_actions + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .toolbar .get_or_insert_default() - .quick_actions + .quick_actions = value; }, }), metadata: None, @@ -1408,18 +1643,19 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show the selections menu in the editor toolbar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(toolbar) = &settings_content.editor.toolbar { - &toolbar.selections_menu - } else { - &None - } + settings_content + .editor + .toolbar + .as_ref()? + .selections_menu + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .toolbar .get_or_insert_default() - .selections_menu + .selections_menu = value; }, }), metadata: None, @@ -1430,18 +1666,19 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show agent review buttons in the editor toolbar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(toolbar) = &settings_content.editor.toolbar { - &toolbar.agent_review - } else { - &None - } + settings_content + .editor + .toolbar + .as_ref()? + .agent_review + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .toolbar .get_or_insert_default() - .agent_review + .agent_review = value; }, }), metadata: None, @@ -1452,18 +1689,19 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show code action buttons in the editor toolbar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(toolbar) = &settings_content.editor.toolbar { - &toolbar.code_actions - } else { - &None - } + settings_content + .editor + .toolbar + .as_ref()? + .code_actions + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .toolbar .get_or_insert_default() - .code_actions + .code_actions = value; }, }), metadata: None, @@ -1487,10 +1725,11 @@ pub(crate) fn settings_data(cx: &App) -> Vec { field: Box::new( SettingField { pick: |settings_content| { - &settings_content.project.all_languages.file_types + settings_content.project.all_languages.file_types.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.project.all_languages.file_types + write: |settings_content, value| { + settings_content.project.all_languages.file_types = value; + }, } .unimplemented(), @@ -1502,217 +1741,181 @@ pub(crate) fn settings_data(cx: &App) -> Vec { items.extend([ SettingsPageItem::SectionHeader("Diagnostics"), - SettingsPageItem::SettingItem(SettingItem { - title: "Max Severity", - description: "Which level to use to filter out diagnostics displayed in the editor", - field: Box::new(SettingField { - pick: |settings_content| &settings_content.editor.diagnostics_max_severity, - pick_mut: |settings_content| { - &mut settings_content.editor.diagnostics_max_severity - }, - }), - metadata: None, - files: USER, - }), - SettingsPageItem::SettingItem(SettingItem { - title: "Include Warnings", - description: "Whether to show warnings or not by default", - field: Box::new(SettingField { - pick: |settings_content| { - if let Some(diagnostics) = &settings_content.diagnostics { - &diagnostics.include_warnings - } else { - &None - } - }, - pick_mut: |settings_content| { - &mut settings_content - .diagnostics - .get_or_insert_default() - .include_warnings - }, - }), - metadata: None, - files: USER, - }), - SettingsPageItem::SectionHeader("Inline Diagnostics"), - SettingsPageItem::SettingItem(SettingItem { - title: "Enabled", - description: "Whether to show diagnostics inline or not", - field: Box::new(SettingField { - pick: |settings_content| { - if let Some(diagnostics) = &settings_content.diagnostics { - if let Some(inline) = &diagnostics.inline { - &inline.enabled - } else { - &None - } - } else { - &None - } - }, - pick_mut: |settings_content| { - &mut settings_content - .diagnostics - .get_or_insert_default() - .inline - .get_or_insert_default() - .enabled - }, - }), - metadata: None, - files: USER, - }), - SettingsPageItem::SettingItem(SettingItem { - title: "Update Debounce", - description: "The delay in milliseconds to show inline diagnostics after the last diagnostic update", - field: Box::new(SettingField { - pick: |settings_content| { - if let Some(diagnostics) = &settings_content.diagnostics { - if let Some(inline) = &diagnostics.inline { - &inline.update_debounce_ms - } else { - &None - } - } else { - &None - } - }, - pick_mut: |settings_content| { - &mut settings_content - .diagnostics - .get_or_insert_default() - .inline - .get_or_insert_default() - .update_debounce_ms - }, - }), - metadata: None, - files: USER, - }), - SettingsPageItem::SettingItem(SettingItem { - title: "Padding", - description: "The amount of padding between the end of the source line and the start of the inline diagnostic", - field: Box::new(SettingField { - pick: |settings_content| { - if let Some(diagnostics) = &settings_content.diagnostics { - if let Some(inline) = &diagnostics.inline { - &inline.padding - } else { - &None - } - } else { - &None - } - }, - pick_mut: |settings_content| { - &mut settings_content - .diagnostics - .get_or_insert_default() - .inline - .get_or_insert_default() - .padding - }, - }), - metadata: None, - files: USER, - }), - SettingsPageItem::SettingItem(SettingItem { - title: "Minimum Column", - description: "The minimum column at which to display inline diagnostics", - field: Box::new(SettingField { - pick: |settings_content| { - if let Some(diagnostics) = &settings_content.diagnostics { - if let Some(inline) = &diagnostics.inline { - &inline.min_column - } else { - &None - } - } else { - &None - } - }, - pick_mut: |settings_content| { - &mut settings_content - .diagnostics - .get_or_insert_default() - .inline - .get_or_insert_default() - .min_column - }, - }), - metadata: None, - files: USER, - }), - SettingsPageItem::SectionHeader("LSP Pull Diagnostics"), - SettingsPageItem::SettingItem(SettingItem { - title: "Enabled", - description: "Whether to pull for language server-powered diagnostics or not", - field: Box::new(SettingField { - pick: |settings_content| { - if let Some(diagnostics) = &settings_content.diagnostics { - if let Some(lsp_pull) = &diagnostics.lsp_pull_diagnostics { - &lsp_pull.enabled - } else { - &None - } - } else { - &None - } - }, - pick_mut: |settings_content| { - &mut settings_content - .diagnostics - .get_or_insert_default() - .lsp_pull_diagnostics - .get_or_insert_default() - .enabled - }, - }), - metadata: None, - files: USER, - }), - // todo(settings_ui): Needs unit - SettingsPageItem::SettingItem(SettingItem { - title: "Debounce", - description: "Minimum time to wait before pulling diagnostics from the language server(s)", - field: Box::new(SettingField { - pick: |settings_content| { - if let Some(diagnostics) = &settings_content.diagnostics { - if let Some(lsp_pull) = &diagnostics.lsp_pull_diagnostics { - &lsp_pull.debounce_ms - } else { - &None - } - } else { - &None - } - }, - pick_mut: |settings_content| { - &mut settings_content - .diagnostics - .get_or_insert_default() - .lsp_pull_diagnostics - .get_or_insert_default() - .debounce_ms - }, - }), - metadata: None, - files: USER, - }), - SettingsPageItem::SectionHeader("LSP Highlights"), - SettingsPageItem::SettingItem(SettingItem { - title: "Debounce", - description: "The debounce delay before querying highlights from the language", - field: Box::new(SettingField { - pick: |settings_content| &settings_content.editor.lsp_highlight_debounce, - pick_mut: |settings_content| { - &mut settings_content.editor.lsp_highlight_debounce - }, - }), - metadata: None, - files: USER, - }), + SettingsPageItem::SettingItem(SettingItem { + title: "Max Severity", + description: "Which level to use to filter out diagnostics displayed in the editor", + field: Box::new(SettingField { + pick: |settings_content| settings_content.editor.diagnostics_max_severity.as_ref(), + write: |settings_content, value| { + settings_content.editor.diagnostics_max_severity = value; + + }, + }), + metadata: None, + files: USER, + }), + SettingsPageItem::SettingItem(SettingItem { + title: "Include Warnings", + description: "Whether to show warnings or not by default", + field: Box::new(SettingField { + pick: |settings_content| { + settings_content.diagnostics.as_ref()?.include_warnings.as_ref() + }, + write: |settings_content, value| { + settings_content + + .diagnostics + .get_or_insert_default() + .include_warnings + = value; + }, + }), + metadata: None, + files: USER, + }), + SettingsPageItem::SectionHeader("Inline Diagnostics"), + SettingsPageItem::SettingItem(SettingItem { + title: "Enabled", + description: "Whether to show diagnostics inline or not", + field: Box::new(SettingField { + pick: |settings_content| { + settings_content.diagnostics.as_ref()?.inline.as_ref()?.enabled.as_ref() + }, + write: |settings_content, value| { + settings_content + + .diagnostics + .get_or_insert_default() + .inline + .get_or_insert_default() + .enabled + = value; + }, + }), + metadata: None, + files: USER, + }), + SettingsPageItem::SettingItem(SettingItem { + title: "Update Debounce", + description: "The delay in milliseconds to show inline diagnostics after the last diagnostic update", + field: Box::new(SettingField { + pick: |settings_content| { + settings_content.diagnostics.as_ref()?.inline.as_ref()?.update_debounce_ms.as_ref() + }, + write: |settings_content, value| { + settings_content + + .diagnostics + .get_or_insert_default() + .inline + .get_or_insert_default() + .update_debounce_ms + = value; + }, + }), + metadata: None, + files: USER, + }), + SettingsPageItem::SettingItem(SettingItem { + title: "Padding", + description: "The amount of padding between the end of the source line and the start of the inline diagnostic", + field: Box::new(SettingField { + pick: |settings_content| { + settings_content.diagnostics.as_ref()?.inline.as_ref()?.padding.as_ref() + }, + write: |settings_content, value| { + settings_content + + .diagnostics + .get_or_insert_default() + .inline + .get_or_insert_default() + .padding + = value; + }, + }), + metadata: None, + files: USER, + }), + SettingsPageItem::SettingItem(SettingItem { + title: "Minimum Column", + description: "The minimum column at which to display inline diagnostics", + field: Box::new(SettingField { + pick: |settings_content| { + settings_content.diagnostics.as_ref()?.inline.as_ref()?.min_column.as_ref() + }, + write: |settings_content, value| { + settings_content + + .diagnostics + .get_or_insert_default() + .inline + .get_or_insert_default() + .min_column + = value; + }, + }), + metadata: None, + files: USER, + }), + SettingsPageItem::SectionHeader("LSP Pull Diagnostics"), + SettingsPageItem::SettingItem(SettingItem { + title: "Enabled", + description: "Whether to pull for language server-powered diagnostics or not", + field: Box::new(SettingField { + pick: |settings_content| { + settings_content.diagnostics.as_ref()?.lsp_pull_diagnostics.as_ref()?.enabled.as_ref() + }, + write: |settings_content, value| { + settings_content + + .diagnostics + .get_or_insert_default() + .lsp_pull_diagnostics + .get_or_insert_default() + .enabled + = value; + }, + }), + metadata: None, + files: USER, + }), + // todo(settings_ui): Needs unit + SettingsPageItem::SettingItem(SettingItem { + title: "Debounce", + description: "Minimum time to wait before pulling diagnostics from the language server(s)", + field: Box::new(SettingField { + pick: |settings_content| { + settings_content.diagnostics.as_ref()?.lsp_pull_diagnostics.as_ref()?.debounce_ms.as_ref() + }, + write: |settings_content, value| { + settings_content + + .diagnostics + .get_or_insert_default() + .lsp_pull_diagnostics + .get_or_insert_default() + .debounce_ms + = value; + }, + }), + metadata: None, + files: USER, + }), + SettingsPageItem::SectionHeader("LSP Highlights"), + SettingsPageItem::SettingItem(SettingItem { + title: "Debounce", + description: "The debounce delay before querying highlights from the language", + field: Box::new(SettingField { + pick: |settings_content| settings_content.editor.lsp_highlight_debounce.as_ref(), + write: |settings_content, value| { + settings_content.editor.lsp_highlight_debounce = value; + + }, + }), + metadata: None, + files: USER, + }), ]); // todo(settings_ui): Refresh on extension (un)/installed @@ -1748,18 +1951,14 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Search for whole words by default", field: Box::new(SettingField { pick: |settings_content| { - if let Some(search) = &settings_content.editor.search { - &search.whole_word - } else { - &None - } + settings_content.editor.search.as_ref()?.whole_word.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .search .get_or_insert_default() - .whole_word + .whole_word = value; }, }), metadata: None, @@ -1770,18 +1969,19 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Search case-sensitively by default", field: Box::new(SettingField { pick: |settings_content| { - if let Some(search) = &settings_content.editor.search { - &search.case_sensitive - } else { - &None - } + settings_content + .editor + .search + .as_ref()? + .case_sensitive + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .search .get_or_insert_default() - .case_sensitive + .case_sensitive = value; }, }), metadata: None, @@ -1791,9 +1991,11 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Use Smartcase Search", description: "Whether to automatically enable case-sensitive search based on the search query", field: Box::new(SettingField { - pick: |settings_content| &settings_content.editor.use_smartcase_search, - pick_mut: |settings_content| { - &mut settings_content.editor.use_smartcase_search + pick: |settings_content| { + settings_content.editor.use_smartcase_search.as_ref() + }, + write: |settings_content, value| { + settings_content.editor.use_smartcase_search = value; }, }), metadata: None, @@ -1804,18 +2006,19 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Include ignored files in search results by default", field: Box::new(SettingField { pick: |settings_content| { - if let Some(search) = &settings_content.editor.search { - &search.include_ignored - } else { - &None - } + settings_content + .editor + .search + .as_ref()? + .include_ignored + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .search .get_or_insert_default() - .include_ignored + .include_ignored = value; }, }), metadata: None, @@ -1826,14 +2029,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Use regex search by default", field: Box::new(SettingField { pick: |settings_content| { - if let Some(search) = &settings_content.editor.search { - &search.regex - } else { - &None - } + settings_content.editor.search.as_ref()?.regex.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.editor.search.get_or_insert_default().regex + write: |settings_content, value| { + settings_content.editor.search.get_or_insert_default().regex = value; }, }), metadata: None, @@ -1843,8 +2042,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Search Wrap", description: "Whether the editor search results will loop", field: Box::new(SettingField { - pick: |settings_content| &settings_content.editor.search_wrap, - pick_mut: |settings_content| &mut settings_content.editor.search_wrap, + pick: |settings_content| settings_content.editor.search_wrap.as_ref(), + write: |settings_content, value| { + settings_content.editor.search_wrap = value; + }, }), metadata: None, files: USER, @@ -1854,10 +2055,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "When to populate a new search's query based on the text under the cursor", field: Box::new(SettingField { pick: |settings_content| { - &settings_content.editor.seed_search_query_from_cursor + settings_content + .editor + .seed_search_query_from_cursor + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.editor.seed_search_query_from_cursor + write: |settings_content, value| { + settings_content.editor.seed_search_query_from_cursor = value; }, }), metadata: None, @@ -1871,17 +2075,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { field: Box::new( SettingField { pick: |settings_content| { - if let Some(file_finder) = &settings_content.file_finder { - &file_finder.include_ignored - } else { - &None - } + settings_content + .file_finder + .as_ref()? + .include_ignored + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .file_finder .get_or_insert_default() - .include_ignored + .include_ignored = value; }, } .unimplemented(), @@ -1894,17 +2098,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show file icons in the file finder", field: Box::new(SettingField { pick: |settings_content| { - if let Some(file_finder) = &settings_content.file_finder { - &file_finder.file_icons - } else { - &None - } + settings_content.file_finder.as_ref()?.file_icons.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .file_finder .get_or_insert_default() - .file_icons + .file_icons = value; }, }), metadata: None, @@ -1915,17 +2115,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Determines how much space the file finder can take up in relation to the available window width", field: Box::new(SettingField { pick: |settings_content| { - if let Some(file_finder) = &settings_content.file_finder { - &file_finder.modal_max_width - } else { - &None - } + settings_content + .file_finder + .as_ref()? + .modal_max_width + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .file_finder .get_or_insert_default() - .modal_max_width + .modal_max_width = value; }, }), metadata: None, @@ -1936,17 +2136,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether the file finder should skip focus for the active file in search results", field: Box::new(SettingField { pick: |settings_content| { - if let Some(file_finder) = &settings_content.file_finder { - &file_finder.skip_focus_for_active_in_search - } else { - &None - } + settings_content + .file_finder + .as_ref()? + .skip_focus_for_active_in_search + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .file_finder .get_or_insert_default() - .skip_focus_for_active_in_search + .skip_focus_for_active_in_search = value; }, }), metadata: None, @@ -1957,17 +2157,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show the git status in the file finder", field: Box::new(SettingField { pick: |settings_content| { - if let Some(file_finder) = &settings_content.file_finder { - &file_finder.git_status - } else { - &None - } + settings_content.file_finder.as_ref()?.git_status.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .file_finder .get_or_insert_default() - .git_status + .git_status = value; }, }), metadata: None, @@ -1980,10 +2176,14 @@ pub(crate) fn settings_data(cx: &App) -> Vec { field: Box::new( SettingField { pick: |settings_content| { - &settings_content.project.worktree.file_scan_exclusions + settings_content + .project + .worktree + .file_scan_exclusions + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.project.worktree.file_scan_exclusions + write: |settings_content, value| { + settings_content.project.worktree.file_scan_exclusions = value; }, } .unimplemented(), @@ -1997,10 +2197,14 @@ pub(crate) fn settings_data(cx: &App) -> Vec { field: Box::new( SettingField { pick: |settings_content| { - &settings_content.project.worktree.file_scan_exclusions + settings_content + .project + .worktree + .file_scan_exclusions + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.project.worktree.file_scan_exclusions + write: |settings_content, value| { + settings_content.project.worktree.file_scan_exclusions = value; }, } .unimplemented(), @@ -2012,9 +2216,11 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Restore File State", description: "Restore previous file state when reopening", field: Box::new(SettingField { - pick: |settings_content| &settings_content.workspace.restore_on_file_reopen, - pick_mut: |settings_content| { - &mut settings_content.workspace.restore_on_file_reopen + pick: |settings_content| { + settings_content.workspace.restore_on_file_reopen.as_ref() + }, + write: |settings_content, value| { + settings_content.workspace.restore_on_file_reopen = value; }, }), metadata: None, @@ -2024,9 +2230,11 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Close on File Delete", description: "Automatically close files that have been deleted", field: Box::new(SettingField { - pick: |settings_content| &settings_content.workspace.close_on_file_delete, - pick_mut: |settings_content| { - &mut settings_content.workspace.close_on_file_delete + pick: |settings_content| { + settings_content.workspace.close_on_file_delete.as_ref() + }, + write: |settings_content, value| { + settings_content.workspace.close_on_file_delete = value; }, }), metadata: None, @@ -2043,17 +2251,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show the project panel button in the status bar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(project_panel) = &settings_content.project_panel { - &project_panel.button - } else { - &None - } + settings_content.project_panel.as_ref()?.button.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .project_panel .get_or_insert_default() - .button + .button = value; }, }), metadata: None, @@ -2064,17 +2268,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show the active language button in the status bar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(status_bar) = &settings_content.status_bar { - &status_bar.active_language_button - } else { - &None - } + settings_content + .status_bar + .as_ref()? + .active_language_button + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .status_bar .get_or_insert_default() - .active_language_button + .active_language_button = value; }, }), metadata: None, @@ -2085,17 +2289,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show the cursor position button in the status bar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(status_bar) = &settings_content.status_bar { - &status_bar.cursor_position_button - } else { - &None - } + settings_content + .status_bar + .as_ref()? + .cursor_position_button + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .status_bar .get_or_insert_default() - .cursor_position_button + .cursor_position_button = value; }, }), metadata: None, @@ -2106,14 +2310,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show the terminal button in the status bar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(terminal) = &settings_content.terminal { - &terminal.button - } else { - &None - } + settings_content.terminal.as_ref()?.button.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.terminal.get_or_insert_default().button + write: |settings_content, value| { + settings_content.terminal.get_or_insert_default().button = value; }, }), metadata: None, @@ -2124,14 +2324,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show the project diagnostics button in the status bar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(diagnostics) = &settings_content.diagnostics { - &diagnostics.button - } else { - &None - } + settings_content.diagnostics.as_ref()?.button.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.diagnostics.get_or_insert_default().button + write: |settings_content, value| { + settings_content.diagnostics.get_or_insert_default().button = value; }, }), metadata: None, @@ -2142,18 +2338,14 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show the project search button in the status bar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(search) = &settings_content.editor.search { - &search.button - } else { - &None - } + settings_content.editor.search.as_ref()?.button.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .editor .search .get_or_insert_default() - .button + .button = value; }, }), metadata: None, @@ -2164,14 +2356,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show the debugger button in the status bar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(debugger) = &settings_content.debugger { - &debugger.button - } else { - &None - } + settings_content.debugger.as_ref()?.button.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.debugger.get_or_insert_default().button + write: |settings_content, value| { + settings_content.debugger.get_or_insert_default().button = value; }, }), metadata: None, @@ -2183,17 +2371,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show the branch icon beside branch switcher in the titlebar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(title_bar) = &settings_content.title_bar { - &title_bar.show_branch_icon - } else { - &None - } + settings_content + .title_bar + .as_ref()? + .show_branch_icon + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .title_bar .get_or_insert_default() - .show_branch_icon + .show_branch_icon = value; }, }), metadata: None, @@ -2204,17 +2392,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show the branch name button in the titlebar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(title_bar) = &settings_content.title_bar { - &title_bar.show_branch_name - } else { - &None - } + settings_content + .title_bar + .as_ref()? + .show_branch_name + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .title_bar .get_or_insert_default() - .show_branch_name + .show_branch_name = value; }, }), metadata: None, @@ -2225,17 +2413,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show the project host and name in the titlebar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(title_bar) = &settings_content.title_bar { - &title_bar.show_project_items - } else { - &None - } + settings_content + .title_bar + .as_ref()? + .show_project_items + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .title_bar .get_or_insert_default() - .show_project_items + .show_project_items = value; }, }), metadata: None, @@ -2246,17 +2434,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show banners announcing new features in the titlebar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(title_bar) = &settings_content.title_bar { - &title_bar.show_onboarding_banner - } else { - &None - } + settings_content + .title_bar + .as_ref()? + .show_onboarding_banner + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .title_bar .get_or_insert_default() - .show_onboarding_banner + .show_onboarding_banner = value; }, }), metadata: None, @@ -2267,17 +2455,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show user picture in the titlebar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(title_bar) = &settings_content.title_bar { - &title_bar.show_user_picture - } else { - &None - } + settings_content + .title_bar + .as_ref()? + .show_user_picture + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .title_bar .get_or_insert_default() - .show_user_picture + .show_user_picture = value; }, }), metadata: None, @@ -2288,17 +2476,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show the sign in button in the titlebar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(title_bar) = &settings_content.title_bar { - &title_bar.show_sign_in - } else { - &None - } + settings_content.title_bar.as_ref()?.show_sign_in.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .title_bar .get_or_insert_default() - .show_sign_in + .show_sign_in = value; }, }), metadata: None, @@ -2309,17 +2493,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show the menus in the titlebar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(title_bar) = &settings_content.title_bar { - &title_bar.show_menus - } else { - &None - } + settings_content.title_bar.as_ref()?.show_menus.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .title_bar .get_or_insert_default() - .show_menus + .show_menus = value; }, }), metadata: None, @@ -2330,15 +2510,9 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Show Tab Bar", description: "Show the tab bar in the editor", field: Box::new(SettingField { - pick: |settings_content| { - if let Some(tab_bar) = &settings_content.tab_bar { - &tab_bar.show - } else { - &None - } - }, - pick_mut: |settings_content| { - &mut settings_content.tab_bar.get_or_insert_default().show + pick: |settings_content| settings_content.tab_bar.as_ref()?.show.as_ref(), + write: |settings_content, value| { + settings_content.tab_bar.get_or_insert_default().show = value; }, }), metadata: None, @@ -2349,14 +2523,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show the Git file status on a tab item", field: Box::new(SettingField { pick: |settings_content| { - if let Some(tabs) = &settings_content.tabs { - &tabs.git_status - } else { - &None - } + settings_content.tabs.as_ref()?.git_status.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.tabs.get_or_insert_default().git_status + write: |settings_content, value| { + settings_content.tabs.get_or_insert_default().git_status = value; }, }), metadata: None, @@ -2367,14 +2537,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show the file icon for a tab", field: Box::new(SettingField { pick: |settings_content| { - if let Some(tabs) = &settings_content.tabs { - &tabs.file_icons - } else { - &None - } + settings_content.tabs.as_ref()?.file_icons.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.tabs.get_or_insert_default().file_icons + write: |settings_content, value| { + settings_content.tabs.get_or_insert_default().file_icons = value; }, }), metadata: None, @@ -2385,14 +2551,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Position of the close button in a tab", field: Box::new(SettingField { pick: |settings_content| { - if let Some(tabs) = &settings_content.tabs { - &tabs.close_position - } else { - &None - } + settings_content.tabs.as_ref()?.close_position.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.tabs.get_or_insert_default().close_position + write: |settings_content, value| { + settings_content.tabs.get_or_insert_default().close_position = value; }, }), metadata: None, @@ -2406,8 +2568,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { // is complex, so I'm going to come back to this later field: Box::new( SettingField { - pick: |settings_content| &settings_content.workspace.max_tabs, - pick_mut: |settings_content| &mut settings_content.workspace.max_tabs, + pick: |settings_content| settings_content.workspace.max_tabs.as_ref(), + write: |settings_content, value| { + settings_content.workspace.max_tabs = value; + }, } .unimplemented(), ), @@ -2418,17 +2582,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show the navigation history buttons in the tab bar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(tab_bar) = &settings_content.tab_bar { - &tab_bar.show_nav_history_buttons - } else { - &None - } + settings_content + .tab_bar + .as_ref()? + .show_nav_history_buttons + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .tab_bar .get_or_insert_default() - .show_nav_history_buttons + .show_nav_history_buttons = value; }, }), metadata: None, @@ -2440,17 +2604,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "What to do after closing the current tab", field: Box::new(SettingField { pick: |settings_content| { - if let Some(tabs) = &settings_content.tabs { - &tabs.activate_on_close - } else { - &None - } + settings_content.tabs.as_ref()?.activate_on_close.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .tabs .get_or_insert_default() - .activate_on_close + .activate_on_close = value; }, }), metadata: None, @@ -2461,17 +2621,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Which files containing diagnostic errors/warnings to mark in the tabs", field: Box::new(SettingField { pick: |settings_content| { - if let Some(tabs) = &settings_content.tabs { - &tabs.show_diagnostics - } else { - &None - } + settings_content.tabs.as_ref()?.show_diagnostics.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .tabs .get_or_insert_default() - .show_diagnostics + .show_diagnostics = value; }, }), metadata: None, @@ -2482,17 +2638,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Controls the appearance behavior of the tab's close button", field: Box::new(SettingField { pick: |settings_content| { - if let Some(tabs) = &settings_content.tabs { - &tabs.show_close_button - } else { - &None - } + settings_content.tabs.as_ref()?.show_close_button.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .tabs .get_or_insert_default() - .show_close_button + .show_close_button = value; }, }), metadata: None, @@ -2504,17 +2656,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show opened editors as preview tabs", field: Box::new(SettingField { pick: |settings_content| { - if let Some(preview_tabs) = &settings_content.preview_tabs { - &preview_tabs.enabled - } else { - &None - } + settings_content.preview_tabs.as_ref()?.enabled.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .preview_tabs .get_or_insert_default() - .enabled + .enabled = value; }, }), metadata: None, @@ -2525,17 +2673,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether to open tabs in preview mode when selected from the file finder", field: Box::new(SettingField { pick: |settings_content| { - if let Some(preview_tabs) = &settings_content.preview_tabs { - &preview_tabs.enable_preview_from_file_finder - } else { - &None - } + settings_content + .preview_tabs + .as_ref()? + .enable_preview_from_file_finder + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .preview_tabs .get_or_insert_default() - .enable_preview_from_file_finder + .enable_preview_from_file_finder = value; }, }), metadata: None, @@ -2546,17 +2694,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether a preview tab gets replaced when code navigation is used to navigate away from the tab", field: Box::new(SettingField { pick: |settings_content| { - if let Some(preview_tabs) = &settings_content.preview_tabs { - &preview_tabs.enable_preview_from_code_navigation - } else { - &None - } + settings_content + .preview_tabs + .as_ref()? + .enable_preview_from_code_navigation + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .preview_tabs .get_or_insert_default() - .enable_preview_from_code_navigation + .enable_preview_from_code_navigation = value; }, }), metadata: None, @@ -2567,9 +2715,11 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Bottom Dock Layout", description: "Layout mode for the bottom dock", field: Box::new(SettingField { - pick: |settings_content| &settings_content.workspace.bottom_dock_layout, - pick_mut: |settings_content| { - &mut settings_content.workspace.bottom_dock_layout + pick: |settings_content| { + settings_content.workspace.bottom_dock_layout.as_ref() + }, + write: |settings_content, value| { + settings_content.workspace.bottom_dock_layout = value; }, }), metadata: None, @@ -2581,20 +2731,19 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Left padding for centered layout", field: Box::new(SettingField { pick: |settings_content| { - if let Some(centered_layout) = - &settings_content.workspace.centered_layout - { - ¢ered_layout.left_padding - } else { - &None - } + settings_content + .workspace + .centered_layout + .as_ref()? + .left_padding + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .workspace .centered_layout .get_or_insert_default() - .left_padding + .left_padding = value; }, }), metadata: None, @@ -2605,33 +2754,34 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Right padding for centered layout", field: Box::new(SettingField { pick: |settings_content| { - if let Some(centered_layout) = - &settings_content.workspace.centered_layout - { - ¢ered_layout.right_padding - } else { - &None - } + settings_content + .workspace + .centered_layout + .as_ref()? + .right_padding + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .workspace .centered_layout .get_or_insert_default() - .right_padding + .right_padding = value; }, }), metadata: None, }), SettingsPageItem::SectionHeader("Window"), - // todo(settings_ui): Should we filter by platform? + // todo(settings_ui): Should we filter by platform.as_ref()? SettingsPageItem::SettingItem(SettingItem { title: "Use System Window Tabs", description: "(macOS only) Whether to allow windows to tab together", field: Box::new(SettingField { - pick: |settings_content| &settings_content.workspace.use_system_window_tabs, - pick_mut: |settings_content| { - &mut settings_content.workspace.use_system_window_tabs + pick: |settings_content| { + settings_content.workspace.use_system_window_tabs.as_ref() + }, + write: |settings_content, value| { + settings_content.workspace.use_system_window_tabs = value; }, }), metadata: None, @@ -2642,20 +2792,20 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Inactive Opacity", description: "Opacity of inactive panels (0.0 - 1.0)", field: Box::new(SettingField { - pick: |settings_content| match settings_content - .workspace - .active_pane_modifiers - .as_ref() - { - Some(modifiers) => &modifiers.inactive_opacity, - None => &None, + pick: |settings_content| { + settings_content + .workspace + .active_pane_modifiers + .as_ref()? + .inactive_opacity + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .workspace .active_pane_modifiers .get_or_insert_default() - .inactive_opacity + .inactive_opacity = value; }, }), metadata: None, @@ -2665,20 +2815,20 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Border Size", description: "Size of the border surrounding the active pane", field: Box::new(SettingField { - pick: |settings_content| match settings_content - .workspace - .active_pane_modifiers - .as_ref() - { - Some(modifiers) => &modifiers.border_size, - None => &None, + pick: |settings_content| { + settings_content + .workspace + .active_pane_modifiers + .as_ref()? + .border_size + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .workspace .active_pane_modifiers .get_or_insert_default() - .border_size + .border_size = value; }, }), metadata: None, @@ -2688,8 +2838,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Zoomed Padding", description: "Show padding for zoomed panes", field: Box::new(SettingField { - pick: |settings_content| &settings_content.workspace.zoomed_padding, - pick_mut: |settings_content| &mut settings_content.workspace.zoomed_padding, + pick: |settings_content| settings_content.workspace.zoomed_padding.as_ref(), + write: |settings_content, value| { + settings_content.workspace.zoomed_padding = value; + }, }), metadata: None, files: USER, @@ -2700,10 +2852,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Direction to split vertically", field: Box::new(SettingField { pick: |settings_content| { - &settings_content.workspace.pane_split_direction_vertical + settings_content + .workspace + .pane_split_direction_vertical + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.workspace.pane_split_direction_vertical + write: |settings_content, value| { + settings_content.workspace.pane_split_direction_vertical = value; }, }), metadata: None, @@ -2714,10 +2869,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Direction to split horizontally", field: Box::new(SettingField { pick: |settings_content| { - &settings_content.workspace.pane_split_direction_horizontal + settings_content + .workspace + .pane_split_direction_horizontal + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.workspace.pane_split_direction_horizontal + write: |settings_content, value| { + settings_content.workspace.pane_split_direction_horizontal = value; }, }), metadata: None, @@ -2734,14 +2892,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Where to dock the project panel", field: Box::new(SettingField { pick: |settings_content| { - if let Some(project_panel) = &settings_content.project_panel { - &project_panel.dock - } else { - &None - } + settings_content.project_panel.as_ref()?.dock.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.project_panel.get_or_insert_default().dock + write: |settings_content, value| { + settings_content.project_panel.get_or_insert_default().dock = value; }, }), metadata: None, @@ -2752,17 +2906,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Default width of the project panel in pixels", field: Box::new(SettingField { pick: |settings_content| { - if let Some(project_panel) = &settings_content.project_panel { - &project_panel.default_width - } else { - &None - } + settings_content + .project_panel + .as_ref()? + .default_width + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .project_panel .get_or_insert_default() - .default_width + .default_width = value; }, }), metadata: None, @@ -2773,17 +2927,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether to hide the gitignore entries in the project panel", field: Box::new(SettingField { pick: |settings_content| { - if let Some(project_panel) = &settings_content.project_panel { - &project_panel.hide_gitignore - } else { - &None - } + settings_content + .project_panel + .as_ref()? + .hide_gitignore + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .project_panel .get_or_insert_default() - .hide_gitignore + .hide_gitignore = value; }, }), metadata: None, @@ -2794,17 +2948,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Spacing between worktree entries in the project panel", field: Box::new(SettingField { pick: |settings_content| { - if let Some(project_panel) = &settings_content.project_panel { - &project_panel.entry_spacing - } else { - &None - } + settings_content + .project_panel + .as_ref()? + .entry_spacing + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .project_panel .get_or_insert_default() - .entry_spacing + .entry_spacing = value; }, }), metadata: None, @@ -2815,17 +2969,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show file icons in the project panel", field: Box::new(SettingField { pick: |settings_content| { - if let Some(project_panel) = &settings_content.project_panel { - &project_panel.file_icons - } else { - &None - } + settings_content.project_panel.as_ref()?.file_icons.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .project_panel .get_or_insert_default() - .file_icons + .file_icons = value; }, }), metadata: None, @@ -2836,17 +2986,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether to show folder icons or chevrons for directories in the project panel", field: Box::new(SettingField { pick: |settings_content| { - if let Some(project_panel) = &settings_content.project_panel { - &project_panel.folder_icons - } else { - &None - } + settings_content + .project_panel + .as_ref()? + .folder_icons + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .project_panel .get_or_insert_default() - .folder_icons + .folder_icons = value; }, }), metadata: None, @@ -2857,17 +3007,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show the git status in the project panel", field: Box::new(SettingField { pick: |settings_content| { - if let Some(project_panel) = &settings_content.project_panel { - &project_panel.git_status - } else { - &None - } + settings_content.project_panel.as_ref()?.git_status.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .project_panel .get_or_insert_default() - .git_status + .git_status = value; }, }), metadata: None, @@ -2878,17 +3024,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Amount of indentation for nested items", field: Box::new(SettingField { pick: |settings_content| { - if let Some(project_panel) = &settings_content.project_panel { - &project_panel.indent_size - } else { - &None - } + settings_content + .project_panel + .as_ref()? + .indent_size + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .project_panel .get_or_insert_default() - .indent_size + .indent_size = value; }, }), metadata: None, @@ -2899,17 +3045,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether to reveal entries in the project panel automatically when a corresponding project entry becomes active", field: Box::new(SettingField { pick: |settings_content| { - if let Some(project_panel) = &settings_content.project_panel { - &project_panel.auto_reveal_entries - } else { - &None - } + settings_content + .project_panel + .as_ref()? + .auto_reveal_entries + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .project_panel .get_or_insert_default() - .auto_reveal_entries + .auto_reveal_entries = value; }, }), metadata: None, @@ -2920,17 +3066,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether the project panel should open on startup", field: Box::new(SettingField { pick: |settings_content| { - if let Some(project_panel) = &settings_content.project_panel { - &project_panel.starts_open - } else { - &None - } + settings_content + .project_panel + .as_ref()? + .starts_open + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .project_panel .get_or_insert_default() - .starts_open + .starts_open = value; }, }), metadata: None, @@ -2941,45 +3087,44 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether to fold directories automatically and show compact folders when a directory has only one subdirectory inside", field: Box::new(SettingField { pick: |settings_content| { - if let Some(project_panel) = &settings_content.project_panel { - &project_panel.auto_fold_dirs - } else { - &None - } + settings_content + .project_panel + .as_ref()? + .auto_fold_dirs + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .project_panel .get_or_insert_default() - .auto_fold_dirs + .auto_fold_dirs = value; }, }), metadata: None, files: USER, }), SettingsPageItem::SettingItem(SettingItem { - title: "Scrollbar Show", + title: "Show Scrollbar", description: "Show the scrollbar in the project panel", field: Box::new(SettingField { pick: |settings_content| { - if let Some(project_panel) = &settings_content.project_panel - && let Some(scrollbar) = &project_panel.scrollbar - && scrollbar.show.is_some() - { - &scrollbar.show - } else if let Some(scrollbar) = &settings_content.editor.scrollbar { - &scrollbar.show - } else { - &None - } + show_scrollbar_or_editor(settings_content, |settings_content| { + settings_content + .project_panel + .as_ref()? + .scrollbar + .as_ref()? + .show + .as_ref() + }) }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .project_panel .get_or_insert_default() .scrollbar .get_or_insert_default() - .show + .show = value; }, }), metadata: None, @@ -2990,17 +3135,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Which files containing diagnostic errors/warnings to mark in the project panel", field: Box::new(SettingField { pick: |settings_content| { - if let Some(project_panel) = &settings_content.project_panel { - &project_panel.show_diagnostics - } else { - &None - } + settings_content + .project_panel + .as_ref()? + .show_diagnostics + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .project_panel .get_or_insert_default() - .show_diagnostics + .show_diagnostics = value; }, }), metadata: None, @@ -3011,17 +3156,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether to stick parent directories at top of the project panel", field: Box::new(SettingField { pick: |settings_content| { - if let Some(project_panel) = &settings_content.project_panel { - &project_panel.sticky_scroll - } else { - &None - } + settings_content + .project_panel + .as_ref()? + .sticky_scroll + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .project_panel .get_or_insert_default() - .sticky_scroll + .sticky_scroll = value; }, }), metadata: None, @@ -3034,23 +3179,21 @@ pub(crate) fn settings_data(cx: &App) -> Vec { field: Box::new( SettingField { pick: |settings_content| { - if let Some(project_panel) = &settings_content.project_panel { - if let Some(indent_guides) = &project_panel.indent_guides { - &indent_guides.show - } else { - &None - } - } else { - &None - } + settings_content + .project_panel + .as_ref()? + .indent_guides + .as_ref()? + .show + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .project_panel .get_or_insert_default() .indent_guides .get_or_insert_default() - .show + .show = value; }, } .unimplemented(), @@ -3062,17 +3205,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether to enable drag-and-drop operations in the project panel", field: Box::new(SettingField { pick: |settings_content| { - if let Some(project_panel) = &settings_content.project_panel { - &project_panel.drag_and_drop - } else { - &None - } + settings_content + .project_panel + .as_ref()? + .drag_and_drop + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .project_panel .get_or_insert_default() - .drag_and_drop + .drag_and_drop = value; }, }), metadata: None, @@ -3083,17 +3226,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether to hide the root entry when only one folder is open in the window", field: Box::new(SettingField { pick: |settings_content| { - if let Some(project_panel) = &settings_content.project_panel { - &project_panel.hide_root - } else { - &None - } + settings_content.project_panel.as_ref()?.hide_root.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .project_panel .get_or_insert_default() - .hide_root + .hide_root = value; }, }), metadata: None, @@ -3104,17 +3243,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether to hide the hidden entries in the project panel", field: Box::new(SettingField { pick: |settings_content| { - if let Some(project_panel) = &settings_content.project_panel { - &project_panel.hide_hidden - } else { - &None - } + settings_content + .project_panel + .as_ref()? + .hide_hidden + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .project_panel .get_or_insert_default() - .hide_hidden + .hide_hidden = value; }, }), metadata: None, @@ -3125,17 +3264,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether to automatically open files when pasting them in the project panel", field: Box::new(SettingField { pick: |settings_content| { - if let Some(project_panel) = &settings_content.project_panel { - &project_panel.open_file_on_paste - } else { - &None - } + settings_content + .project_panel + .as_ref()? + .open_file_on_paste + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .project_panel .get_or_insert_default() - .open_file_on_paste + .open_file_on_paste = value; }, }), metadata: None, @@ -3146,15 +3285,9 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Terminal Dock", description: "Where to dock the terminal panel", field: Box::new(SettingField { - pick: |settings_content| { - if let Some(terminal) = &settings_content.terminal { - &terminal.dock - } else { - &None - } - }, - pick_mut: |settings_content| { - &mut settings_content.terminal.get_or_insert_default().dock + pick: |settings_content| settings_content.terminal.as_ref()?.dock.as_ref(), + write: |settings_content, value| { + settings_content.terminal.get_or_insert_default().dock = value; }, }), metadata: None, @@ -3166,17 +3299,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show the outline panel button in the status bar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(outline_panel) = &settings_content.outline_panel { - &outline_panel.button - } else { - &None - } + settings_content.outline_panel.as_ref()?.button.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .outline_panel .get_or_insert_default() - .button + .button = value; }, }), metadata: None, @@ -3187,14 +3316,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Where to dock the outline panel", field: Box::new(SettingField { pick: |settings_content| { - if let Some(outline_panel) = &settings_content.outline_panel { - &outline_panel.dock - } else { - &None - } + settings_content.outline_panel.as_ref()?.dock.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.outline_panel.get_or_insert_default().dock + write: |settings_content, value| { + settings_content.outline_panel.get_or_insert_default().dock = value; }, }), metadata: None, @@ -3205,17 +3330,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Default width of the outline panel in pixels", field: Box::new(SettingField { pick: |settings_content| { - if let Some(outline_panel) = &settings_content.outline_panel { - &outline_panel.default_width - } else { - &None - } + settings_content + .outline_panel + .as_ref()? + .default_width + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .outline_panel .get_or_insert_default() - .default_width + .default_width = value; }, }), metadata: None, @@ -3226,17 +3351,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show file icons in the outline panel", field: Box::new(SettingField { pick: |settings_content| { - if let Some(outline_panel) = &settings_content.outline_panel { - &outline_panel.file_icons - } else { - &None - } + settings_content.outline_panel.as_ref()?.file_icons.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .outline_panel .get_or_insert_default() - .file_icons + .file_icons = value; }, }), metadata: None, @@ -3247,17 +3368,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether to show folder icons or chevrons for directories in the outline panel", field: Box::new(SettingField { pick: |settings_content| { - if let Some(outline_panel) = &settings_content.outline_panel { - &outline_panel.folder_icons - } else { - &None - } + settings_content + .outline_panel + .as_ref()? + .folder_icons + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .outline_panel .get_or_insert_default() - .folder_icons + .folder_icons = value; }, }), metadata: None, @@ -3268,17 +3389,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show the git status in the outline panel", field: Box::new(SettingField { pick: |settings_content| { - if let Some(outline_panel) = &settings_content.outline_panel { - &outline_panel.git_status - } else { - &None - } + settings_content.outline_panel.as_ref()?.git_status.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .outline_panel .get_or_insert_default() - .git_status + .git_status = value; }, }), metadata: None, @@ -3289,17 +3406,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Amount of indentation for nested items", field: Box::new(SettingField { pick: |settings_content| { - if let Some(outline_panel) = &settings_content.outline_panel { - &outline_panel.indent_size - } else { - &None - } + settings_content + .outline_panel + .as_ref()? + .indent_size + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .outline_panel .get_or_insert_default() - .indent_size + .indent_size = value; }, }), metadata: None, @@ -3310,17 +3427,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether to reveal when a corresponding outline entry becomes active", field: Box::new(SettingField { pick: |settings_content| { - if let Some(outline_panel) = &settings_content.outline_panel { - &outline_panel.auto_reveal_entries - } else { - &None - } + settings_content + .outline_panel + .as_ref()? + .auto_reveal_entries + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .outline_panel .get_or_insert_default() - .auto_reveal_entries + .auto_reveal_entries = value; }, }), metadata: None, @@ -3331,17 +3448,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether to fold directories automatically when a directory contains only one subdirectory", field: Box::new(SettingField { pick: |settings_content| { - if let Some(outline_panel) = &settings_content.outline_panel { - &outline_panel.auto_fold_dirs - } else { - &None - } + settings_content + .outline_panel + .as_ref()? + .auto_fold_dirs + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .outline_panel .get_or_insert_default() - .auto_fold_dirs + .auto_fold_dirs = value; }, }), metadata: None, @@ -3354,23 +3471,21 @@ pub(crate) fn settings_data(cx: &App) -> Vec { field: Box::new( SettingField { pick: |settings_content| { - if let Some(outline_panel) = &settings_content.outline_panel { - if let Some(indent_guides) = &outline_panel.indent_guides { - &indent_guides.show - } else { - &None - } - } else { - &None - } + settings_content + .outline_panel + .as_ref()? + .indent_guides + .as_ref()? + .show + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .outline_panel .get_or_insert_default() .indent_guides .get_or_insert_default() - .show + .show = value; }, } .unimplemented(), @@ -3383,14 +3498,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show the Git panel button in the status bar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(git_panel) = &settings_content.git_panel { - &git_panel.button - } else { - &None - } + settings_content.git_panel.as_ref()?.button.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.git_panel.get_or_insert_default().button + write: |settings_content, value| { + settings_content.git_panel.get_or_insert_default().button = value; }, }), metadata: None, @@ -3400,15 +3511,9 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Git Panel Dock", description: "Where to dock the Git panel", field: Box::new(SettingField { - pick: |settings_content| { - if let Some(git_panel) = &settings_content.git_panel { - &git_panel.dock - } else { - &None - } - }, - pick_mut: |settings_content| { - &mut settings_content.git_panel.get_or_insert_default().dock + pick: |settings_content| settings_content.git_panel.as_ref()?.dock.as_ref(), + write: |settings_content, value| { + settings_content.git_panel.get_or_insert_default().dock = value; }, }), metadata: None, @@ -3419,17 +3524,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Default width of the Git panel in pixels", field: Box::new(SettingField { pick: |settings_content| { - if let Some(git_panel) = &settings_content.git_panel { - &git_panel.default_width - } else { - &None - } + settings_content.git_panel.as_ref()?.default_width.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .git_panel .get_or_insert_default() - .default_width + .default_width = value; }, }), metadata: None, @@ -3440,17 +3541,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "How entry statuses are displayed", field: Box::new(SettingField { pick: |settings_content| { - if let Some(git_panel) = &settings_content.git_panel { - &git_panel.status_style - } else { - &None - } + settings_content.git_panel.as_ref()?.status_style.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .git_panel .get_or_insert_default() - .status_style + .status_style = value; }, }), metadata: None, @@ -3461,17 +3558,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Default branch name will be when init.defaultBranch is not set in git", field: Box::new(SettingField { pick: |settings_content| { - if let Some(git_panel) = &settings_content.git_panel { - &git_panel.fallback_branch_name - } else { - &None - } + settings_content + .git_panel + .as_ref()? + .fallback_branch_name + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .git_panel .get_or_insert_default() - .fallback_branch_name + .fallback_branch_name = value; }, }), metadata: None, @@ -3482,17 +3579,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Enable to sort entries in the panel by path, disable to sort by status", field: Box::new(SettingField { pick: |settings_content| { - if let Some(git_panel) = &settings_content.git_panel { - &git_panel.sort_by_path - } else { - &None - } + settings_content.git_panel.as_ref()?.sort_by_path.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .git_panel .get_or_insert_default() - .sort_by_path + .sort_by_path = value; }, }), metadata: None, @@ -3503,17 +3596,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether to collapse untracked files in the diff panel", field: Box::new(SettingField { pick: |settings_content| { - if let Some(git_panel) = &settings_content.git_panel { - &git_panel.collapse_untracked_diff - } else { - &None - } + settings_content + .git_panel + .as_ref()? + .collapse_untracked_diff + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .git_panel .get_or_insert_default() - .collapse_untracked_diff + .collapse_untracked_diff = value; }, }), metadata: None, @@ -3523,20 +3616,24 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Scroll Bar", description: "How and when the scrollbar should be displayed", field: Box::new(SettingField { - pick: |settings_content| match &settings_content.git_panel { - Some(settings::GitPanelSettingsContent { - scrollbar: Some(scrollbar), - .. - }) => &scrollbar.show, - _ => &None, + pick: |settings_content| { + show_scrollbar_or_editor(settings_content, |settings_content| { + settings_content + .git_panel + .as_ref()? + .scrollbar + .as_ref()? + .show + .as_ref() + }) }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .git_panel .get_or_insert_default() .scrollbar .get_or_insert_default() - .show + .show = value; }, }), metadata: None, @@ -3547,15 +3644,9 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Debugger Panel Dock", description: "The dock position of the debug panel", field: Box::new(SettingField { - pick: |settings_content| { - if let Some(debugger) = &settings_content.debugger { - &debugger.dock - } else { - &None - } - }, - pick_mut: |settings_content| { - &mut settings_content.debugger.get_or_insert_default().dock + pick: |settings_content| settings_content.debugger.as_ref()?.dock.as_ref(), + write: |settings_content, value| { + settings_content.debugger.get_or_insert_default().dock = value; }, }), metadata: None, @@ -3567,17 +3658,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show the notification panel button in the status bar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(notification_panel) = &settings_content.notification_panel { - ¬ification_panel.button - } else { - &None - } + settings_content + .notification_panel + .as_ref()? + .button + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .notification_panel .get_or_insert_default() - .button + .button = value; }, }), metadata: None, @@ -3588,17 +3679,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Where to dock the notification panel", field: Box::new(SettingField { pick: |settings_content| { - if let Some(notification_panel) = &settings_content.notification_panel { - ¬ification_panel.dock - } else { - &None - } + settings_content.notification_panel.as_ref()?.dock.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .notification_panel .get_or_insert_default() - .dock + .dock = value; }, }), metadata: None, @@ -3609,17 +3696,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Default width of the notification panel in pixels", field: Box::new(SettingField { pick: |settings_content| { - if let Some(notification_panel) = &settings_content.notification_panel { - ¬ification_panel.default_width - } else { - &None - } + settings_content + .notification_panel + .as_ref()? + .default_width + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .notification_panel .get_or_insert_default() - .default_width + .default_width = value; }, }), metadata: None, @@ -3631,18 +3718,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show the collaboration panel button in the status bar", field: Box::new(SettingField { pick: |settings_content| { - if let Some(collaboration_panel) = &settings_content.collaboration_panel - { - &collaboration_panel.button - } else { - &None - } + settings_content + .collaboration_panel + .as_ref()? + .button + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .collaboration_panel .get_or_insert_default() - .button + .button = value; }, }), metadata: None, @@ -3653,18 +3739,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Where to dock the collaboration panel", field: Box::new(SettingField { pick: |settings_content| { - if let Some(collaboration_panel) = &settings_content.collaboration_panel - { - &collaboration_panel.dock - } else { - &None - } + settings_content.collaboration_panel.as_ref()?.dock.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .collaboration_panel .get_or_insert_default() - .dock + .dock = value; }, }), metadata: None, @@ -3675,18 +3756,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Default width of the collaboration panel in pixels", field: Box::new(SettingField { pick: |settings_content| { - if let Some(collaboration_panel) = &settings_content.collaboration_panel - { - &collaboration_panel.default_width - } else { - &None - } + settings_content + .collaboration_panel + .as_ref()? + .default_width + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .collaboration_panel .get_or_insert_default() - .default_width + .default_width = value; }, }), metadata: None, @@ -3697,15 +3777,9 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Agent Panel Button", description: "Whether to show the agent panel button in the status bar", field: Box::new(SettingField { - pick: |settings_content| { - if let Some(agent) = &settings_content.agent { - &agent.button - } else { - &None - } - }, - pick_mut: |settings_content| { - &mut settings_content.agent.get_or_insert_default().button + pick: |settings_content| settings_content.agent.as_ref()?.button.as_ref(), + write: |settings_content, value| { + settings_content.agent.get_or_insert_default().button = value; }, }), metadata: None, @@ -3715,15 +3789,9 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Agent Panel Dock", description: "Where to dock the agent panel.", field: Box::new(SettingField { - pick: |settings_content| { - if let Some(agent) = &settings_content.agent { - &agent.dock - } else { - &None - } - }, - pick_mut: |settings_content| { - &mut settings_content.agent.get_or_insert_default().dock + pick: |settings_content| settings_content.agent.as_ref()?.dock.as_ref(), + write: |settings_content, value| { + settings_content.agent.get_or_insert_default().dock = value; }, }), metadata: None, @@ -3734,14 +3802,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Default width when the agent panel is docked to the left or right", field: Box::new(SettingField { pick: |settings_content| { - if let Some(agent) = &settings_content.agent { - &agent.default_width - } else { - &None - } + settings_content.agent.as_ref()?.default_width.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.agent.get_or_insert_default().default_width + write: |settings_content, value| { + settings_content.agent.get_or_insert_default().default_width = value; }, }), metadata: None, @@ -3752,17 +3816,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Default height when the agent panel is docked to the bottom", field: Box::new(SettingField { pick: |settings_content| { - if let Some(agent) = &settings_content.agent { - &agent.default_height - } else { - &None - } + settings_content.agent.as_ref()?.default_height.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .agent .get_or_insert_default() - .default_height + .default_height = value; }, }), metadata: None, @@ -3779,17 +3839,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Determines the stepping granularity for debug operations", field: Box::new(SettingField { pick: |settings_content| { - if let Some(debugger) = &settings_content.debugger { - &debugger.stepping_granularity - } else { - &None - } + settings_content + .debugger + .as_ref()? + .stepping_granularity + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .debugger .get_or_insert_default() - .stepping_granularity + .stepping_granularity = value; }, }), metadata: None, @@ -3800,17 +3860,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether breakpoints should be reused across Zed sessions", field: Box::new(SettingField { pick: |settings_content| { - if let Some(debugger) = &settings_content.debugger { - &debugger.save_breakpoints - } else { - &None - } + settings_content + .debugger + .as_ref()? + .save_breakpoints + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .debugger .get_or_insert_default() - .save_breakpoints + .save_breakpoints = value; }, }), metadata: None, @@ -3821,14 +3881,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Time in milliseconds until timeout error when connecting to a TCP debug adapter", field: Box::new(SettingField { pick: |settings_content| { - if let Some(debugger) = &settings_content.debugger { - &debugger.timeout - } else { - &None - } + settings_content.debugger.as_ref()?.timeout.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.debugger.get_or_insert_default().timeout + write: |settings_content, value| { + settings_content.debugger.get_or_insert_default().timeout = value; }, }), metadata: None, @@ -3839,17 +3895,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether to log messages between active debug adapters and Zed", field: Box::new(SettingField { pick: |settings_content| { - if let Some(debugger) = &settings_content.debugger { - &debugger.log_dap_communications - } else { - &None - } + settings_content + .debugger + .as_ref()? + .log_dap_communications + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .debugger .get_or_insert_default() - .log_dap_communications + .log_dap_communications = value; }, }), metadata: None, @@ -3860,17 +3916,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether to format DAP messages when adding them to debug adapter logger", field: Box::new(SettingField { pick: |settings_content| { - if let Some(debugger) = &settings_content.debugger { - &debugger.format_dap_log_messages - } else { - &None - } + settings_content + .debugger + .as_ref()? + .format_dap_log_messages + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .debugger .get_or_insert_default() - .format_dap_log_messages + .format_dap_log_messages = value; }, }), metadata: None, @@ -3888,18 +3944,14 @@ pub(crate) fn settings_data(cx: &App) -> Vec { field: Box::new( SettingField { pick: |settings_content| { - if let Some(terminal) = &settings_content.terminal { - &terminal.project.shell - } else { - &None - } + settings_content.terminal.as_ref()?.project.shell.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .terminal .get_or_insert_default() .project - .shell + .shell = value; }, } .unimplemented(), @@ -3913,18 +3965,19 @@ pub(crate) fn settings_data(cx: &App) -> Vec { field: Box::new( SettingField { pick: |settings_content| { - if let Some(terminal) = &settings_content.terminal { - &terminal.project.working_directory - } else { - &None - } + settings_content + .terminal + .as_ref()? + .project + .working_directory + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .terminal .get_or_insert_default() .project - .working_directory + .working_directory = value; }, } .unimplemented(), @@ -3938,18 +3991,14 @@ pub(crate) fn settings_data(cx: &App) -> Vec { field: Box::new( SettingField { pick: |settings_content| { - if let Some(terminal) = &settings_content.terminal { - &terminal.project.env - } else { - &None - } + settings_content.terminal.as_ref()?.project.env.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .terminal .get_or_insert_default() .project - .env + .env = value; }, } .unimplemented(), @@ -3963,18 +4012,19 @@ pub(crate) fn settings_data(cx: &App) -> Vec { field: Box::new( SettingField { pick: |settings_content| { - if let Some(terminal) = &settings_content.terminal { - &terminal.project.detect_venv - } else { - &None - } + settings_content + .terminal + .as_ref()? + .project + .detect_venv + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .terminal .get_or_insert_default() .project - .detect_venv + .detect_venv = value; }, } .unimplemented(), @@ -3988,18 +4038,14 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Font size for terminal text. If not set, defaults to buffer font size", field: Box::new(SettingField { pick: |settings_content| { - if let Some(terminal) = &settings_content.terminal - && terminal.font_size.is_some() - { - &terminal.font_size - } else if settings_content.theme.buffer_font_size.is_some() { - &settings_content.theme.buffer_font_size - } else { - &None - } + settings_content + .terminal + .as_ref() + .and_then(|terminal| terminal.font_size.as_ref()) + .or(settings_content.theme.buffer_font_size.as_ref()) }, - pick_mut: |settings_content| { - &mut settings_content.terminal.get_or_insert_default().font_size + write: |settings_content, value| { + settings_content.terminal.get_or_insert_default().font_size = value; }, }), metadata: None, @@ -4010,21 +4056,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Font family for terminal text. If not set, defaults to buffer font family", field: Box::new(SettingField { pick: |settings_content| { - if let Some(terminal) = &settings_content.terminal - && terminal.font_family.is_some() - { - &terminal.font_family - } else if settings_content.theme.buffer_font_family.is_some() { - &settings_content.theme.buffer_font_family - } else { - &None - } + settings_content + .terminal + .as_ref() + .and_then(|terminal| terminal.font_family.as_ref()) + .or(settings_content.theme.buffer_font_family.as_ref()) }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .terminal .get_or_insert_default() - .font_family + .font_family = value; }, }), metadata: None, @@ -4036,17 +4078,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { field: Box::new( SettingField { pick: |settings_content| { - if let Some(terminal) = &settings_content.terminal { - &terminal.font_fallbacks - } else { - &None - } + settings_content + .terminal + .as_ref() + .and_then(|terminal| terminal.font_fallbacks.as_ref()) + .or(settings_content.theme.buffer_font_fallbacks.as_ref()) }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .terminal .get_or_insert_default() - .font_fallbacks + .font_fallbacks = value; }, } .unimplemented(), @@ -4059,17 +4101,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Font weight for terminal text in CSS weight units (100-900)", field: Box::new(SettingField { pick: |settings_content| { - if let Some(terminal) = &settings_content.terminal { - &terminal.font_weight - } else { - &None - } + settings_content.terminal.as_ref()?.font_weight.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .terminal .get_or_insert_default() - .font_weight + .font_weight = value; }, }), metadata: None, @@ -4081,17 +4119,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { field: Box::new( SettingField { pick: |settings_content| { - if let Some(terminal) = &settings_content.terminal { - &terminal.font_features - } else { - &None - } + settings_content + .terminal + .as_ref() + .and_then(|terminal| terminal.font_features.as_ref()) + .or(settings_content.theme.buffer_font_features.as_ref()) }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .terminal .get_or_insert_default() - .font_features + .font_features = value; }, } .unimplemented(), @@ -4106,17 +4144,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { field: Box::new( SettingField { pick: |settings_content| { - if let Some(terminal) = &settings_content.terminal { - &terminal.line_height - } else { - &None - } + settings_content.terminal.as_ref()?.line_height.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .terminal .get_or_insert_default() - .line_height + .line_height = value; }, } .unimplemented(), @@ -4129,17 +4163,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Default cursor shape for the terminal (bar, block, underline, or hollow)", field: Box::new(SettingField { pick: |settings_content| { - if let Some(terminal) = &settings_content.terminal { - &terminal.cursor_shape - } else { - &None - } + settings_content.terminal.as_ref()?.cursor_shape.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .terminal .get_or_insert_default() - .cursor_shape + .cursor_shape = value; }, }), metadata: None, @@ -4150,14 +4180,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Sets the cursor blinking behavior in the terminal", field: Box::new(SettingField { pick: |settings_content| { - if let Some(terminal) = &settings_content.terminal { - &terminal.blinking - } else { - &None - } + settings_content.terminal.as_ref()?.blinking.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.terminal.get_or_insert_default().blinking + write: |settings_content, value| { + settings_content.terminal.get_or_insert_default().blinking = value; }, }), metadata: None, @@ -4168,17 +4194,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether Alternate Scroll mode is active by default (converts mouse scroll to arrow keys in apps like vim)", field: Box::new(SettingField { pick: |settings_content| { - if let Some(terminal) = &settings_content.terminal { - &terminal.alternate_scroll - } else { - &None - } + settings_content + .terminal + .as_ref()? + .alternate_scroll + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .terminal .get_or_insert_default() - .alternate_scroll + .alternate_scroll = value; }, }), metadata: None, @@ -4189,17 +4215,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "The minimum APCA perceptual contrast between foreground and background colors (0-106)", field: Box::new(SettingField { pick: |settings_content| { - if let Some(terminal) = &settings_content.terminal { - &terminal.minimum_contrast - } else { - &None - } + settings_content + .terminal + .as_ref()? + .minimum_contrast + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .terminal .get_or_insert_default() - .minimum_contrast + .minimum_contrast = value; }, }), metadata: None, @@ -4211,17 +4237,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether the option key behaves as the meta key", field: Box::new(SettingField { pick: |settings_content| { - if let Some(terminal) = &settings_content.terminal { - &terminal.option_as_meta - } else { - &None - } + settings_content.terminal.as_ref()?.option_as_meta.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .terminal .get_or_insert_default() - .option_as_meta + .option_as_meta = value; }, }), metadata: None, @@ -4232,17 +4254,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether selecting text in the terminal automatically copies to the system clipboard", field: Box::new(SettingField { pick: |settings_content| { - if let Some(terminal) = &settings_content.terminal { - &terminal.copy_on_select - } else { - &None - } + settings_content.terminal.as_ref()?.copy_on_select.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .terminal .get_or_insert_default() - .copy_on_select + .copy_on_select = value; }, }), metadata: None, @@ -4253,17 +4271,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether to keep the text selection after copying it to the clipboard", field: Box::new(SettingField { pick: |settings_content| { - if let Some(terminal) = &settings_content.terminal { - &terminal.keep_selection_on_copy - } else { - &None - } + settings_content + .terminal + .as_ref()? + .keep_selection_on_copy + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .terminal .get_or_insert_default() - .keep_selection_on_copy + .keep_selection_on_copy = value; }, }), metadata: None, @@ -4275,17 +4293,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Default width when the terminal is docked to the left or right (in pixels)", field: Box::new(SettingField { pick: |settings_content| { - if let Some(terminal) = &settings_content.terminal { - &terminal.default_width - } else { - &None - } + settings_content.terminal.as_ref()?.default_width.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .terminal .get_or_insert_default() - .default_width + .default_width = value; }, }), metadata: None, @@ -4296,17 +4310,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Default height when the terminal is docked to the bottom (in pixels)", field: Box::new(SettingField { pick: |settings_content| { - if let Some(terminal) = &settings_content.terminal { - &terminal.default_height - } else { - &None - } + settings_content.terminal.as_ref()?.default_height.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .terminal .get_or_insert_default() - .default_height + .default_height = value; }, }), metadata: None, @@ -4318,17 +4328,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Maximum number of lines to keep in scrollback history (max: 100,000; 0 disables scrolling)", field: Box::new(SettingField { pick: |settings_content| { - if let Some(terminal) = &settings_content.terminal { - &terminal.max_scroll_history_lines - } else { - &None - } + settings_content + .terminal + .as_ref()? + .max_scroll_history_lines + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .terminal .get_or_insert_default() - .max_scroll_history_lines + .max_scroll_history_lines = value; }, }), metadata: None, @@ -4340,23 +4350,21 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Display the terminal title in breadcrumbs inside the terminal pane", field: Box::new(SettingField { pick: |settings_content| { - if let Some(terminal) = &settings_content.terminal { - if let Some(toolbar) = &terminal.toolbar { - &toolbar.breadcrumbs - } else { - &None - } - } else { - &None - } + settings_content + .terminal + .as_ref()? + .toolbar + .as_ref()? + .breadcrumbs + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .terminal .get_or_insert_default() .toolbar .get_or_insert_default() - .breadcrumbs + .breadcrumbs = value; }, }), metadata: None, @@ -4368,24 +4376,23 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "When to show the scrollbar in the terminal", field: Box::new(SettingField { pick: |settings_content| { - if let Some(terminal) = &settings_content.terminal - && let Some(scrollbar) = &terminal.scrollbar - && scrollbar.show.is_some() - { - &scrollbar.show - } else if let Some(scrollbar) = &settings_content.editor.scrollbar { - &scrollbar.show - } else { - &None - } + show_scrollbar_or_editor(settings_content, |settings_content| { + settings_content + .terminal + .as_ref()? + .scrollbar + .as_ref()? + .show + .as_ref() + }) }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .terminal .get_or_insert_default() .scrollbar .get_or_insert_default() - .show + .show = value; }, }), metadata: None, @@ -4401,15 +4408,9 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Visibilility", description: "Control whether git status is shown in the editor's gutter", field: Box::new(SettingField { - pick: |settings_content| { - if let Some(git) = &settings_content.git { - &git.git_gutter - } else { - &None - } - }, - pick_mut: |settings_content| { - &mut settings_content.git.get_or_insert_default().git_gutter + pick: |settings_content| settings_content.git.as_ref()?.git_gutter.as_ref(), + write: |settings_content, value| { + settings_content.git.get_or_insert_default().git_gutter = value; }, }), metadata: None, @@ -4421,14 +4422,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Debounce threshold in milliseconds after which changes are reflected in the git gutter", field: Box::new(SettingField { pick: |settings_content| { - if let Some(git) = &settings_content.git { - &git.gutter_debounce - } else { - &None - } + settings_content.git.as_ref()?.gutter_debounce.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.git.get_or_insert_default().gutter_debounce + write: |settings_content, value| { + settings_content.git.get_or_insert_default().gutter_debounce = value; }, }), metadata: None, @@ -4440,23 +4437,21 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether or not to show git blame data inline in the currently focused line", field: Box::new(SettingField { pick: |settings_content| { - if let Some(git) = &settings_content.git { - if let Some(inline_blame) = &git.inline_blame { - &inline_blame.enabled - } else { - &None - } - } else { - &None - } + settings_content + .git + .as_ref()? + .inline_blame + .as_ref()? + .enabled + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .git .get_or_insert_default() .inline_blame .get_or_insert_default() - .enabled + .enabled = value; }, }), metadata: None, @@ -4467,23 +4462,21 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "The delay after which the inline blame information is shown", field: Box::new(SettingField { pick: |settings_content| { - if let Some(git) = &settings_content.git { - if let Some(inline_blame) = &git.inline_blame { - &inline_blame.delay_ms - } else { - &None - } - } else { - &None - } + settings_content + .git + .as_ref()? + .inline_blame + .as_ref()? + .delay_ms + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .git .get_or_insert_default() .inline_blame .get_or_insert_default() - .delay_ms + .delay_ms = value; }, }), metadata: None, @@ -4494,23 +4487,21 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Padding between the end of the source line and the start of the inline blame in columns", field: Box::new(SettingField { pick: |settings_content| { - if let Some(git) = &settings_content.git { - if let Some(inline_blame) = &git.inline_blame { - &inline_blame.padding - } else { - &None - } - } else { - &None - } + settings_content + .git + .as_ref()? + .inline_blame + .as_ref()? + .padding + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .git .get_or_insert_default() .inline_blame .get_or_insert_default() - .padding + .padding = value; }, }), metadata: None, @@ -4520,20 +4511,22 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Minimum Column", description: "The minimum column number at which to show the inline blame information", field: Box::new(SettingField { - pick: |settings_content| match &settings_content.git { - Some(settings::GitSettings { - inline_blame: Some(inline_blame), - .. - }) => &inline_blame.min_column, - _ => &None, + pick: |settings_content| { + settings_content + .git + .as_ref()? + .inline_blame + .as_ref()? + .min_column + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .git .get_or_insert_default() .inline_blame .get_or_insert_default() - .min_column + .min_column = value; }, }), metadata: None, @@ -4544,23 +4537,21 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show commit summary as part of the inline blame", field: Box::new(SettingField { pick: |settings_content| { - if let Some(git) = &settings_content.git { - if let Some(inline_blame) = &git.inline_blame { - &inline_blame.show_commit_summary - } else { - &None - } - } else { - &None - } + settings_content + .git + .as_ref()? + .inline_blame + .as_ref()? + .show_commit_summary + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .git .get_or_insert_default() .inline_blame .get_or_insert_default() - .show_commit_summary + .show_commit_summary = value; }, }), metadata: None, @@ -4572,23 +4563,21 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show the avatar of the author of the commit", field: Box::new(SettingField { pick: |settings_content| { - if let Some(git) = &settings_content.git { - if let Some(blame) = &git.blame { - &blame.show_avatar - } else { - &None - } - } else { - &None - } + settings_content + .git + .as_ref()? + .blame + .as_ref()? + .show_avatar + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .git .get_or_insert_default() .blame .get_or_insert_default() - .show_avatar + .show_avatar = value; }, }), metadata: None, @@ -4600,23 +4589,21 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show author name as part of the commit information in branch picker", field: Box::new(SettingField { pick: |settings_content| { - if let Some(git) = &settings_content.git { - if let Some(branch_picker) = &git.branch_picker { - &branch_picker.show_author_name - } else { - &None - } - } else { - &None - } + settings_content + .git + .as_ref()? + .branch_picker + .as_ref()? + .show_author_name + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .git .get_or_insert_default() .branch_picker .get_or_insert_default() - .show_author_name + .show_author_name = value; }, }), metadata: None, @@ -4627,15 +4614,9 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Hunk Style", description: "How git hunks are displayed visually in the editor", field: Box::new(SettingField { - pick: |settings_content| { - if let Some(git) = &settings_content.git { - &git.hunk_style - } else { - &None - } - }, - pick_mut: |settings_content| { - &mut settings_content.git.get_or_insert_default().hunk_style + pick: |settings_content| settings_content.git.as_ref()?.hunk_style.as_ref(), + write: |settings_content, value| { + settings_content.git.get_or_insert_default().hunk_style = value; }, }), metadata: None, @@ -4652,14 +4633,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether the microphone should be muted when joining a channel or a call", field: Box::new(SettingField { pick: |settings_content| { - if let Some(calls) = &settings_content.calls { - &calls.mute_on_join - } else { - &None - } + settings_content.calls.as_ref()?.mute_on_join.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.calls.get_or_insert_default().mute_on_join + write: |settings_content, value| { + settings_content.calls.get_or_insert_default().mute_on_join = value; }, }), metadata: None, @@ -4670,14 +4647,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether your current project should be shared when joining an empty channel", field: Box::new(SettingField { pick: |settings_content| { - if let Some(calls) = &settings_content.calls { - &calls.share_on_join - } else { - &None - } + settings_content.calls.as_ref()?.share_on_join.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.calls.get_or_insert_default().share_on_join + write: |settings_content, value| { + settings_content.calls.get_or_insert_default().share_on_join = value; }, }), metadata: None, @@ -4689,14 +4662,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Opt into the new audio system", field: Box::new(SettingField { pick: |settings_content| { - if let Some(audio) = &settings_content.audio { - &audio.rodio_audio - } else { - &None - } + settings_content.audio.as_ref()?.rodio_audio.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.audio.get_or_insert_default().rodio_audio + write: |settings_content, value| { + settings_content.audio.get_or_insert_default().rodio_audio = value; }, }), metadata: None, @@ -4707,17 +4676,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Automatically adjust microphone volume (requires Rodio Audio)", field: Box::new(SettingField { pick: |settings_content| { - if let Some(audio) = &settings_content.audio { - &audio.auto_microphone_volume - } else { - &None - } + settings_content + .audio + .as_ref()? + .auto_microphone_volume + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .audio .get_or_insert_default() - .auto_microphone_volume + .auto_microphone_volume = value; }, }), metadata: None, @@ -4728,17 +4697,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Automatically adjust volume of other call members (requires Rodio Audio)", field: Box::new(SettingField { pick: |settings_content| { - if let Some(audio) = &settings_content.audio { - &audio.auto_speaker_volume - } else { - &None - } + settings_content + .audio + .as_ref()? + .auto_speaker_volume + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .audio .get_or_insert_default() - .auto_speaker_volume + .auto_speaker_volume = value; }, }), metadata: None, @@ -4748,15 +4717,9 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Denoise", description: "Remove background noises (requires Rodio Audio)", field: Box::new(SettingField { - pick: |settings_content| { - if let Some(audio) = &settings_content.audio { - &audio.denoise - } else { - &None - } - }, - pick_mut: |settings_content| { - &mut settings_content.audio.get_or_insert_default().denoise + pick: |settings_content| settings_content.audio.as_ref()?.denoise.as_ref(), + write: |settings_content, value| { + settings_content.audio.get_or_insert_default().denoise = value; }, }), metadata: None, @@ -4767,17 +4730,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Use audio parameters compatible with previous versions (requires Rodio Audio)", field: Box::new(SettingField { pick: |settings_content| { - if let Some(audio) = &settings_content.audio { - &audio.legacy_audio_compatible - } else { - &None - } + settings_content + .audio + .as_ref()? + .legacy_audio_compatible + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .audio .get_or_insert_default() - .legacy_audio_compatible + .legacy_audio_compatible = value; }, }), metadata: None, @@ -4793,8 +4756,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Disable AI", description: "Whether to disable all AI features in Zed", field: Box::new(SettingField { - pick: |settings_content| &settings_content.disable_ai, - pick_mut: |settings_content| &mut settings_content.disable_ai, + pick: |settings_content| settings_content.disable_ai.as_ref(), + write: |settings_content, value| { + settings_content.disable_ai = value; + }, }), metadata: None, files: USER, @@ -4805,17 +4770,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "When enabled, the agent can run potentially destructive actions without asking for your confirmation. This setting has no effect on external agents.", field: Box::new(SettingField { pick: |settings_content| { - if let Some(agent) = &settings_content.agent { - &agent.always_allow_tool_actions - } else { - &None - } + settings_content + .agent + .as_ref()? + .always_allow_tool_actions + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .agent .get_or_insert_default() - .always_allow_tool_actions + .always_allow_tool_actions = value; }, }), metadata: None, @@ -4826,17 +4791,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "When enabled, agent edits will also be displayed in single-file buffers for review", field: Box::new(SettingField { pick: |settings_content| { - if let Some(agent) = &settings_content.agent { - &agent.single_file_review - } else { - &None - } + settings_content.agent.as_ref()?.single_file_review.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .agent .get_or_insert_default() - .single_file_review + .single_file_review = value; }, }), metadata: None, @@ -4847,17 +4808,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Show voting thumbs up/down icon buttons for feedback on agent edits", field: Box::new(SettingField { pick: |settings_content| { - if let Some(agent) = &settings_content.agent { - &agent.enable_feedback - } else { - &None - } + settings_content.agent.as_ref()?.enable_feedback.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .agent .get_or_insert_default() - .enable_feedback + .enable_feedback = value; }, }), metadata: None, @@ -4868,17 +4825,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Where to show notifications when the agent has completed its response or needs confirmation before running a tool action", field: Box::new(SettingField { pick: |settings_content| { - if let Some(agent) = &settings_content.agent { - &agent.notify_when_agent_waiting - } else { - &None - } + settings_content + .agent + .as_ref()? + .notify_when_agent_waiting + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .agent .get_or_insert_default() - .notify_when_agent_waiting + .notify_when_agent_waiting = value; }, }), metadata: None, @@ -4889,17 +4846,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether to play a sound when the agent has either completed its response, or needs user input", field: Box::new(SettingField { pick: |settings_content| { - if let Some(agent) = &settings_content.agent { - &agent.play_sound_when_agent_done - } else { - &None - } + settings_content + .agent + .as_ref()? + .play_sound_when_agent_done + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .agent .get_or_insert_default() - .play_sound_when_agent_done + .play_sound_when_agent_done = value; }, }), metadata: None, @@ -4910,17 +4867,13 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether to have edit cards in the agent panel expanded, showing a preview of the diff", field: Box::new(SettingField { pick: |settings_content| { - if let Some(agent) = &settings_content.agent { - &agent.expand_edit_card - } else { - &None - } + settings_content.agent.as_ref()?.expand_edit_card.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .agent .get_or_insert_default() - .expand_edit_card + .expand_edit_card = value; }, }), metadata: None, @@ -4931,17 +4884,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether to have terminal cards in the agent panel expanded, showing the whole command output", field: Box::new(SettingField { pick: |settings_content| { - if let Some(agent) = &settings_content.agent { - &agent.expand_terminal_card - } else { - &None - } + settings_content + .agent + .as_ref()? + .expand_terminal_card + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .agent .get_or_insert_default() - .expand_terminal_card + .expand_terminal_card = value; }, }), metadata: None, @@ -4952,17 +4905,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Whether to always use cmd-enter (or ctrl-enter on Linux or Windows) to send messages", field: Box::new(SettingField { pick: |settings_content| { - if let Some(agent) = &settings_content.agent { - &agent.use_modifier_to_send - } else { - &None - } + settings_content + .agent + .as_ref()? + .use_modifier_to_send + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .agent .get_or_insert_default() - .use_modifier_to_send + .use_modifier_to_send = value; }, }), metadata: None, @@ -4973,17 +4926,17 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "Minimum number of lines to display in the agent message editor", field: Box::new(SettingField { pick: |settings_content| { - if let Some(agent) = &settings_content.agent { - &agent.message_editor_min_lines - } else { - &None - } + settings_content + .agent + .as_ref()? + .message_editor_min_lines + .as_ref() }, - pick_mut: |settings_content| { - &mut settings_content + write: |settings_content, value| { + settings_content .agent .get_or_insert_default() - .message_editor_min_lines + .message_editor_min_lines = value; }, }), metadata: None, @@ -5001,8 +4954,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { description: "The proxy to use for network requests", field: Box::new( SettingField { - pick: |settings_content| &settings_content.proxy, - pick_mut: |settings_content| &mut settings_content.proxy, + pick: |settings_content| settings_content.proxy.as_ref(), + write: |settings_content, value| { + settings_content.proxy = value; + }, } .unimplemented(), ), @@ -5016,8 +4971,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Server URL", description: "The URL of the Zed server to connect to", field: Box::new(SettingField { - pick: |settings_content| &settings_content.server_url, - pick_mut: |settings_content| &mut settings_content.server_url, + pick: |settings_content| settings_content.server_url.as_ref(), + write: |settings_content, value| { + settings_content.server_url = value; + }, }), metadata: Some(Box::new(SettingsFieldMetadata { placeholder: Some("https://zed.dev"), @@ -5040,8 +4997,8 @@ fn current_language() -> Option { fn language_settings_field( settings_content: &SettingsContent, - get: fn(&LanguageSettingsContent) -> &Option, -) -> &Option { + get: fn(&LanguageSettingsContent) -> Option<&T>, +) -> Option<&T> { let all_languages = &settings_content.project.all_languages; if let Some(current_language_name) = current_language() { if let Some(current_language) = all_languages.languages.0.get(¤t_language_name) { @@ -5057,8 +5014,9 @@ fn language_settings_field( fn language_settings_field_mut( settings_content: &mut SettingsContent, - get: fn(&mut LanguageSettingsContent) -> &mut Option, -) -> &mut Option { + value: Option, + write: fn(&mut LanguageSettingsContent, Option), +) { let all_languages = &mut settings_content.project.all_languages; let language_content = if let Some(current_language) = current_language() { all_languages @@ -5069,7 +5027,7 @@ fn language_settings_field_mut( } else { &mut all_languages.defaults }; - return get(language_content); + write(language_content, value); } fn language_settings_data() -> Vec { @@ -5080,10 +5038,12 @@ fn language_settings_data() -> Vec { description: "How many columns a tab should occupy", field: Box::new(SettingField { pick: |settings_content| { - language_settings_field(settings_content, |language| &language.tab_size) + language_settings_field(settings_content, |language| language.tab_size.as_ref()) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| &mut language.tab_size) + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.tab_size = value; + }) }, }), metadata: None, @@ -5094,11 +5054,13 @@ fn language_settings_data() -> Vec { description: "Whether to indent lines using tab characters, as opposed to multiple spaces", field: Box::new(SettingField { pick: |settings_content| { - language_settings_field(settings_content, |language| &language.hard_tabs) + language_settings_field(settings_content, |language| { + language.hard_tabs.as_ref() + }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.hard_tabs + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.hard_tabs = value; }) }, }), @@ -5110,11 +5072,13 @@ fn language_settings_data() -> Vec { description: "Whether indentation should be adjusted based on the context whilst typing", field: Box::new(SettingField { pick: |settings_content| { - language_settings_field(settings_content, |language| &language.auto_indent) + language_settings_field(settings_content, |language| { + language.auto_indent.as_ref() + }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.auto_indent + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.auto_indent = value; }) }, }), @@ -5127,12 +5091,12 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - &language.auto_indent_on_paste + language.auto_indent_on_paste.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.auto_indent_on_paste + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.auto_indent_on_paste = value; }) }, }), @@ -5145,11 +5109,13 @@ fn language_settings_data() -> Vec { description: "How to soft-wrap long lines of text", field: Box::new(SettingField { pick: |settings_content| { - language_settings_field(settings_content, |language| &language.soft_wrap) + language_settings_field(settings_content, |language| { + language.soft_wrap.as_ref() + }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.soft_wrap + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.soft_wrap = value; }) }, }), @@ -5161,11 +5127,13 @@ fn language_settings_data() -> Vec { description: "Show wrap guides in the editor", field: Box::new(SettingField { pick: |settings_content| { - language_settings_field(settings_content, |language| &language.show_wrap_guides) + language_settings_field(settings_content, |language| { + language.show_wrap_guides.as_ref() + }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.show_wrap_guides + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.show_wrap_guides = value; }) }, }), @@ -5178,12 +5146,12 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - &language.preferred_line_length + language.preferred_line_length.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.preferred_line_length + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.preferred_line_length = value; }) }, }), @@ -5196,11 +5164,13 @@ fn language_settings_data() -> Vec { field: Box::new( SettingField { pick: |settings_content| { - language_settings_field(settings_content, |language| &language.wrap_guides) + language_settings_field(settings_content, |language| { + language.wrap_guides.as_ref() + }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.wrap_guides + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.wrap_guides = value; }) }, } @@ -5214,11 +5184,13 @@ fn language_settings_data() -> Vec { description: "Controls where the `editor::Rewrap` action is allowed for this language", field: Box::new(SettingField { pick: |settings_content| { - language_settings_field(settings_content, |language| &language.allow_rewrap) + language_settings_field(settings_content, |language| { + language.allow_rewrap.as_ref() + }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.allow_rewrap + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.allow_rewrap = value; }) }, }), @@ -5232,16 +5204,15 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(indent_guides) = &language.indent_guides { - &indent_guides.enabled - } else { - &None - } + language + .indent_guides + .as_ref() + .and_then(|indent_guides| indent_guides.enabled.as_ref()) }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.indent_guides.get_or_insert_default().enabled + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.indent_guides.get_or_insert_default().enabled = value; }) }, }), @@ -5254,16 +5225,15 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(indent_guides) = &language.indent_guides { - &indent_guides.line_width - } else { - &None - } + language + .indent_guides + .as_ref() + .and_then(|indent_guides| indent_guides.line_width.as_ref()) }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.indent_guides.get_or_insert_default().line_width + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.indent_guides.get_or_insert_default().line_width = value; }) }, }), @@ -5276,19 +5246,18 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(indent_guides) = &language.indent_guides { - &indent_guides.active_line_width - } else { - &None - } + language + .indent_guides + .as_ref() + .and_then(|indent_guides| indent_guides.active_line_width.as_ref()) }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language .indent_guides .get_or_insert_default() - .active_line_width + .active_line_width = value; }) }, }), @@ -5301,16 +5270,15 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(indent_guides) = &language.indent_guides { - &indent_guides.coloring - } else { - &None - } + language + .indent_guides + .as_ref() + .and_then(|indent_guides| indent_guides.coloring.as_ref()) }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.indent_guides.get_or_insert_default().coloring + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.indent_guides.get_or_insert_default().coloring = value; }) }, }), @@ -5323,19 +5291,18 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(indent_guides) = &language.indent_guides { - &indent_guides.background_coloring - } else { - &None - } + language + .indent_guides + .as_ref() + .and_then(|indent_guides| indent_guides.background_coloring.as_ref()) }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language .indent_guides .get_or_insert_default() - .background_coloring + .background_coloring = value; }) }, }), @@ -5351,12 +5318,12 @@ fn language_settings_data() -> Vec { SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - &language.format_on_save + language.format_on_save.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.format_on_save + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.format_on_save = value; }) }, }, @@ -5370,12 +5337,12 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - &language.remove_trailing_whitespace_on_save + language.remove_trailing_whitespace_on_save.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.remove_trailing_whitespace_on_save + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.remove_trailing_whitespace_on_save = value; }) }, }), @@ -5388,12 +5355,12 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - &language.ensure_final_newline_on_save + language.ensure_final_newline_on_save.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.ensure_final_newline_on_save + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.ensure_final_newline_on_save = value; }) }, }), @@ -5406,11 +5373,13 @@ fn language_settings_data() -> Vec { field: Box::new( SettingField { pick: |settings_content| { - language_settings_field(settings_content, |language| &language.formatter) + language_settings_field(settings_content, |language| { + language.formatter.as_ref() + }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.formatter + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.formatter = value; }) }, } @@ -5425,12 +5394,12 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - &language.use_on_type_format + language.use_on_type_format.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.use_on_type_format + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.use_on_type_format = value; }) }, }), @@ -5444,12 +5413,12 @@ fn language_settings_data() -> Vec { SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - &language.code_actions_on_format + language.code_actions_on_format.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.code_actions_on_format + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.code_actions_on_format = value; }) }, } @@ -5464,11 +5433,13 @@ fn language_settings_data() -> Vec { description: "Whether to automatically type closing characters for you. For example, when you type (, Zed will automatically add a closing ) at the correct position", field: Box::new(SettingField { pick: |settings_content| { - language_settings_field(settings_content, |language| &language.use_autoclose) + language_settings_field(settings_content, |language| { + language.use_autoclose.as_ref() + }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.use_autoclose + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.use_autoclose = value; }) }, }), @@ -5481,12 +5452,12 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - &language.use_auto_surround + language.use_auto_surround.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.use_auto_surround + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.use_auto_surround = value; }) }, }), @@ -5499,12 +5470,12 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - &language.always_treat_brackets_as_autoclosed + language.always_treat_brackets_as_autoclosed.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.always_treat_brackets_as_autoclosed + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.always_treat_brackets_as_autoclosed = value; }) }, }), @@ -5518,15 +5489,12 @@ fn language_settings_data() -> Vec { // TODO(settings_ui): this setting should just be a bool pick: |settings_content| { language_settings_field(settings_content, |language| { - match language.jsx_tag_auto_close.as_ref() { - Some(s) => &s.enabled, - None => &None, - } + language.jsx_tag_auto_close.as_ref()?.enabled.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.jsx_tag_auto_close.get_or_insert_default().enabled + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.jsx_tag_auto_close.get_or_insert_default().enabled = value; }) }, }), @@ -5540,12 +5508,12 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - &language.show_edit_predictions + language.show_edit_predictions.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.show_edit_predictions + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.show_edit_predictions = value; }) }, }), @@ -5559,12 +5527,12 @@ fn language_settings_data() -> Vec { SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - &language.edit_predictions_disabled_in + language.edit_predictions_disabled_in.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.edit_predictions_disabled_in + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.edit_predictions_disabled_in = value; }) }, } @@ -5579,11 +5547,13 @@ fn language_settings_data() -> Vec { description: "Whether to show tabs and spaces in the editor", field: Box::new(SettingField { pick: |settings_content| { - language_settings_field(settings_content, |language| &language.show_whitespaces) + language_settings_field(settings_content, |language| { + language.show_whitespaces.as_ref() + }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.show_whitespaces + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.show_whitespaces = value; }) }, }), @@ -5597,16 +5567,12 @@ fn language_settings_data() -> Vec { SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(whitespace_map) = &language.whitespace_map { - &whitespace_map.space - } else { - &None - } + language.whitespace_map.as_ref()?.space.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.whitespace_map.get_or_insert_default().space + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.whitespace_map.get_or_insert_default().space = value; }) }, } @@ -5622,16 +5588,12 @@ fn language_settings_data() -> Vec { SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(whitespace_map) = &language.whitespace_map { - &whitespace_map.tab - } else { - &None - } + language.whitespace_map.as_ref()?.tab.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.whitespace_map.get_or_insert_default().tab + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.whitespace_map.get_or_insert_default().tab = value; }) }, } @@ -5647,12 +5609,12 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - &language.show_completions_on_input + language.show_completions_on_input.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.show_completions_on_input + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.show_completions_on_input = value; }) }, }), @@ -5665,12 +5627,12 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - &language.show_completion_documentation + language.show_completion_documentation.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.show_completion_documentation + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.show_completion_documentation = value; }) }, }), @@ -5683,16 +5645,12 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(completions) = &language.completions { - &completions.words - } else { - &None - } + language.completions.as_ref()?.words.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.completions.get_or_insert_default().words + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.completions.get_or_insert_default().words = value; }) }, }), @@ -5705,19 +5663,15 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(completions) = &language.completions { - &completions.words_min_length - } else { - &None - } + language.completions.as_ref()?.words_min_length.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language .completions .get_or_insert_default() - .words_min_length + .words_min_length = value; }) }, }), @@ -5731,16 +5685,12 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(inlay_hints) = &language.inlay_hints { - &inlay_hints.enabled - } else { - &None - } + language.inlay_hints.as_ref()?.enabled.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.inlay_hints.get_or_insert_default().enabled + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.inlay_hints.get_or_insert_default().enabled = value; }) }, }), @@ -5753,19 +5703,15 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(inlay_hints) = &language.inlay_hints { - &inlay_hints.show_value_hints - } else { - &None - } + language.inlay_hints.as_ref()?.show_value_hints.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language .inlay_hints .get_or_insert_default() - .show_value_hints + .show_value_hints = value; }) }, }), @@ -5778,16 +5724,12 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(inlay_hints) = &language.inlay_hints { - &inlay_hints.show_type_hints - } else { - &None - } + language.inlay_hints.as_ref()?.show_type_hints.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.inlay_hints.get_or_insert_default().show_type_hints + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.inlay_hints.get_or_insert_default().show_type_hints = value; }) }, }), @@ -5800,19 +5742,15 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(inlay_hints) = &language.inlay_hints { - &inlay_hints.show_parameter_hints - } else { - &None - } + language.inlay_hints.as_ref()?.show_parameter_hints.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language .inlay_hints .get_or_insert_default() - .show_parameter_hints + .show_parameter_hints = value; }) }, }), @@ -5825,19 +5763,15 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(inlay_hints) = &language.inlay_hints { - &inlay_hints.show_other_hints - } else { - &None - } + language.inlay_hints.as_ref()?.show_other_hints.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language .inlay_hints .get_or_insert_default() - .show_other_hints + .show_other_hints = value; }) }, }), @@ -5850,16 +5784,12 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(inlay_hints) = &language.inlay_hints { - &inlay_hints.show_background - } else { - &None - } + language.inlay_hints.as_ref()?.show_background.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.inlay_hints.get_or_insert_default().show_background + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.inlay_hints.get_or_insert_default().show_background = value; }) }, }), @@ -5872,19 +5802,15 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(inlay_hints) = &language.inlay_hints { - &inlay_hints.edit_debounce_ms - } else { - &None - } + language.inlay_hints.as_ref()?.edit_debounce_ms.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language .inlay_hints .get_or_insert_default() - .edit_debounce_ms + .edit_debounce_ms = value; }) }, }), @@ -5897,19 +5823,15 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(inlay_hints) = &language.inlay_hints { - &inlay_hints.scroll_debounce_ms - } else { - &None - } + language.inlay_hints.as_ref()?.scroll_debounce_ms.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language .inlay_hints .get_or_insert_default() - .scroll_debounce_ms + .scroll_debounce_ms = value; }) }, }), @@ -5923,19 +5845,19 @@ fn language_settings_data() -> Vec { SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(inlay_hints) = &language.inlay_hints { - &inlay_hints.toggle_on_modifiers_press - } else { - &None - } + language + .inlay_hints + .as_ref()? + .toggle_on_modifiers_press + .as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language .inlay_hints .get_or_insert_default() - .toggle_on_modifiers_press + .toggle_on_modifiers_press = value; }) }, } @@ -5950,8 +5872,10 @@ fn language_settings_data() -> Vec { title: "LSP Document Colors", description: "How to render LSP color previews in the editor", field: Box::new(SettingField { - pick: |settings_content| &settings_content.editor.lsp_document_colors, - pick_mut: |settings_content| &mut settings_content.editor.lsp_document_colors, + pick: |settings_content| settings_content.editor.lsp_document_colors.as_ref(), + write: |settings_content, value| { + settings_content.editor.lsp_document_colors = value; + }, }), metadata: None, files: USER, @@ -5965,16 +5889,13 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(tasks) = &language.tasks { - &tasks.enabled - } else { - &None - } + language.tasks.as_ref()?.enabled.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.tasks.get_or_insert_default().enabled + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.tasks.get_or_insert_default().enabled = value; + }) }, }), @@ -5988,16 +5909,13 @@ fn language_settings_data() -> Vec { SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(tasks) = &language.tasks { - &tasks.variables - } else { - &None - } + language.tasks.as_ref()?.variables.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.tasks.get_or_insert_default().variables + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.tasks.get_or_insert_default().variables = value; + }) }, } @@ -6012,16 +5930,13 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(tasks) = &language.tasks { - &tasks.prefer_lsp - } else { - &None - } + language.tasks.as_ref()?.prefer_lsp.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.tasks.get_or_insert_default().prefer_lsp + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.tasks.get_or_insert_default().prefer_lsp = value; + }) }, }), @@ -6035,11 +5950,12 @@ fn language_settings_data() -> Vec { field: Box::new( SettingField { pick: |settings_content| { - language_settings_field(settings_content, |language| &language.debuggers) + language_settings_field(settings_content, |language| language.debuggers.as_ref()) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.debuggers + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.debuggers = value; + }) }, } @@ -6052,8 +5968,8 @@ fn language_settings_data() -> Vec { title: "Middle Click Paste", description: "Enable middle-click paste on Linux", field: Box::new(SettingField { - pick: |settings_content| &settings_content.editor.middle_click_paste, - pick_mut: |settings_content| &mut settings_content.editor.middle_click_paste, + pick: |settings_content| settings_content.editor.middle_click_paste.as_ref(), + write: |settings_content, value| {settings_content.editor.middle_click_paste = value;}, }), metadata: None, files: USER, @@ -6064,12 +5980,13 @@ fn language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - &language.extend_comment_on_newline + language.extend_comment_on_newline.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.extend_comment_on_newline + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.extend_comment_on_newline = value; + }) }, }), @@ -6085,14 +6002,11 @@ fn language_settings_data() -> Vec { description: "The unit for image file sizes", field: Box::new(SettingField { pick: |settings_content| { - if let Some(image_viewer) = settings_content.image_viewer.as_ref() { - &image_viewer.unit - } else { - &None - } + settings_content.image_viewer.as_ref().and_then(|image_viewer| image_viewer.unit.as_ref()) }, - pick_mut: |settings_content| { - &mut settings_content.image_viewer.get_or_insert_default().unit + write: |settings_content, value| { + settings_content.image_viewer.get_or_insert_default().unit = value; + }, }), metadata: None, @@ -6103,14 +6017,11 @@ fn language_settings_data() -> Vec { description: "Whether to automatically replace emoji shortcodes with emoji characters", field: Box::new(SettingField { pick: |settings_content| { - if let Some(message_editor) = settings_content.message_editor.as_ref() { - &message_editor.auto_replace_emoji_shortcode - } else { - &None - } + settings_content.message_editor.as_ref().and_then(|message_editor| message_editor.auto_replace_emoji_shortcode.as_ref()) }, - pick_mut: |settings_content| { - &mut settings_content.message_editor.get_or_insert_default().auto_replace_emoji_shortcode + write: |settings_content, value| { + settings_content.message_editor.get_or_insert_default().auto_replace_emoji_shortcode = value; + }, }), metadata: None, @@ -6121,10 +6032,11 @@ fn language_settings_data() -> Vec { description: "Relative size of the drop target in the editor that will open dropped file as a split pane", field: Box::new(SettingField { pick: |settings_content| { - &settings_content.workspace.drop_target_size + settings_content.workspace.drop_target_size.as_ref() }, - pick_mut: |settings_content| { - &mut settings_content.workspace.drop_target_size + write: |settings_content, value| { + settings_content.workspace.drop_target_size = value; + }, }), metadata: None, @@ -6146,12 +6058,12 @@ fn non_editor_language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - &language.enable_language_server + language.enable_language_server.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.enable_language_server + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.enable_language_server = value; }) }, }), @@ -6165,12 +6077,12 @@ fn non_editor_language_settings_data() -> Vec { SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - &language.language_servers + language.language_servers.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.language_servers + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.language_servers = value; }) }, } @@ -6184,11 +6096,13 @@ fn non_editor_language_settings_data() -> Vec { description: "Whether to perform linked edits of associated ranges, if the LS supports it. For example, when editing opening tag, the contents of the closing tag will be edited as well", field: Box::new(SettingField { pick: |settings_content| { - language_settings_field(settings_content, |language| &language.linked_edits) + language_settings_field(settings_content, |language| { + language.linked_edits.as_ref() + }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.linked_edits + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.linked_edits = value; }) }, }), @@ -6199,8 +6113,10 @@ fn non_editor_language_settings_data() -> Vec { title: "Go To Definition Fallback", description: "Whether to follow-up empty go to definition responses from the language server", field: Box::new(SettingField { - pick: |settings_content| &settings_content.editor.go_to_definition_fallback, - pick_mut: |settings_content| &mut settings_content.editor.go_to_definition_fallback, + pick: |settings_content| settings_content.editor.go_to_definition_fallback.as_ref(), + write: |settings_content, value| { + settings_content.editor.go_to_definition_fallback = value; + }, }), metadata: None, files: USER, @@ -6212,16 +6128,12 @@ fn non_editor_language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(completions) = &language.completions { - &completions.lsp - } else { - &None - } + language.completions.as_ref()?.lsp.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.completions.get_or_insert_default().lsp + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.completions.get_or_insert_default().lsp = value; }) }, }), @@ -6234,19 +6146,15 @@ fn non_editor_language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(completions) = &language.completions { - &completions.lsp_fetch_timeout_ms - } else { - &None - } + language.completions.as_ref()?.lsp_fetch_timeout_ms.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language .completions .get_or_insert_default() - .lsp_fetch_timeout_ms + .lsp_fetch_timeout_ms = value; }) }, }), @@ -6259,16 +6167,12 @@ fn non_editor_language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(completions) = &language.completions { - &completions.lsp_insert_mode - } else { - &None - } + language.completions.as_ref()?.lsp_insert_mode.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.completions.get_or_insert_default().lsp_insert_mode + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.completions.get_or_insert_default().lsp_insert_mode = value; }) }, }), @@ -6282,11 +6186,13 @@ fn non_editor_language_settings_data() -> Vec { field: Box::new( SettingField { pick: |settings_content| { - language_settings_field(settings_content, |language| &language.debuggers) + language_settings_field(settings_content, |language| { + language.debuggers.as_ref() + }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.debuggers + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.debuggers = value; }) }, } @@ -6302,16 +6208,12 @@ fn non_editor_language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(prettier) = &language.prettier { - &prettier.allowed - } else { - &None - } + language.prettier.as_ref()?.allowed.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.prettier.get_or_insert_default().allowed + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.prettier.get_or_insert_default().allowed = value; }) }, }), @@ -6324,16 +6226,12 @@ fn non_editor_language_settings_data() -> Vec { field: Box::new(SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(prettier) = &language.prettier { - &prettier.parser - } else { - &None - } + language.prettier.as_ref()?.parser.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.prettier.get_or_insert_default().parser + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.prettier.get_or_insert_default().parser = value; }) }, }), @@ -6347,16 +6245,12 @@ fn non_editor_language_settings_data() -> Vec { SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(prettier) = &language.prettier { - &prettier.plugins - } else { - &None - } + language.prettier.as_ref()?.plugins.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.prettier.get_or_insert_default().plugins + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.prettier.get_or_insert_default().plugins = value; }) }, } @@ -6372,16 +6266,12 @@ fn non_editor_language_settings_data() -> Vec { SettingField { pick: |settings_content| { language_settings_field(settings_content, |language| { - if let Some(prettier) = &language.prettier { - &prettier.options - } else { - &None - } + language.prettier.as_ref()?.options.as_ref() }) }, - pick_mut: |settings_content| { - language_settings_field_mut(settings_content, |language| { - &mut language.prettier.get_or_insert_default().options + write: |settings_content, value| { + language_settings_field_mut(settings_content, value, |language, value| { + language.prettier.get_or_insert_default().options = value; }) }, } @@ -6392,3 +6282,14 @@ fn non_editor_language_settings_data() -> Vec { }), ] } + +fn show_scrollbar_or_editor( + settings_content: &SettingsContent, + show: fn(&SettingsContent) -> Option<&settings::ShowScrollbar>, +) -> Option<&settings::ShowScrollbar> { + show(settings_content).or(settings_content + .editor + .scrollbar + .as_ref() + .and_then(|scrollbar| scrollbar.show.as_ref())) +} diff --git a/crates/settings_ui/src/settings_ui.rs b/crates/settings_ui/src/settings_ui.rs index 7c79a3719f829ccda6c162b1fd13024a4b0e69b2..592e71bbf12f7a64dbb14dd6aa3d152b890b0121 100644 --- a/crates/settings_ui/src/settings_ui.rs +++ b/crates/settings_ui/src/settings_ui.rs @@ -6,10 +6,10 @@ use editor::{Editor, EditorEvent}; use feature_flags::FeatureFlag; use fuzzy::StringMatchCandidate; use gpui::{ - Action, App, Div, Entity, FocusHandle, Focusable, FontWeight, Global, ListState, - ReadGlobal as _, ScrollHandle, Stateful, Subscription, Task, TitlebarOptions, - UniformListScrollHandle, Window, WindowBounds, WindowHandle, WindowOptions, actions, div, list, - point, prelude::*, px, size, uniform_list, + Action, App, Div, Entity, FocusHandle, Focusable, Global, ListState, ReadGlobal as _, + ScrollHandle, Stateful, Subscription, Task, TitlebarOptions, UniformListScrollHandle, Window, + WindowBounds, WindowHandle, WindowOptions, actions, div, list, point, prelude::*, px, size, + uniform_list, }; use heck::ToTitleCase as _; use project::WorktreeId; @@ -84,8 +84,8 @@ actions!( struct FocusFile(pub u32); struct SettingField { - pick: fn(&SettingsContent) -> &Option, - pick_mut: fn(&mut SettingsContent) -> &mut Option, + pick: fn(&SettingsContent) -> Option<&T>, + write: fn(&mut SettingsContent, Option), } impl Clone for SettingField { @@ -98,7 +98,7 @@ impl Clone for SettingField { impl Copy for SettingField {} /// Helper for unimplemented settings, used in combination with `SettingField::unimplemented` -/// to keep the setting around in the UI with valid pick and pick_mut implementations, but don't actually try to render it. +/// to keep the setting around in the UI with valid pick and write implementations, but don't actually try to render it. /// TODO(settings_ui): In non-dev builds (`#[cfg(not(debug_assertions))]`) make this render as edit-in-json #[derive(Clone, Copy)] struct UnimplementedSettingField; @@ -114,8 +114,8 @@ impl SettingField { #[allow(unused)] fn unimplemented(self) -> SettingField { SettingField { - pick: |_| &Some(UnimplementedSettingField), - pick_mut: |_| unreachable!(), + pick: |_| Some(&UnimplementedSettingField), + write: |_, _| unreachable!(), } } } @@ -163,12 +163,15 @@ impl AnySettingField for SettingFi if file_set_in == &settings::SettingsFile::Default { return None; } + if file_set_in != ¤t_file.to_settings() { + return None; + } let this = *self; let store = SettingsStore::global(cx); let default_value = (this.pick)(store.raw_default_settings()); let is_default = store .get_content_for_file(file_set_in.clone()) - .map_or(&None, this.pick) + .map_or(None, this.pick) == default_value; if is_default { return None; @@ -183,12 +186,12 @@ impl AnySettingField for SettingFi .0 != settings::SettingsFile::Default; let value_to_set = if is_set_somewhere_other_than_default { - default_value.clone() + default_value.cloned() } else { None }; update_settings_file(current_file.clone(), cx, move |settings, _| { - *(this.pick_mut)(settings) = value_to_set; + (this.write)(settings, value_to_set); }) // todo(settings_ui): Don't log err .log_err(); @@ -374,12 +377,6 @@ fn init_renderers(cx: &mut App) { .add_basic_renderer::(render_dropdown) .add_basic_renderer::(render_dropdown) .add_basic_renderer::(render_font_picker) - // todo(settings_ui): This needs custom ui - // .add_renderer::(|settings_field, file, _, window, cx| { - // // todo(settings_ui): Do we want to expose the custom variant of buffer line height? - // // right now there's a manual impl of strum::VariantArray - // render_dropdown(*settings_field, file, window, cx) - // }) .add_basic_renderer::(render_dropdown) .add_basic_renderer::(render_dropdown) .add_basic_renderer::(render_dropdown) @@ -420,7 +417,7 @@ fn init_renderers(cx: &mut App) { .add_basic_renderer::>(render_number_field) .add_basic_renderer::(render_number_field) .add_basic_renderer::(render_number_field) - .add_basic_renderer::(render_number_field) + .add_basic_renderer::(render_number_field) .add_basic_renderer::(render_number_field) .add_basic_renderer::(render_dropdown) .add_basic_renderer::(render_dropdown) @@ -430,17 +427,18 @@ fn init_renderers(cx: &mut App) { .add_basic_renderer::(render_dropdown) .add_basic_renderer::(render_dropdown) .add_basic_renderer::(render_dropdown) + .add_basic_renderer::(render_dropdown) .add_basic_renderer::(render_dropdown) .add_basic_renderer::(render_dropdown) .add_basic_renderer::(render_dropdown) .add_basic_renderer::(render_dropdown) .add_basic_renderer::(render_dropdown) .add_basic_renderer::(render_dropdown) - // please semicolon stay on next line - ; - // .add_renderer::(|settings_field, file, _, window, cx| { - // render_dropdown(*settings_field, file, window, cx) - // }); + .add_basic_renderer::(render_dropdown) + .add_basic_renderer::(render_dropdown) + .add_basic_renderer::(render_theme_picker) + // please semicolon stay on next line + ; } pub fn open_settings_editor( @@ -500,7 +498,7 @@ pub fn open_settings_editor( /// If this is empty the selected page is rendered, /// otherwise the last sub page gets rendered. /// -/// Global so that `pick` and `pick_mut` callbacks can access it +/// Global so that `pick` and `write` callbacks can access it /// and use it to dynamically render sub pages (e.g. for language settings) static SUB_PAGE_STACK: LazyLock>> = LazyLock::new(|| RwLock::new(Vec::new())); @@ -584,6 +582,7 @@ enum SettingsPageItem { SectionHeader(&'static str), SettingItem(SettingItem), SubPageLink(SubPageLink), + DynamicItem(DynamicItem), } impl std::fmt::Debug for SettingsPageItem { @@ -596,6 +595,9 @@ impl std::fmt::Debug for SettingsPageItem { SettingsPageItem::SubPageLink(sub_page_link) => { write!(f, "SubPageLink({})", sub_page_link.title) } + SettingsPageItem::DynamicItem(dynamic_item) => { + write!(f, "DynamicItem({})", dynamic_item.discriminant.title) + } } } } @@ -610,19 +612,17 @@ impl SettingsPageItem { cx: &mut Context, ) -> AnyElement { let file = settings_window.current_file.clone(); - match self { - SettingsPageItem::SectionHeader(header) => v_flex() - .w_full() - .gap_1p5() - .child( - Label::new(SharedString::new_static(header)) - .size(LabelSize::Small) - .color(Color::Muted) - .buffer_font(cx), - ) - .child(Divider::horizontal().color(DividerColor::BorderFaded)) - .into_any_element(), - SettingsPageItem::SettingItem(setting_item) => { + let border_variant = cx.theme().colors().border_variant; + let apply_padding = |element: Stateful
| -> Stateful
{ + let element = element.pt_4(); + if is_last { + element.pb_10() + } else { + element.pb_4().border_b_1().border_color(border_variant) + } + }; + let mut render_setting_item_inner = + |setting_item: &SettingItem, cx: &mut Context| { let renderer = cx.default_global::().clone(); let (_, found) = setting_item.field.file_set_in(file.clone(), cx); @@ -642,7 +642,7 @@ impl SettingsPageItem { Ok(field_renderer) => field_renderer( settings_window, setting_item, - file, + file.clone(), setting_item.metadata.as_deref(), window, cx, @@ -650,7 +650,7 @@ impl SettingsPageItem { Err(warning) => render_settings_item( settings_window, setting_item, - file, + file.clone(), Button::new("error-warning", warning) .style(ButtonStyle::Outlined) .size(ButtonSize::Medium) @@ -665,17 +665,23 @@ impl SettingsPageItem { ), }; - field - .pt_4() - .map(|this| { - if is_last { - this.pb_10() - } else { - this.pb_4() - .border_b_1() - .border_color(cx.theme().colors().border_variant) - } - }) + (field.map(apply_padding), field_renderer_or_warning.is_ok()) + }; + match self { + SettingsPageItem::SectionHeader(header) => v_flex() + .w_full() + .gap_1p5() + .child( + Label::new(SharedString::new_static(header)) + .size(LabelSize::Small) + .color(Color::Muted) + .buffer_font(cx), + ) + .child(Divider::horizontal().color(DividerColor::BorderFaded)) + .into_any_element(), + SettingsPageItem::SettingItem(setting_item) => { + render_setting_item_inner(setting_item, cx) + .0 .into_any_element() } SettingsPageItem::SubPageLink(sub_page_link) => h_flex() @@ -684,16 +690,7 @@ impl SettingsPageItem { .min_w_0() .gap_2() .justify_between() - .pt_4() - .map(|this| { - if is_last { - this.pb_10() - } else { - this.pb_4() - .border_b_1() - .border_color(cx.theme().colors().border_variant) - } - }) + .map(apply_padding) .child( v_flex() .w_full() @@ -736,6 +733,32 @@ impl SettingsPageItem { }), ) .into_any_element(), + SettingsPageItem::DynamicItem(DynamicItem { + discriminant: discriminant_setting_item, + pick_discriminant, + fields, + }) => { + let file = file.to_settings(); + let discriminant = SettingsStore::global(cx) + .get_value_from_file(file, *pick_discriminant) + .1; + let (discriminant_element, rendered_ok) = + render_setting_item_inner(discriminant_setting_item, cx); + let mut content = v_flex() + .gap_2() + .id("dynamic-item") + .child(discriminant_element); + if rendered_ok { + let discriminant = + discriminant.expect("This should be Some if rendered_ok is true"); + let sub_fields = &fields[discriminant]; + for field in sub_fields { + content = content.child(render_setting_item_inner(field, cx).0.pl_6()); + } + } + + return content.into_any_element(); + } } } } @@ -767,8 +790,7 @@ fn render_settings_item( .when_some( setting_item .field - .reset_to_default_fn(&file, &found_in_file, cx) - .filter(|_| file_set_in.as_ref() == Some(&file)), + .reset_to_default_fn(&file, &found_in_file, cx), |this, reset_to_default| { this.child( IconButton::new("reset-to-default-btn", IconName::Undo) @@ -816,6 +838,18 @@ struct SettingItem { files: FileMask, } +struct DynamicItem { + discriminant: SettingItem, + pick_discriminant: fn(&SettingsContent) -> Option, + fields: Vec>, +} + +impl PartialEq for DynamicItem { + fn eq(&self, other: &Self) -> bool { + self.discriminant == other.discriminant && self.fields == other.fields + } +} + #[derive(PartialEq, Eq, Clone, Copy)] struct FileMask(u8); @@ -1204,7 +1238,11 @@ impl SettingsWindow { any_found_since_last_header = false; } SettingsPageItem::SettingItem(SettingItem { files, .. }) - | SettingsPageItem::SubPageLink(SubPageLink { files, .. }) => { + | SettingsPageItem::SubPageLink(SubPageLink { files, .. }) + | SettingsPageItem::DynamicItem(DynamicItem { + discriminant: SettingItem { files, .. }, + .. + }) => { if !files.contains(current_file) { page_filter[index] = false; } else { @@ -1375,7 +1413,10 @@ impl SettingsWindow { for (item_index, item) in page.items.iter().enumerate() { let key_index = key_lut.len(); match item { - SettingsPageItem::SettingItem(item) => { + SettingsPageItem::DynamicItem(DynamicItem { + discriminant: item, .. + }) + | SettingsPageItem::SettingItem(item) => { documents.push(bm25::Document { id: key_index, contents: [page.title, header_str, item.title, item.description] @@ -2687,7 +2728,7 @@ fn render_text_field + Into + AsRef + Clone>( .on_confirm({ move |new_text, cx| { update_settings_file(file.clone(), cx, move |settings, _cx| { - *(field.pick_mut)(settings) = new_text.map(Into::into); + (field.write)(settings, new_text.map(Into::into)); }) .log_err(); // todo(settings_ui) don't log err } @@ -2716,7 +2757,7 @@ fn render_toggle_button + From + Copy>( move |state, _window, cx| { let state = *state == ui::ToggleState::Selected; update_settings_file(file.clone(), cx, move |settings, _cx| { - *(field.pick_mut)(settings) = Some(state.into()); + (field.write)(settings, Some(state.into())); }) .log_err(); // todo(settings_ui) don't log err } @@ -2744,7 +2785,7 @@ fn render_font_picker( current_value.clone().into(), move |font_name, cx| { update_settings_file(file.clone(), cx, move |settings, _cx| { - *(field.pick_mut)(settings) = Some(font_name.into()); + (field.write)(settings, Some(font_name.into())); }) .log_err(); // todo(settings_ui) don't log err }, @@ -2788,7 +2829,7 @@ fn render_number_field( move |value, _window, cx| { let value = *value; update_settings_file(file.clone(), cx, move |settings, _cx| { - *(field.pick_mut)(settings) = Some(value); + (field.write)(settings, Some(value)); }) .log_err(); // todo(settings_ui) don't log err } @@ -2843,7 +2884,58 @@ where return; } update_settings_file(file.clone(), cx, move |settings, _cx| { - *(field.pick_mut)(settings) = Some(value); + (field.write)(settings, Some(value)); + }) + .log_err(); // todo(settings_ui) don't log err + }, + ); + } + menu + }), + ) + .trigger_size(ButtonSize::Medium) + .style(DropdownStyle::Outlined) + .offset(gpui::Point { + x: px(0.0), + y: px(2.0), + }) + .tab_index(0) + .into_any_element() +} + +fn render_theme_picker( + field: SettingField, + file: SettingsUiFile, + _metadata: Option<&SettingsFieldMetadata>, + window: &mut Window, + cx: &mut App, +) -> AnyElement { + let (_, value) = SettingsStore::global(cx).get_value_from_file(file.to_settings(), field.pick); + let current_value = value + .cloned() + .map(|theme_name| theme_name.0.into()) + .unwrap_or_else(|| cx.theme().name.clone()); + + DropdownMenu::new( + "font-picker", + current_value.clone(), + ContextMenu::build(window, cx, move |mut menu, _, cx| { + let all_theme_names = theme::ThemeRegistry::global(cx).list_names(); + for theme_name in all_theme_names { + let file = file.clone(); + let selected = theme_name.as_ref() == current_value.as_ref(); + menu = menu.toggleable_entry( + theme_name.clone(), + selected, + IconPosition::End, + None, + move |_, cx| { + if selected { + return; + } + let theme_name = theme_name.clone(); + update_settings_file(file.clone(), cx, move |settings, _cx| { + (field.write)(settings, Some(settings::ThemeName(theme_name.into()))); }) .log_err(); // todo(settings_ui) don't log err },