@@ -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",
@@ -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<SettingsPage> {
@@ -18,8 +19,10 @@ pub(crate) fn settings_data(cx: &App) -> Vec<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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(&<<settings::ThemeSelection as strum::IntoDiscriminant>::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: <<settings::ThemeSelection as strum::IntoDiscriminant>::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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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<SettingsPage> {
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,
@@ -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<T: 'static> {
- pick: fn(&SettingsContent) -> &Option<T>,
- pick_mut: fn(&mut SettingsContent) -> &mut Option<T>,
+ pick: fn(&SettingsContent) -> Option<&T>,
+ write: fn(&mut SettingsContent, Option<T>),
}
impl<T: 'static> Clone for SettingField<T> {
@@ -98,7 +98,7 @@ impl<T: 'static> Clone for SettingField<T> {
impl<T: 'static> Copy for SettingField<T> {}
/// 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<T: 'static> SettingField<T> {
#[allow(unused)]
fn unimplemented(self) -> SettingField<UnimplementedSettingField> {
SettingField {
- pick: |_| &Some(UnimplementedSettingField),
- pick_mut: |_| unreachable!(),
+ pick: |_| Some(&UnimplementedSettingField),
+ write: |_, _| unreachable!(),
}
}
}
@@ -163,12 +163,15 @@ impl<T: PartialEq + Clone + Send + Sync + 'static> 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<T: PartialEq + Clone + Send + Sync + 'static> 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::<settings::OnLastWindowClosed>(render_dropdown)
.add_basic_renderer::<settings::CloseWindowWhenNoItems>(render_dropdown)
.add_basic_renderer::<settings::FontFamilyName>(render_font_picker)
- // todo(settings_ui): This needs custom ui
- // .add_renderer::<settings::BufferLineHeight>(|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::<settings::BaseKeymapContent>(render_dropdown)
.add_basic_renderer::<settings::MultiCursorModifier>(render_dropdown)
.add_basic_renderer::<settings::HideMouseMode>(render_dropdown)
@@ -420,7 +417,7 @@ fn init_renderers(cx: &mut App) {
.add_basic_renderer::<NonZero<usize>>(render_number_field)
.add_basic_renderer::<NonZeroU32>(render_number_field)
.add_basic_renderer::<settings::CodeFade>(render_number_field)
- .add_basic_renderer::<FontWeight>(render_number_field)
+ .add_basic_renderer::<gpui::FontWeight>(render_number_field)
.add_basic_renderer::<settings::MinimumContrast>(render_number_field)
.add_basic_renderer::<settings::ShowScrollbar>(render_dropdown)
.add_basic_renderer::<settings::ScrollbarDiagnostics>(render_dropdown)
@@ -430,17 +427,18 @@ fn init_renderers(cx: &mut App) {
.add_basic_renderer::<settings::MinimapThumbBorder>(render_dropdown)
.add_basic_renderer::<settings::SteppingGranularity>(render_dropdown)
.add_basic_renderer::<settings::NotifyWhenAgentWaiting>(render_dropdown)
+ .add_basic_renderer::<settings::NotifyWhenAgentWaiting>(render_dropdown)
.add_basic_renderer::<settings::ImageFileSizeUnit>(render_dropdown)
.add_basic_renderer::<settings::StatusStyle>(render_dropdown)
.add_basic_renderer::<settings::PaneSplitDirectionHorizontal>(render_dropdown)
.add_basic_renderer::<settings::PaneSplitDirectionVertical>(render_dropdown)
.add_basic_renderer::<settings::PaneSplitDirectionVertical>(render_dropdown)
.add_basic_renderer::<settings::DocumentColorsRenderMode>(render_dropdown)
- // please semicolon stay on next line
- ;
- // .add_renderer::<ThemeSelection>(|settings_field, file, _, window, cx| {
- // render_dropdown(*settings_field, file, window, cx)
- // });
+ .add_basic_renderer::<settings::ThemeSelectionDiscriminants>(render_dropdown)
+ .add_basic_renderer::<settings::ThemeMode>(render_dropdown)
+ .add_basic_renderer::<settings::ThemeName>(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<RwLock<Vec<SubPage>>> = 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<SettingsWindow>,
) -> 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<Div>| -> Stateful<Div> {
+ 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<SettingsWindow>| {
let renderer = cx.default_global::<SettingFieldRenderer>().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<usize>,
+ fields: Vec<Vec<SettingItem>>,
+}
+
+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<T: From<String> + Into<String> + AsRef<str> + 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<B: Into<bool> + From<bool> + 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<T: NumberFieldType + Send + Sync>(
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<settings::ThemeName>,
+ 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
},