Compare commits
7 commits
main
...
settings-u
Author | SHA1 | Date | |
---|---|---|---|
![]() |
e42d5a8264 | ||
![]() |
8ff656c999 | ||
![]() |
1fd0f7a46b | ||
![]() |
c1631b6e8c | ||
![]() |
ba9d109289 | ||
![]() |
15f634f8cc | ||
![]() |
3c0ec5f612 |
59 changed files with 610 additions and 156 deletions
76
Cargo.lock
generated
76
Cargo.lock
generated
|
@ -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",
|
||||
|
|
10
Cargo.toml
10
Cargo.toml
|
@ -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" }
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 `👋`.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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| {
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
|
|
55
crates/keymap_editor/Cargo.toml
Normal file
55
crates/keymap_editor/Cargo.toml
Normal 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"] }
|
1
crates/keymap_editor/LICENSE-GPL
Symbolic link
1
crates/keymap_editor/LICENSE-GPL
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../LICENSE-GPL
|
|
@ -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},
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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>,
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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>,
|
||||
|
|
152
crates/settings/src/settings_ui.rs
Normal file
152
crates/settings/src/settings_ui.rs
Normal 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
|
||||
*/
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
21
crates/settings_ui_macros/Cargo.toml
Normal file
21
crates/settings_ui_macros/Cargo.toml
Normal 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
|
1
crates/settings_ui_macros/LICENSE-GPL
Symbolic link
1
crates/settings_ui_macros/LICENSE-GPL
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../LICENSE-GPL
|
131
crates/settings_ui_macros/src/settings_ui_macros.rs
Normal file
131
crates/settings_ui_macros/src/settings_ui_macros.rs
Normal 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)
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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>,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue