settings_ui: Add Basic Implementation of Language Settings (#37803)

Closes #ISSUE

Release Notes:

- N/A *or* Added/Fixed/Improved ...

---------

Co-authored-by: Anthony <anthony@zed.dev>
This commit is contained in:
Ben Kunkle
2025-09-08 20:14:36 -04:00
committed by GitHub
co-authored by Anthony
parent 1feffad5e8
commit 8c93112869
5 changed files with 278 additions and 94 deletions
+2 -2
View File
@@ -601,12 +601,12 @@ impl SettingsStore {
pub fn update_settings_file_at_path(
&self,
fs: Arc<dyn Fs>,
path: &[&str],
path: &[impl AsRef<str>],
new_value: serde_json::Value,
) -> oneshot::Receiver<Result<()>> {
let key_path = path
.into_iter()
.cloned()
.map(AsRef::as_ref)
.map(SharedString::new)
.collect::<Vec<_>>();
let update = move |mut old_text: String, cx: AsyncApp| {
+37 -10
View File
@@ -1,8 +1,12 @@
use std::any::TypeId;
use std::{
any::TypeId,
num::{NonZeroU32, NonZeroUsize},
rc::Rc,
};
use anyhow::Context as _;
use fs::Fs;
use gpui::{AnyElement, App, AppContext as _, ReadGlobal as _, Window};
use gpui::{AnyElement, App, AppContext as _, ReadGlobal as _, SharedString, Window};
use smallvec::SmallVec;
use crate::SettingsStore;
@@ -24,6 +28,7 @@ pub trait SettingsUi {
}
}
#[derive(Clone)]
pub struct SettingsUiEntry {
/// The path in the settings JSON file for this setting. Relative to parent
/// None implies `#[serde(flatten)]` or `Settings::KEY.is_none()` for top level settings
@@ -35,6 +40,7 @@ pub struct SettingsUiEntry {
pub item: SettingsUiItem,
}
#[derive(Clone)]
pub enum SettingsUiItemSingle {
SwitchField,
/// A numeric stepper for a specific type of number
@@ -52,13 +58,13 @@ pub enum SettingsUiItemSingle {
/// Must be the same length as `variants`
labels: &'static [&'static str],
},
Custom(Box<dyn Fn(SettingsValue<serde_json::Value>, &mut Window, &mut App) -> AnyElement>),
Custom(Rc<dyn Fn(SettingsValue<serde_json::Value>, &mut Window, &mut App) -> AnyElement>),
}
pub struct SettingsValue<T> {
pub title: &'static str,
pub documentation: Option<&'static str>,
pub path: SmallVec<[&'static str; 1]>,
pub title: SharedString,
pub documentation: Option<SharedString>,
pub path: SmallVec<[SharedString; 1]>,
pub value: Option<T>,
pub default_value: T,
}
@@ -73,7 +79,7 @@ impl<T> SettingsValue<T> {
}
impl SettingsValue<serde_json::Value> {
pub fn write_value(path: &SmallVec<[&'static str; 1]>, value: serde_json::Value, cx: &mut App) {
pub fn write_value(path: &SmallVec<[SharedString; 1]>, value: serde_json::Value, cx: &mut App) {
let settings_store = SettingsStore::global(cx);
let fs = <dyn Fs>::global(cx);
@@ -90,7 +96,7 @@ impl SettingsValue<serde_json::Value> {
impl<T: serde::Serialize> SettingsValue<T> {
pub fn write(
path: &SmallVec<[&'static str; 1]>,
path: &SmallVec<[SharedString; 1]>,
value: T,
cx: &mut App,
) -> Result<(), serde_json::Error> {
@@ -99,19 +105,36 @@ impl<T: serde::Serialize> SettingsValue<T> {
}
}
pub struct SettingsUiItemDynamic {
#[derive(Clone)]
pub struct SettingsUiItemUnion {
pub options: Vec<SettingsUiEntry>,
pub determine_option: fn(&serde_json::Value, &App) -> usize,
}
pub struct SettingsUiEntryMetaData {
pub title: SharedString,
pub path: SharedString,
pub documentation: Option<SharedString>,
}
#[derive(Clone)]
pub struct SettingsUiItemDynamicMap {
pub item: fn() -> SettingsUiItem,
pub determine_items: fn(&serde_json::Value, &App) -> Vec<SettingsUiEntryMetaData>,
pub defaults_path: &'static [&'static str],
}
#[derive(Clone)]
pub struct SettingsUiItemGroup {
pub items: Vec<SettingsUiEntry>,
}
#[derive(Clone)]
pub enum SettingsUiItem {
Group(SettingsUiItemGroup),
Single(SettingsUiItemSingle),
Dynamic(SettingsUiItemDynamic),
Union(SettingsUiItemUnion),
DynamicMap(SettingsUiItemDynamicMap),
None,
}
@@ -134,6 +157,7 @@ pub enum NumType {
U32 = 1,
F32 = 2,
USIZE = 3,
U32NONZERO = 4,
}
pub static NUM_TYPE_NAMES: std::sync::LazyLock<[&'static str; NumType::COUNT]> =
@@ -151,6 +175,7 @@ impl NumType {
NumType::U32 => TypeId::of::<u32>(),
NumType::F32 => TypeId::of::<f32>(),
NumType::USIZE => TypeId::of::<usize>(),
NumType::U32NONZERO => TypeId::of::<NonZeroU32>(),
}
}
@@ -160,6 +185,7 @@ impl NumType {
NumType::U32 => std::any::type_name::<u32>(),
NumType::F32 => std::any::type_name::<f32>(),
NumType::USIZE => std::any::type_name::<usize>(),
NumType::U32NONZERO => std::any::type_name::<NonZeroU32>(),
}
}
}
@@ -185,3 +211,4 @@ numeric_stepper_for_num_type!(u32, U32);
// todo(settings_ui) is there a better ui for f32?
numeric_stepper_for_num_type!(f32, F32);
numeric_stepper_for_num_type!(usize, USIZE);
numeric_stepper_for_num_type!(NonZeroUsize, U32NONZERO);