Compare commits

...
Sign in to create a new pull request.

7 commits

Author SHA1 Message Date
Anthony
e42d5a8264 Add more notes
Co-authored-by: Ben Kunkle <ben@zed.dev>
2025-08-26 15:53:46 -04:00
Anthony
8ff656c999 Update boolean in settings ui to show up as switch fields
Co-authored-by: Ben Kunkle <ben@zed.dev>
2025-08-26 15:43:20 -04:00
Anthony
1fd0f7a46b Improve macro to show items
Co-authored-by: Ben Kunkle <ben@zed.dev>
2025-08-26 15:36:53 -04:00
Anthony
c1631b6e8c Add group setting titles
Co-authored-by: Ben Kunkle <ben@zed.dev>
2025-08-26 13:55:25 -04:00
Anthony
ba9d109289 Add settings_ui(group) attribute to macro
Co-authored-by: Ben Kunkle <ben@zed.dev>
2025-08-26 12:33:38 -04:00
Anthony
15f634f8cc Move keymap editor into it's own crate and create settings ui crate
We also change the structure of the settings ui macro. The trait is
still a requirement on the Settings trait implementation, but it returns
a SettingUIItemVariant now, which the settings ui crate will take
adventage of to generate UI

This allows us to get around circular dependency errors and still get
the type system to ensure all settings fulfill the settings UI crate

Co-authored-by: Ben Kunkle <ben@zed.dev>
2025-08-26 12:00:10 -04:00
Anthony
3c0ec5f612 Start work on creating the inital structure for the settings UI
We created a proc macro that derives the settings ui trait on types and
added that trait as a marker on Settings trait. Then we added the derive
macro on all settings

Co-authored-by: Ben Kunkle <ben@zed.dev>
2025-08-25 15:50:42 -04:00
59 changed files with 610 additions and 156 deletions

76
Cargo.lock generated
View file

@ -8953,6 +8953,46 @@ dependencies = [
"uuid",
]
[[package]]
name = "keymap_editor"
version = "0.1.0"
dependencies = [
"anyhow",
"collections",
"command_palette",
"command_palette_hooks",
"component",
"db",
"editor",
"feature_flags",
"fs",
"fuzzy",
"gpui",
"itertools 0.14.0",
"language",
"log",
"menu",
"notifications",
"paths",
"project",
"search",
"serde",
"serde_json",
"settings",
"telemetry",
"tempfile",
"theme",
"tree-sitter-json",
"tree-sitter-rust",
"ui",
"ui_input",
"util",
"vim",
"workspace",
"workspace-hack",
"zed_actions",
]
[[package]]
name = "khronos-egl"
version = "6.0.0"
@ -14856,6 +14896,7 @@ dependencies = [
"serde_derive",
"serde_json",
"serde_json_lenient",
"settings_ui_macros",
"smallvec",
"tree-sitter",
"tree-sitter-json",
@ -14891,39 +14932,25 @@ name = "settings_ui"
version = "0.1.0"
dependencies = [
"anyhow",
"collections",
"command_palette",
"command_palette_hooks",
"component",
"db",
"editor",
"feature_flags",
"fs",
"fuzzy",
"gpui",
"itertools 0.14.0",
"language",
"log",
"menu",
"notifications",
"paths",
"project",
"search",
"serde",
"serde_json",
"settings",
"telemetry",
"tempfile",
"theme",
"tree-sitter-json",
"tree-sitter-rust",
"ui",
"ui_input",
"util",
"vim",
"workspace",
"workspace-hack",
"zed_actions",
]
[[package]]
name = "settings_ui_macros"
version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
]
[[package]]
@ -16739,6 +16766,7 @@ dependencies = [
"db",
"gpui",
"http_client",
"keymap_editor",
"notifications",
"pretty_assertions",
"project",
@ -16747,7 +16775,6 @@ dependencies = [
"schemars",
"serde",
"settings",
"settings_ui",
"smallvec",
"story",
"telemetry",
@ -20459,6 +20486,7 @@ dependencies = [
"itertools 0.14.0",
"jj_ui",
"journal",
"keymap_editor",
"language",
"language_extension",
"language_model",

View file

@ -54,6 +54,8 @@ members = [
"crates/deepseek",
"crates/diagnostics",
"crates/docs_preprocessor",
"crates/edit_prediction",
"crates/edit_prediction_button",
"crates/editor",
"crates/eval",
"crates/explorer_command_injector",
@ -82,13 +84,12 @@ members = [
"crates/http_client_tls",
"crates/icons",
"crates/image_viewer",
"crates/edit_prediction",
"crates/edit_prediction_button",
"crates/inspector_ui",
"crates/install_cli",
"crates/jj",
"crates/jj_ui",
"crates/journal",
"crates/keymap_editor",
"crates/language",
"crates/language_extension",
"crates/language_model",
@ -146,6 +147,7 @@ members = [
"crates/settings",
"crates/settings_profile_selector",
"crates/settings_ui",
"crates/settings_ui_macros",
"crates/snippet",
"crates/snippet_provider",
"crates/snippets_ui",
@ -156,9 +158,9 @@ members = [
"crates/streaming_diff",
"crates/sum_tree",
"crates/supermaven",
"crates/system_specs",
"crates/supermaven_api",
"crates/svg_preview",
"crates/system_specs",
"crates/tab_switcher",
"crates/task",
"crates/tasks_ui",
@ -314,6 +316,7 @@ install_cli = { path = "crates/install_cli" }
jj = { path = "crates/jj" }
jj_ui = { path = "crates/jj_ui" }
journal = { path = "crates/journal" }
keymap_editor = { path = "crates/keymap_editor" }
language = { path = "crates/language" }
language_extension = { path = "crates/language_extension" }
language_model = { path = "crates/language_model" }
@ -373,6 +376,7 @@ semantic_version = { path = "crates/semantic_version" }
session = { path = "crates/session" }
settings = { path = "crates/settings" }
settings_ui = { path = "crates/settings_ui" }
settings_ui_macros = { path = "crates/settings_ui_macros" }
snippet = { path = "crates/snippet" }
snippet_provider = { path = "crates/snippet_provider" }
snippets_ui = { path = "crates/snippets_ui" }

View file

@ -4,13 +4,13 @@ use collections::HashMap;
use gpui::{App, SharedString};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
use settings::{SettingsUI, Settings, SettingsSources};
pub fn init(cx: &mut App) {
AllAgentServersSettings::register(cx);
}
#[derive(Default, Deserialize, Serialize, Clone, JsonSchema, Debug)]
#[derive(Default, Deserialize, Serialize, Clone, JsonSchema, Debug, SettingsUI)]
pub struct AllAgentServersSettings {
pub gemini: Option<AgentServerSettings>,
pub claude: Option<AgentServerSettings>,

View file

@ -8,7 +8,7 @@ use gpui::{App, Pixels, SharedString};
use language_model::LanguageModel;
use schemars::{JsonSchema, json_schema};
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
use settings::{SettingsUI, Settings, SettingsSources};
use std::borrow::Cow;
pub use crate::agent_profile::*;
@ -48,7 +48,7 @@ pub enum NotifyWhenAgentWaiting {
Never,
}
#[derive(Default, Clone, Debug)]
#[derive(Default, Clone, Debug, SettingsUI)]
pub struct AgentSettings {
pub enabled: bool,
pub button: bool,

View file

@ -2,10 +2,10 @@ use anyhow::Result;
use gpui::App;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
use settings::{SettingsUI, Settings, SettingsSources};
/// Settings for slash commands.
#[derive(Deserialize, Serialize, Debug, Default, Clone, JsonSchema)]
#[derive(Deserialize, Serialize, Debug, Default, Clone, JsonSchema, SettingsUI)]
pub struct SlashCommandSettings {
/// Settings for the `/cargo-workspace` slash command.
#[serde(default)]

View file

@ -2,9 +2,9 @@ use anyhow::Result;
use gpui::App;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
use settings::{SettingsUI, Settings, SettingsSources};
#[derive(Deserialize, Debug)]
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug, SettingsUI)]
pub struct AudioSettings {
/// Opt into the new audio system.
#[serde(rename = "experimental.rodio_audio", default)]

View file

@ -10,7 +10,7 @@ use paths::remote_servers_dir;
use release_channel::{AppCommitSha, ReleaseChannel};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources, SettingsStore};
use settings::{SettingsUI, Settings, SettingsSources, SettingsStore};
use smol::{fs, io::AsyncReadExt};
use smol::{fs::File, process::Command};
use std::{
@ -113,6 +113,7 @@ impl Drop for MacOsUnmounter {
}
}
#[derive(SettingsUI)]
struct AutoUpdateSetting(bool);
/// Whether or not to automatically check for updates.

View file

@ -2,9 +2,9 @@ use anyhow::Result;
use gpui::App;
use schemars::JsonSchema;
use serde_derive::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
use settings::{SettingsUI, Settings, SettingsSources};
#[derive(Deserialize, Debug)]
#[derive(Deserialize, Debug, SettingsUI)]
pub struct CallSettings {
pub mute_on_join: bool,
pub share_on_join: bool,

View file

@ -31,7 +31,7 @@ use release_channel::{AppVersion, ReleaseChannel};
use rpc::proto::{AnyTypedEnvelope, EnvelopedMessage, PeerId, RequestMessage};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
use settings::{SettingsUI, Settings, SettingsSources};
use std::{
any::TypeId,
convert::TryFrom,
@ -101,7 +101,7 @@ pub struct ClientSettingsContent {
server_url: Option<String>,
}
#[derive(Deserialize)]
#[derive(Deserialize, SettingsUI)]
pub struct ClientSettings {
pub server_url: String,
}
@ -127,7 +127,7 @@ pub struct ProxySettingsContent {
proxy: Option<String>,
}
#[derive(Deserialize, Default)]
#[derive(Deserialize, Default, SettingsUI)]
pub struct ProxySettings {
pub proxy: Option<String>,
}
@ -504,7 +504,7 @@ impl<T: 'static> Drop for PendingEntitySubscription<T> {
}
}
#[derive(Copy, Clone, Deserialize, Debug)]
#[derive(Copy, Clone, Deserialize, Debug, SettingsUI)]
pub struct TelemetrySettings {
pub diagnostics: bool,
pub metrics: bool,

View file

@ -1,10 +1,10 @@
use gpui::Pixels;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
use settings::{SettingsUI, Settings, SettingsSources};
use workspace::dock::DockPosition;
#[derive(Deserialize, Debug)]
#[derive(Deserialize, Debug, SettingsUI)]
pub struct CollaborationPanelSettings {
pub button: bool,
pub dock: DockPosition,
@ -20,7 +20,7 @@ pub enum ChatPanelButton {
WhenInCall,
}
#[derive(Deserialize, Debug)]
#[derive(Deserialize, Debug, SettingsUI)]
pub struct ChatPanelSettings {
pub button: ChatPanelButton,
pub dock: DockPosition,
@ -43,7 +43,7 @@ pub struct ChatPanelSettingsContent {
pub default_width: Option<f32>,
}
#[derive(Deserialize, Debug)]
#[derive(Deserialize, Debug, SettingsUI)]
pub struct NotificationPanelSettings {
pub button: bool,
pub dock: DockPosition,
@ -66,7 +66,7 @@ pub struct PanelSettingsContent {
pub default_width: Option<f32>,
}
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug)]
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug, SettingsUI)]
pub struct MessageEditorSettings {
/// Whether to automatically replace emoji shortcodes with emoji characters.
/// For example: typing `:wave:` gets replaced with `👋`.

View file

@ -2,7 +2,7 @@ use dap_types::SteppingGranularity;
use gpui::{App, Global};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
use settings::{SettingsUI, Settings, SettingsSources};
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
@ -12,7 +12,7 @@ pub enum DebugPanelDockPosition {
Right,
}
#[derive(Serialize, Deserialize, JsonSchema, Clone, Copy)]
#[derive(Serialize, Deserialize, JsonSchema, Clone, Copy, SettingsUI)]
#[serde(default)]
pub struct DebuggerSettings {
/// Determines the stepping granularity.

View file

@ -6,12 +6,12 @@ use language::CursorShape;
use project::project_settings::DiagnosticSeverity;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources, VsCodeSettings};
use settings::{SettingsUI, Settings, SettingsSources, VsCodeSettings};
use util::serde::default_true;
/// Imports from the VSCode settings at
/// https://code.visualstudio.com/docs/reference/default-settings
#[derive(Deserialize, Clone)]
#[derive(Deserialize, Clone, SettingsUI)]
pub struct EditorSettings {
pub cursor_blink: bool,
pub cursor_shape: Option<CursorShape>,

View file

@ -3,10 +3,10 @@ use collections::HashMap;
use gpui::App;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
use settings::{SettingsUI, Settings, SettingsSources};
use std::sync::Arc;
#[derive(Deserialize, Serialize, Debug, Default, Clone, JsonSchema)]
#[derive(Deserialize, Serialize, Debug, Default, Clone, JsonSchema, SettingsUI)]
pub struct ExtensionSettings {
/// The extensions that should be automatically installed by Zed.
///

View file

@ -1,9 +1,9 @@
use anyhow::Result;
use schemars::JsonSchema;
use serde_derive::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
use settings::{SettingsUI, Settings, SettingsSources};
#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
#[derive(Deserialize, Debug, Clone, Copy, PartialEq, SettingsUI)]
pub struct FileFinderSettings {
pub file_icons: bool,
pub modal_max_width: Option<FileFinderWidth>,

View file

@ -5,7 +5,7 @@ use git::GitHostingProviderRegistry;
use gpui::App;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsStore};
use settings::{Settings, SettingsStore, SettingsUI};
use url::Url;
use util::ResultExt as _;
@ -78,7 +78,7 @@ pub struct GitHostingProviderConfig {
pub name: String,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, SettingsUI)]
pub struct GitHostingProviderSettings {
/// The list of custom Git hosting providers.
#[serde(default)]

View file

@ -2,7 +2,7 @@ use editor::ShowScrollbar;
use gpui::Pixels;
use schemars::JsonSchema;
use serde_derive::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
use settings::{SettingsUI, Settings, SettingsSources};
use workspace::dock::DockPosition;
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
@ -77,7 +77,7 @@ pub struct GitPanelSettingsContent {
pub collapse_untracked_diff: Option<bool>,
}
#[derive(Deserialize, Debug, Clone, PartialEq)]
#[derive(Deserialize, Debug, Clone, PartialEq, SettingsUI)]
pub struct GitPanelSettings {
pub button: bool,
pub dock: DockPosition,

View file

@ -2,7 +2,7 @@ use editor::{Editor, EditorSettings, MultiBufferSnapshot};
use gpui::{App, Entity, FocusHandle, Focusable, Subscription, Task, WeakEntity};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
use settings::{SettingsUI, Settings, SettingsSources};
use std::{fmt::Write, num::NonZeroU32, time::Duration};
use text::{Point, Selection};
use ui::{
@ -293,7 +293,7 @@ impl StatusItemView for CursorPosition {
}
}
#[derive(Clone, Copy, Default, PartialEq, JsonSchema, Deserialize, Serialize)]
#[derive(Clone, Copy, Default, PartialEq, JsonSchema, Deserialize, Serialize, SettingsUI)]
#[serde(rename_all = "snake_case")]
pub(crate) enum LineIndicatorFormat {
Short,

View file

@ -16,6 +16,13 @@ pub(crate) fn derive_action(input: TokenStream) -> TokenStream {
let mut deprecated = None;
let mut doc_str: Option<String> = None;
/*
*
* #[action()]
* Struct Foo {
* bar: bool // is bar considered an attribute
}
*/
for attr in &input.attrs {
if attr.path().is_ident("action") {
attr.parse_nested_meta(|meta| {

View file

@ -1,10 +1,10 @@
use gpui::App;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
use settings::{SettingsUI, Settings, SettingsSources};
/// The settings for the image viewer.
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Default)]
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Default, SettingsUI)]
pub struct ImageViewerSettings {
/// The unit to use for displaying image file sizes.
///

View file

@ -5,7 +5,7 @@ use editor::{Editor, SelectionEffects};
use gpui::{App, AppContext as _, Context, Window, actions};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
use settings::{SettingsUI, Settings, SettingsSources};
use std::{
fs::OpenOptions,
path::{Path, PathBuf},
@ -22,7 +22,7 @@ actions!(
);
/// Settings specific to journaling
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, SettingsUI)]
pub struct JournalSettings {
/// The path of the directory where journal entries are stored.
///

View file

@ -0,0 +1,55 @@
[package]
name = "keymap_editor"
version = "0.1.0"
edition.workspace = true
publish.workspace = true
license = "GPL-3.0-or-later"
[lints]
workspace = true
[lib]
path = "src/keymap_editor.rs"
[dependencies]
anyhow.workspace = true
collections.workspace = true
command_palette.workspace = true
command_palette_hooks.workspace = true
component.workspace = true
db.workspace = true
editor.workspace = true
feature_flags.workspace = true
fs.workspace = true
fuzzy.workspace = true
gpui.workspace = true
itertools.workspace = true
language.workspace = true
log.workspace = true
menu.workspace = true
notifications.workspace = true
paths.workspace = true
project.workspace = true
search.workspace = true
serde.workspace = true
serde_json.workspace = true
settings.workspace = true
telemetry.workspace = true
tempfile.workspace = true
theme.workspace = true
tree-sitter-json.workspace = true
tree-sitter-rust.workspace = true
ui.workspace = true
ui_input.workspace = true
util.workspace = true
vim.workspace = true
workspace-hack.workspace = true
workspace.workspace = true
zed_actions.workspace = true
[dev-dependencies]
db = {"workspace"= true, "features" = ["test-support"]}
fs = { workspace = true, features = ["test-support"] }
gpui = { workspace = true, features = ["test-support"] }
project = { workspace = true, features = ["test-support"] }
workspace = { workspace = true, features = ["test-support"] }

View file

@ -0,0 +1 @@
../../LICENSE-GPL

View file

@ -1,3 +1,5 @@
mod ui_components;
use std::{
cmp::{self},
ops::{Not as _, Range},
@ -35,7 +37,7 @@ use workspace::{
};
use crate::{
keybindings::persistence::KEYBINDING_EDITORS,
persistence::KEYBINDING_EDITORS,
ui_components::{
keystroke_input::{ClearKeystrokes, KeystrokeInput, StartRecording, StopRecording},
table::{ColumnWidths, ResizeBehavior, Table, TableInteractionState},

View file

@ -17,7 +17,7 @@ use serde::{
};
use settings::{
ParameterizedJsonSchema, Settings, SettingsLocation, SettingsSources, SettingsStore,
ParameterizedJsonSchema, Settings, SettingsLocation, SettingsSources, SettingsStore, SettingsUI,
};
use shellexpand;
use std::{borrow::Cow, num::NonZeroU32, path::Path, slice, sync::Arc};
@ -55,7 +55,7 @@ pub fn all_language_settings<'a>(
}
/// The settings for all languages.
#[derive(Debug, Clone)]
#[derive(Debug, Clone, SettingsUI)]
pub struct AllLanguageSettings {
/// The edit prediction settings.
pub edit_predictions: EditPredictionSettings,

View file

@ -5,7 +5,7 @@ use collections::HashMap;
use gpui::App;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
use settings::{SettingsUI, Settings, SettingsSources};
use crate::provider::{
self,
@ -29,7 +29,7 @@ pub fn init_settings(cx: &mut App) {
AllLanguageModelSettings::register(cx);
}
#[derive(Default)]
#[derive(Default, SettingsUI)]
pub struct AllLanguageModelSettings {
pub anthropic: AnthropicSettings,
pub bedrock: AmazonBedrockSettings,

View file

@ -2,7 +2,7 @@ use editor::ShowScrollbar;
use gpui::Pixels;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
use settings::{SettingsUI, Settings, SettingsSources};
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Copy, PartialEq)]
#[serde(rename_all = "snake_case")]
@ -18,7 +18,7 @@ pub enum ShowIndentGuides {
Never,
}
#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
#[derive(Deserialize, Debug, Clone, Copy, PartialEq, SettingsUI)]
pub struct OutlinePanelSettings {
pub button: bool,
pub default_width: Pixels,

View file

@ -948,7 +948,7 @@ pub enum PulledDiagnostics {
/// Whether to disable all AI features in Zed.
///
/// Default: false
#[derive(Copy, Clone, Debug)]
#[derive(Copy, Clone, Debug, settings::SettingsUI)]
pub struct DisableAiSettings {
pub disable_ai: bool,
}

View file

@ -18,8 +18,8 @@ use rpc::{
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{
InvalidSettingsError, LocalSettingsKind, Settings, SettingsLocation, SettingsSources,
SettingsStore, parse_json_with_comments, watch_config_file,
SettingsUI, InvalidSettingsError, LocalSettingsKind, Settings,
SettingsLocation, SettingsSources, SettingsStore, parse_json_with_comments, watch_config_file,
};
use std::{
collections::BTreeMap,
@ -36,7 +36,7 @@ use crate::{
worktree_store::{WorktreeStore, WorktreeStoreEvent},
};
#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema)]
#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema, SettingsUI)]
pub struct ProjectSettings {
/// Configuration for language servers.
///

View file

@ -2,7 +2,7 @@ use editor::ShowScrollbar;
use gpui::Pixels;
use schemars::JsonSchema;
use serde_derive::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
use settings::{SettingsUI, Settings, SettingsSources};
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Copy, PartialEq)]
#[serde(rename_all = "snake_case")]
@ -28,7 +28,7 @@ pub enum EntrySpacing {
Standard,
}
#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
#[derive(Deserialize, Debug, Clone, Copy, PartialEq, SettingsUI)]
pub struct ProjectPanelSettings {
pub button: bool,
pub hide_gitignore: bool,

View file

@ -19,7 +19,7 @@ use remote::ssh_session::{ConnectionIdentifier, SshPortForwardOption};
use remote::{SshConnectionOptions, SshPlatform, SshRemoteClient};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
use settings::{SettingsUI, Settings, SettingsSources};
use theme::ThemeSettings;
use ui::{
ActiveTheme, Color, Context, Icon, IconName, IconSize, InteractiveElement, IntoElement, Label,
@ -28,7 +28,7 @@ use ui::{
use util::serde::default_true;
use workspace::{AppState, ModalView, Workspace};
#[derive(Deserialize)]
#[derive(Deserialize, SettingsUI)]
pub struct SshSettings {
pub ssh_connections: Option<Vec<SshConnection>>,
/// Whether to read ~/.ssh/config for ssh connection sources.

View file

@ -4,9 +4,9 @@ use editor::EditorSettings;
use gpui::App;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
use settings::{SettingsUI, Settings, SettingsSources};
#[derive(Debug, Default)]
#[derive(Debug, Default, SettingsUI)]
pub struct JupyterSettings {
pub kernel_selections: HashMap<String, String>,
}

View file

@ -31,6 +31,7 @@ schemars.workspace = true
serde.workspace = true
serde_derive.workspace = true
serde_json.workspace = true
settings_ui_macros.workspace = true
serde_json_lenient.workspace = true
smallvec.workspace = true
tree-sitter-json.workspace = true

View file

@ -1,13 +1,17 @@
use std::fmt::{Display, Formatter};
use crate::{Settings, SettingsSources, VsCodeSettings};
use crate as settings;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources, VsCodeSettings};
use settings_ui_macros::SettingsUI;
/// Base key bindings scheme. Base keymaps can be overridden with user keymaps.
///
/// Default: VSCode
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Default)]
#[derive(
Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Default, SettingsUI,
)]
pub enum BaseKeymap {
#[default]
VSCode,

View file

@ -5,6 +5,7 @@ mod keymap_file;
mod settings_file;
mod settings_json;
mod settings_store;
mod settings_ui;
mod vscode_import;
use gpui::{App, Global};
@ -25,6 +26,9 @@ pub use settings_store::{
InvalidSettingsError, LocalSettingsKind, Settings, SettingsLocation, SettingsSources,
SettingsStore,
};
pub use settings_ui::*;
// Re-export the derive macro
pub use settings_ui_macros::SettingsUI;
pub use vscode_import::{VsCodeSettings, VsCodeSettingsSource};
#[derive(Clone, Debug, PartialEq)]

View file

@ -31,14 +31,15 @@ use util::{
pub type EditorconfigProperties = ec4rs::Properties;
use crate::{
ActiveSettingsProfileName, ParameterizedJsonSchema, SettingsJsonSchemaParams, VsCodeSettings,
WorktreeId, parse_json_with_comments, update_value_in_json_text,
ActiveSettingsProfileName, ParameterizedJsonSchema, SettingsJsonSchemaParams, SettingsUIItem,
SettingsUIRender, VsCodeSettings, WorktreeId, parse_json_with_comments,
settings_ui::SettingsUI, update_value_in_json_text,
};
/// A value that can be defined as a user setting.
///
/// Settings can be loaded from a combination of multiple JSON files.
pub trait Settings: 'static + Send + Sync {
pub trait Settings: SettingsUI + 'static + Send + Sync {
/// The name of a key within the JSON file from which this setting should
/// be deserialized. If this is `None`, then the setting will be deserialized
/// from the root object.
@ -272,6 +273,7 @@ trait AnySettingValue: 'static + Send + Sync {
text: &mut String,
edits: &mut Vec<(Range<usize>, String)>,
);
fn settings_ui_item(&self) -> SettingsUIItem;
}
struct DeserializedSetting(Box<dyn Any>);
@ -604,6 +606,12 @@ impl SettingsStore {
rx
}
pub fn settings_ui_items(&self) -> impl IntoIterator<Item = SettingsUIItem> {
self.setting_values
.values()
.map(|item| item.settings_ui_item())
}
}
impl SettingsStore {
@ -1498,6 +1506,10 @@ impl<T: Settings> AnySettingValue for SettingValue<T> {
edits,
);
}
fn settings_ui_item(&self) -> SettingsUIItem {
<T as SettingsUI>::settings_ui_item()
}
}
#[cfg(test)]
@ -1505,7 +1517,10 @@ mod tests {
use crate::VsCodeSettingsSource;
use super::*;
// This is so the SettingsUI macro can still work properly
use crate as settings;
use serde_derive::Deserialize;
use settings_ui_macros::SettingsUI;
use unindent::Unindent;
#[gpui::test]
@ -2048,14 +2063,14 @@ mod tests {
pretty_assertions::assert_eq!(new, expected);
}
#[derive(Debug, PartialEq, Deserialize)]
#[derive(Debug, PartialEq, Deserialize, SettingsUI)]
struct UserSettings {
name: String,
age: u32,
staff: bool,
}
#[derive(Default, Clone, Serialize, Deserialize, JsonSchema)]
#[derive(Default, Clone, Serialize, Deserialize, JsonSchema, SettingsUI)]
struct UserSettingsContent {
name: Option<String>,
age: Option<u32>,
@ -2075,7 +2090,7 @@ mod tests {
}
}
#[derive(Debug, Deserialize, PartialEq)]
#[derive(Debug, Deserialize, PartialEq, SettingsUI)]
struct TurboSetting(bool);
impl Settings for TurboSetting {
@ -2089,7 +2104,7 @@ mod tests {
fn import_from_vscode(_vscode: &VsCodeSettings, _current: &mut Self::FileContent) {}
}
#[derive(Clone, Debug, PartialEq, Deserialize)]
#[derive(Clone, Debug, PartialEq, Deserialize, SettingsUI)]
struct MultiKeySettings {
#[serde(default)]
key1: String,
@ -2122,7 +2137,7 @@ mod tests {
}
}
#[derive(Debug, Deserialize)]
#[derive(Debug, Deserialize, SettingsUI)]
struct JournalSettings {
pub path: String,
pub hour_format: HourFormat,
@ -2223,7 +2238,7 @@ mod tests {
);
}
#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, SettingsUI)]
struct LanguageSettings {
#[serde(default)]
languages: HashMap<String, LanguageSettingEntry>,

View file

@ -0,0 +1,152 @@
use std::any::Any;
use gpui::{AnyElement, App, Window};
pub trait SettingsUI {
fn settings_ui_render() -> SettingsUIRender {
SettingsUIRender::None
}
fn settings_ui_item() -> SettingsUIItem;
}
pub struct SettingsUIItem {
// TODO: move this back here once there isn't a None variant
// pub path: &'static str,
// pub title: &'static str,
pub item: SettingsUIItemVariant,
}
pub enum SettingsUIItemVariant {
Group {
path: &'static str,
title: &'static str,
group: SettingsUIItemGroup,
},
Item {
path: &'static str,
item: SettingsUIItemSingle,
},
// TODO: remove
None,
}
pub struct SettingsUIItemGroup {
pub items: Vec<SettingsUIItem>,
}
pub enum SettingsUIItemSingle {
// TODO: default/builtin variants
SwitchField,
Custom(Box<dyn Fn(&dyn Any, &mut Window, &mut App) -> AnyElement>),
}
pub enum SettingsUIRender {
Group {
title: &'static str,
items: Vec<SettingsUIItem>,
},
Item(SettingsUIItemSingle),
None,
}
impl SettingsUI for bool {
fn settings_ui_render() -> SettingsUIRender {
SettingsUIRender::Item(SettingsUIItemSingle::SwitchField)
}
fn settings_ui_item() -> SettingsUIItem {
SettingsUIItem {
item: SettingsUIItemVariant::None,
}
}
}
/*
FOR DOC COMMENTS ON "Contents" TYPES:
define trait: SettingsUIDocProvider with derive
derive creates:
impl SettingsUIDocProvider for Foo {
fn settings_ui_doc() -> Hashmap<&'static str, &'static str> {
Hashmap::from(Foo.fields.map(|field| (field.name, field.doc_comment)))
}
}
on derive settings_ui, have attr
#[settings_ui(doc_from = "Foo")]
and have derive(SettingsUI) do
if doc_from {
quote! {
doc_comments = doc_from.type::settings_ui_doc();
for fields {
field.doc_comment = doc_comments.get(field.name).unwrap()
}
}
} else {
doc_comments = <Self as Settings>FileContent::settings_ui
}
FOR PATH:
if derive attr also contains "Settings", then we can use <T as Settings>::KEY,
otherwise we need a #[settings_ui(path = ...)].
FOR BOTH OF ABOVE, we can check if derive() attr contains Settings, otherwise assert that both doc_from and path are present
like so: #[settings_ui(doc_from = "Foo", path = "foo")]
*/
/*
#[derive(SettingsUI)]
#[settings_ui(group = "Foo")]
struct Foo {
// #[settings_ui(render = "my_render_function")]
pub toggle: bool,
pub font_size: u32,
Group(vec![Item {path: "toggle", item: SwitchField}])
}
macro code:
settings_ui_item() {
group.items = struct.fields.map((field_name, field_type) => quote! { SettingsUIItem::Item {path: #field_type::settings_ui_path().unwrap_or_else(|| #field_name), item: if field.attrs.render { #render } else field::settings_ui_render()}})
}
*/
/* NOTES:
# Root Group
some_setting: {
# First Item
# this shouldn't be a group
# it should just be item with path "some_bool.enabled" and title "Some Bool"
"some_bool": {
# this should
enabled: true | false
}
# Second Item
"some_other_thing": "foo" | "bar" | "baz"
}
Structure:
Group {
path: "some_item",
items: [
Item(
path: ["some_bool", "enabled"],
),
Item(
path: ["some_other_thing"],
)
]
}
is the following better than "foo.enabled"?
- for objects with single key "enabled", should just be a bool, with no "enabled"
for objects with enabled and other settings, enabled should be implicit,
so
"vim": false, # disabled
"vim": true, # enabled with default settings
"vim": {
"default_mode": "HelixNormal"
} # enabled with custom settings
*/

View file

@ -11,45 +11,24 @@ workspace = true
[lib]
path = "src/settings_ui.rs"
[features]
default = []
[dependencies]
anyhow.workspace = true
collections.workspace = true
command_palette.workspace = true
command_palette_hooks.workspace = true
component.workspace = true
db.workspace = true
editor.workspace = true
feature_flags.workspace = true
fs.workspace = true
fuzzy.workspace = true
gpui.workspace = true
itertools.workspace = true
language.workspace = true
log.workspace = true
menu.workspace = true
notifications.workspace = true
paths.workspace = true
project.workspace = true
search.workspace = true
serde.workspace = true
serde_json.workspace = true
settings.workspace = true
telemetry.workspace = true
tempfile.workspace = true
theme.workspace = true
tree-sitter-json.workspace = true
tree-sitter-rust.workspace = true
settings.workspace = true
ui.workspace = true
ui_input.workspace = true
util.workspace = true
vim.workspace = true
workspace-hack.workspace = true
workspace.workspace = true
zed_actions.workspace = true
[dev-dependencies]
db = {"workspace"= true, "features" = ["test-support"]}
fs = { workspace = true, features = ["test-support"] }
gpui = { workspace = true, features = ["test-support"] }
project = { workspace = true, features = ["test-support"] }
workspace = { workspace = true, features = ["test-support"] }
# Uncomment other workspace dependencies as needed
# assistant.workspace = true
# client.workspace = true
# project.workspace = true
# settings.workspace = true

View file

@ -5,16 +5,14 @@ use std::any::TypeId;
use command_palette_hooks::CommandPaletteFilter;
use editor::EditorSettingsControls;
use feature_flags::{FeatureFlag, FeatureFlagViewExt};
use gpui::{App, Entity, EventEmitter, FocusHandle, Focusable, actions};
use ui::prelude::*;
use gpui::{App, Entity, EventEmitter, FocusHandle, Focusable, ReadGlobal, actions};
use settings::{SettingsStore, SettingsUIItemSingle, SettingsUIItemVariant};
use ui::{SwitchField, prelude::*};
use workspace::item::{Item, ItemEvent};
use workspace::{Workspace, with_active_or_new_workspace};
use crate::appearance_settings_controls::AppearanceSettingsControls;
pub mod keybindings;
pub mod ui_components;
pub struct SettingsUiFeatureFlag;
impl FeatureFlag for SettingsUiFeatureFlag {
@ -75,8 +73,6 @@ pub fn init(cx: &mut App) {
.detach();
})
.detach();
keybindings::init(cx);
}
pub struct SettingsPage {
@ -125,6 +121,52 @@ impl Render for SettingsPage {
.p_4()
.size_full()
.gap_4()
.children(
SettingsStore::global(cx)
.settings_ui_items()
.into_iter()
.flat_map(|item| match item.item {
settings::SettingsUIItemVariant::Group { title, path, group } => Some(
div()
.child(Label::new(title).size(LabelSize::Large))
.children(group.items.iter().map(|item| {
match &item.item {
settings::SettingsUIItemVariant::Group {
path,
title,
group,
} => div()
.child(format!("Subgroup: {}", title))
.into_any_element(),
settings::SettingsUIItemVariant::Item { path, item } => {
match item {
SettingsUIItemSingle::Custom(_) => div()
.child(format!("Item: {}", path))
.into_any_element(),
SettingsUIItemSingle::SwitchField => div()
.child(SwitchField::new(
ElementId::Name(SharedString::new_static(
path,
)),
SharedString::new_static(path),
None,
ToggleState::Unselected,
|_, _, _| {},
))
.into_any_element(),
}
}
settings::SettingsUIItemVariant::None => {
div().child("None").into_any_element()
}
}
})),
),
settings::SettingsUIItemVariant::Item { path, item } => todo!(),
settings::SettingsUIItemVariant::None => None,
}),
)
.child(Label::new("Settings").size(LabelSize::Large))
.child(
v_flex().gap_1().child(Label::new("Appearance")).child(

View file

@ -0,0 +1,21 @@
[package]
name = "settings_ui_macros"
version = "0.1.0"
edition.workspace = true
publish.workspace = true
license = "GPL-3.0-or-later"
[lib]
path = "src/settings_ui_macros.rs"
proc-macro = true
[lints]
workspace = true
[features]
default = []
[dependencies]
proc-macro2.workspace = true
quote.workspace = true
syn.workspace = true

View file

@ -0,0 +1 @@
../../LICENSE-GPL

View file

@ -0,0 +1,131 @@
use proc_macro2::TokenStream;
use quote::{ToTokens, quote};
use syn::{DeriveInput, LitStr, Token, parse_macro_input};
/// Derive macro for the `SettingsUI` marker trait.
///
/// This macro automatically implements the `SettingsUI` trait for the annotated type.
/// The `SettingsUI` trait is a marker trait used to indicate that a type can be
/// displayed in the settings UI.
///
/// # Example
///
/// ```
/// use settings::SettingsUI;
/// use settings_ui_macros::SettingsUI;
///
/// #[derive(SettingsUI)]
/// #[settings_ui(group = "Standard")]
/// struct MySettings {
/// enabled: bool,
/// count: usize,
/// }
/// ```
#[proc_macro_derive(SettingsUI, attributes(settings_ui))]
pub fn derive_settings_ui(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = &input.ident;
// Handle generic parameters if present
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
let mut group_name = Option::<String>::None;
for attr in &input.attrs {
if attr.path().is_ident("settings_ui") {
attr.parse_nested_meta(|meta| {
if meta.path.is_ident("group") {
if group_name.is_some() {
return Err(meta.error("Only one 'group' path can be specified"));
}
meta.input.parse::<Token![=]>()?;
let lit: LitStr = meta.input.parse()?;
group_name = Some(lit.value());
}
Ok(())
})
.unwrap_or_else(|e| panic!("in #[settings_ui] attribute: {}", e));
}
}
// let mut root_item = vec![];
// for field in struct {
//
// match field::settings_ui_render()
// Group(items) => {
// let item = items.map(|item| something);
// item
// items.push(item::settings_ui_render());
// root_item.push(Group(items));
// },
// Leaf(item) => {
// root_item.push(item);
// }
// }
// }
//
// group.items = struct.fields.map((field_name, field_type) => quote! { SettingsUIItem::Item {path: #field_type::settings_ui_path().unwrap_or_else(|| #field_name), item: if field.attrs.render { #render } else field::settings_ui_render()}})
// }
fn map_ui_item_to_render(path: &str, ty: TokenStream) -> TokenStream {
quote! {
settings::SettingsUIItem {
item: match #ty::settings_ui_render() {
settings::SettingsUIRender::Group{title, items} => settings::SettingsUIItemVariant::Group {
title,
path: #path,
group: settings::SettingsUIItemGroup { items },
},
settings::SettingsUIRender::Item(item) => settings::SettingsUIItemVariant::Item {
path: #path,
item,
},
settings::SettingsUIRender::None => settings::SettingsUIItemVariant::None,
}
}
}
}
let ui_render_fn_body = if let Some(group_name) = group_name {
let fields = match input.data {
syn::Data::Struct(data_struct) => data_struct
.fields
.iter()
.map(|field| {
(
field.ident.clone().expect("tuple fields").to_string(),
field.ty.to_token_stream(),
)
})
.collect(),
syn::Data::Enum(data_enum) => vec![], // todo! enums
syn::Data::Union(data_union) => unimplemented!("Derive SettingsUI for unions"),
};
let items = fields
.into_iter()
.map(|(name, ty)| map_ui_item_to_render(&name, ty));
quote! {
settings::SettingsUIRender::Group{ title: #group_name, items: vec![#(#items),*] }
}
} else {
quote! {
settings::SettingsUIRender::None
}
};
let settings_ui_item_fn_body = map_ui_item_to_render("todo! define path", quote! { Self });
let expanded = quote! {
impl #impl_generics settings::SettingsUI for #name #ty_generics #where_clause {
fn settings_ui_render() -> settings::SettingsUIRender {
#ui_render_fn_body
}
fn settings_ui_item() -> settings::SettingsUIItem {
#settings_ui_item_fn_body
}
}
};
proc_macro::TokenStream::from(expanded)
}

View file

@ -6,7 +6,7 @@ use gpui::{AbsoluteLength, App, FontFallbacks, FontFeatures, FontWeight, Pixels,
use schemars::JsonSchema;
use serde_derive::{Deserialize, Serialize};
use settings::SettingsSources;
use settings::{SettingsSources, SettingsUI};
use std::path::PathBuf;
use task::Shell;
use theme::FontFamilyName;
@ -24,7 +24,7 @@ pub struct Toolbar {
pub breadcrumbs: bool,
}
#[derive(Clone, Debug, Deserialize)]
#[derive(Clone, Debug, Deserialize, SettingsUI)]
pub struct TerminalSettings {
pub shell: Shell,
pub working_directory: WorkingDirectory,

View file

@ -13,7 +13,7 @@ use gpui::{
use refineable::Refineable;
use schemars::{JsonSchema, json_schema};
use serde::{Deserialize, Serialize};
use settings::{ParameterizedJsonSchema, Settings, SettingsSources};
use settings::{ParameterizedJsonSchema, Settings, SettingsSources, SettingsUI};
use std::sync::Arc;
use util::ResultExt as _;
use util::schemars::replace_subschema;
@ -87,7 +87,7 @@ impl From<UiDensity> for String {
}
/// Customizable settings for the UI and theme system.
#[derive(Clone, PartialEq)]
#[derive(Clone, PartialEq, SettingsUI)]
pub struct ThemeSettings {
/// The UI font size. Determines the size of text in the UI,
/// as well as the size of a [gpui::Rems] unit.

View file

@ -42,7 +42,7 @@ rpc.workspace = true
schemars.workspace = true
serde.workspace = true
settings.workspace = true
settings_ui.workspace = true
keymap_editor.workspace = true
smallvec.workspace = true
story = { workspace = true, optional = true }
telemetry.workspace = true

View file

@ -27,10 +27,10 @@ use gpui::{
IntoElement, MouseButton, ParentElement, Render, StatefulInteractiveElement, Styled,
Subscription, WeakEntity, Window, actions, div,
};
use keymap_editor;
use onboarding_banner::OnboardingBanner;
use project::Project;
use settings::Settings as _;
use settings_ui::keybindings;
use std::sync::Arc;
use theme::ActiveTheme;
use title_bar_settings::TitleBarSettings;
@ -681,7 +681,7 @@ impl TitleBar {
"Settings Profiles",
zed_actions::settings_profile_selector::Toggle.boxed_clone(),
)
.action("Key Bindings", Box::new(keybindings::OpenKeymapEditor))
.action("Key Bindings", Box::new(keymap_editor::OpenKeymapEditor))
.action(
"Themes…",
zed_actions::theme_selector::Toggle::default().boxed_clone(),
@ -729,7 +729,7 @@ impl TitleBar {
"Settings Profiles",
zed_actions::settings_profile_selector::Toggle.boxed_clone(),
)
.action("Key Bindings", Box::new(keybindings::OpenKeymapEditor))
.action("Key Bindings", Box::new(keymap_editor::OpenKeymapEditor))
.action(
"Themes…",
zed_actions::theme_selector::Toggle::default().boxed_clone(),

View file

@ -1,9 +1,10 @@
use db::anyhow;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
use settings::{Settings, SettingsSources, SettingsUI};
#[derive(Copy, Clone, Deserialize, Debug)]
#[derive(Copy, Clone, Deserialize, Debug, SettingsUI)]
#[settings_ui(group = "Title Bar")]
pub struct TitleBarSettings {
pub show_branch_icon: bool,
pub show_onboarding_banner: bool,

View file

@ -39,7 +39,9 @@ use object::Object;
use schemars::JsonSchema;
use serde::Deserialize;
use serde_derive::Serialize;
use settings::{Settings, SettingsSources, SettingsStore, update_settings_file};
use settings::{
SettingsUI, Settings, SettingsSources, SettingsStore, update_settings_file,
};
use state::{Mode, Operator, RecordedSelection, SearchState, VimGlobals};
use std::{mem, ops::Range, sync::Arc};
use surrounds::SurroundsType;
@ -1774,7 +1776,7 @@ struct CursorShapeSettings {
pub insert: Option<CursorShape>,
}
#[derive(Deserialize)]
#[derive(Deserialize, SettingsUI)]
struct VimSettings {
pub default_mode: Mode,
pub toggle_relative_line_numbers: bool,

View file

@ -6,7 +6,7 @@
use anyhow::Result;
use gpui::App;
use settings::{Settings, SettingsSources};
use settings::{Settings, SettingsSources, SettingsUI};
/// Initializes the `vim_mode_setting` crate.
pub fn init(cx: &mut App) {
@ -17,6 +17,7 @@ pub fn init(cx: &mut App) {
/// Whether or not to enable Vim mode.
///
/// Default: false
#[derive(SettingsUI)]
pub struct VimModeSetting(pub bool);
impl Settings for VimModeSetting {
@ -43,6 +44,7 @@ impl Settings for VimModeSetting {
/// Whether or not to enable Helix mode.
///
/// Default: false
#[derive(SettingsUI)]
pub struct HelixModeSetting(pub bool);
impl Settings for HelixModeSetting {

View file

@ -17,7 +17,7 @@ use gpui::{
use project::{Project, ProjectEntryId, ProjectPath};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsLocation, SettingsSources};
use settings::{SettingsUI, Settings, SettingsLocation, SettingsSources};
use smallvec::SmallVec;
use std::{
any::{Any, TypeId},
@ -49,7 +49,7 @@ impl Default for SaveOptions {
}
}
#[derive(Deserialize)]
#[derive(Deserialize, SettingsUI)]
pub struct ItemSettings {
pub git_status: bool,
pub close_position: ClosePosition,
@ -59,7 +59,7 @@ pub struct ItemSettings {
pub show_close_button: ShowCloseButton,
}
#[derive(Deserialize)]
#[derive(Deserialize, SettingsUI)]
pub struct PreviewTabsSettings {
pub enabled: bool,
pub enable_preview_from_file_finder: bool,

View file

@ -6,9 +6,9 @@ use collections::HashMap;
use gpui::App;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
use settings::{SettingsUI, Settings, SettingsSources};
#[derive(Deserialize)]
#[derive(Deserialize, SettingsUI)]
pub struct WorkspaceSettings {
pub active_pane_modifiers: ActivePanelModifiers,
pub bottom_dock_layout: BottomDockLayout,
@ -204,7 +204,7 @@ pub struct WorkspaceSettingsContent {
pub close_on_file_delete: Option<bool>,
}
#[derive(Deserialize)]
#[derive(Deserialize, SettingsUI)]
pub struct TabBarSettings {
pub show: bool,
pub show_nav_history_buttons: bool,

View file

@ -4,10 +4,10 @@ use anyhow::Context as _;
use gpui::App;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
use settings::{SettingsUI, Settings, SettingsSources};
use util::paths::PathMatcher;
#[derive(Clone, PartialEq, Eq)]
#[derive(Clone, PartialEq, Eq, SettingsUI)]
pub struct WorktreeSettings {
pub file_scan_inclusions: PathMatcher,
pub file_scan_exclusions: PathMatcher,

View file

@ -131,6 +131,7 @@ serde_json.workspace = true
session.workspace = true
settings.workspace = true
settings_ui.workspace = true
keymap_editor.workspace = true
shellexpand.workspace = true
smol.workspace = true
snippet_provider.workspace = true

View file

@ -632,6 +632,7 @@ pub fn main() {
svg_preview::init(cx);
onboarding::init(cx);
settings_ui::init(cx);
keymap_editor::init(cx);
extensions_ui::init(cx);
zeta::init(cx);
inspector_ui::init(app_state.clone(), cx);

View file

@ -1482,7 +1482,7 @@ fn reload_keymaps(cx: &mut App, mut user_key_bindings: Vec<KeyBinding>) {
workspace::NewWindow,
)]);
// todo: nicer api here?
settings_ui::keybindings::KeymapEventChannel::trigger_keymap_changed(cx);
keymap_editor::KeymapEventChannel::trigger_keymap_changed(cx);
}
pub fn load_default_keymap(cx: &mut App) {

View file

@ -1,6 +1,5 @@
use collab_ui::collab_panel;
use gpui::{Menu, MenuItem, OsAction};
use settings_ui::keybindings;
use terminal_view::terminal_panel;
pub fn app_menus() -> Vec<Menu> {
@ -17,7 +16,7 @@ pub fn app_menus() -> Vec<Menu> {
name: "Settings".into(),
items: vec![
MenuItem::action("Open Settings", super::OpenSettings),
MenuItem::action("Open Key Bindings", keybindings::OpenKeymapEditor),
MenuItem::action("Open Key Bindings", keymap_editor::OpenKeymapEditor),
MenuItem::action("Open Default Settings", super::OpenDefaultSettings),
MenuItem::action(
"Open Default Key Bindings",

View file

@ -3,7 +3,7 @@ use anyhow::Result;
use gpui::App;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsStore};
use settings::{SettingsUI, Settings, SettingsStore};
pub fn init(cx: &mut App) {
ZlogSettings::register(cx);
@ -15,7 +15,7 @@ pub fn init(cx: &mut App) {
.detach();
}
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, SettingsUI)]
pub struct ZlogSettings {
#[serde(default, flatten)]
pub scopes: std::collections::HashMap<String, String>,