settings_content.rs

   1mod agent;
   2mod editor;
   3mod extension;
   4mod fallible_options;
   5mod language;
   6mod language_model;
   7pub mod merge_from;
   8mod project;
   9mod serde_helper;
  10mod terminal;
  11mod theme;
  12mod workspace;
  13
  14pub use agent::*;
  15pub use editor::*;
  16pub use extension::*;
  17pub use fallible_options::*;
  18pub use language::*;
  19pub use language_model::*;
  20pub use merge_from::MergeFrom as MergeFromTrait;
  21pub use project::*;
  22use serde::de::DeserializeOwned;
  23pub use serde_helper::{
  24    serialize_f32_with_two_decimal_places, serialize_optional_f32_with_two_decimal_places,
  25};
  26use settings_json::parse_json_with_comments;
  27pub use terminal::*;
  28pub use theme::*;
  29pub use workspace::*;
  30
  31use collections::{HashMap, IndexMap};
  32use schemars::JsonSchema;
  33use serde::{Deserialize, Serialize};
  34use settings_macros::{MergeFrom, with_fallible_options};
  35
  36/// Defines a settings override struct where each field is
  37/// `Option<Box<SettingsContent>>`, along with:
  38/// - `OVERRIDE_KEYS`: a `&[&str]` of the field names (the JSON keys)
  39/// - `get_by_key(&self, key) -> Option<&SettingsContent>`: accessor by key
  40///
  41/// The field list is the single source of truth for the override key strings.
  42macro_rules! settings_overrides {
  43    (
  44        $(#[$attr:meta])*
  45        pub struct $name:ident { $($field:ident),* $(,)? }
  46    ) => {
  47        $(#[$attr])*
  48        pub struct $name {
  49            $(pub $field: Option<Box<SettingsContent>>,)*
  50        }
  51
  52        impl $name {
  53            /// The JSON override keys, derived from the field names on this struct.
  54            pub const OVERRIDE_KEYS: &[&str] = &[$(stringify!($field)),*];
  55
  56            /// Look up an override by its JSON key name.
  57            pub fn get_by_key(&self, key: &str) -> Option<&SettingsContent> {
  58                match key {
  59                    $(stringify!($field) => self.$field.as_deref(),)*
  60                    _ => None,
  61                }
  62            }
  63        }
  64    }
  65}
  66use std::collections::BTreeSet;
  67use std::sync::Arc;
  68pub use util::serde::default_true;
  69
  70#[derive(Debug, Clone, PartialEq, Eq)]
  71pub enum ParseStatus {
  72    /// Settings were parsed successfully
  73    Success,
  74    /// Settings failed to parse
  75    Failed { error: String },
  76}
  77
  78#[with_fallible_options]
  79#[derive(Debug, PartialEq, Default, Clone, Serialize, Deserialize, JsonSchema, MergeFrom)]
  80pub struct SettingsContent {
  81    #[serde(flatten)]
  82    pub project: ProjectSettingsContent,
  83
  84    #[serde(flatten)]
  85    pub theme: Box<ThemeSettingsContent>,
  86
  87    #[serde(flatten)]
  88    pub extension: ExtensionSettingsContent,
  89
  90    #[serde(flatten)]
  91    pub workspace: WorkspaceSettingsContent,
  92
  93    #[serde(flatten)]
  94    pub editor: EditorSettingsContent,
  95
  96    #[serde(flatten)]
  97    pub remote: RemoteSettingsContent,
  98
  99    /// Settings related to the file finder.
 100    pub file_finder: Option<FileFinderSettingsContent>,
 101
 102    pub git_panel: Option<GitPanelSettingsContent>,
 103
 104    pub tabs: Option<ItemSettingsContent>,
 105    pub tab_bar: Option<TabBarSettingsContent>,
 106    pub status_bar: Option<StatusBarSettingsContent>,
 107
 108    pub preview_tabs: Option<PreviewTabsSettingsContent>,
 109
 110    pub agent: Option<AgentSettingsContent>,
 111    pub agent_servers: Option<AllAgentServersSettings>,
 112
 113    /// Configuration of audio in Zed.
 114    pub audio: Option<AudioSettingsContent>,
 115
 116    /// Whether or not to automatically check for updates.
 117    ///
 118    /// Default: true
 119    pub auto_update: Option<bool>,
 120
 121    /// This base keymap settings adjusts the default keybindings in Zed to be similar
 122    /// to other common code editors. By default, Zed's keymap closely follows VSCode's
 123    /// keymap, with minor adjustments, this corresponds to the "VSCode" setting.
 124    ///
 125    /// Default: VSCode
 126    pub base_keymap: Option<BaseKeymapContent>,
 127
 128    /// Configuration for the collab panel visual settings.
 129    pub collaboration_panel: Option<PanelSettingsContent>,
 130
 131    pub debugger: Option<DebuggerSettingsContent>,
 132
 133    /// Configuration for Diagnostics-related features.
 134    pub diagnostics: Option<DiagnosticsSettingsContent>,
 135
 136    /// Configuration for Git-related features
 137    pub git: Option<GitSettings>,
 138
 139    /// Common language server settings.
 140    pub global_lsp_settings: Option<GlobalLspSettingsContent>,
 141
 142    /// The settings for the image viewer.
 143    pub image_viewer: Option<ImageViewerSettingsContent>,
 144
 145    pub repl: Option<ReplSettingsContent>,
 146
 147    /// Whether or not to enable Helix mode.
 148    ///
 149    /// Default: false
 150    pub helix_mode: Option<bool>,
 151
 152    pub journal: Option<JournalSettingsContent>,
 153
 154    /// A map of log scopes to the desired log level.
 155    /// Useful for filtering out noisy logs or enabling more verbose logging.
 156    ///
 157    /// Example: {"log": {"client": "warn"}}
 158    pub log: Option<HashMap<String, String>>,
 159
 160    pub line_indicator_format: Option<LineIndicatorFormat>,
 161
 162    pub language_models: Option<AllLanguageModelSettingsContent>,
 163
 164    pub outline_panel: Option<OutlinePanelSettingsContent>,
 165
 166    pub project_panel: Option<ProjectPanelSettingsContent>,
 167
 168    /// Configuration for the Message Editor
 169    pub message_editor: Option<MessageEditorSettings>,
 170
 171    /// Configuration for Node-related features
 172    pub node: Option<NodeBinarySettings>,
 173
 174    /// Configuration for the Notification Panel
 175    pub notification_panel: Option<NotificationPanelSettingsContent>,
 176
 177    pub proxy: Option<String>,
 178
 179    /// The URL of the Zed server to connect to.
 180    pub server_url: Option<String>,
 181
 182    /// Configuration for session-related features
 183    pub session: Option<SessionSettingsContent>,
 184    /// Control what info is collected by Zed.
 185    pub telemetry: Option<TelemetrySettingsContent>,
 186
 187    /// Configuration of the terminal in Zed.
 188    pub terminal: Option<TerminalSettingsContent>,
 189
 190    pub title_bar: Option<TitleBarSettingsContent>,
 191
 192    /// Whether or not to enable Vim mode.
 193    ///
 194    /// Default: false
 195    pub vim_mode: Option<bool>,
 196
 197    // Settings related to calls in Zed
 198    pub calls: Option<CallSettingsContent>,
 199
 200    /// Settings for the which-key popup.
 201    pub which_key: Option<WhichKeySettingsContent>,
 202
 203    /// Settings related to Vim mode in Zed.
 204    pub vim: Option<VimSettingsContent>,
 205
 206    /// Number of lines to search for modelines at the beginning and end of files.
 207    /// Modelines contain editor directives (e.g., vim/emacs settings) that configure
 208    /// the editor behavior for specific files.
 209    ///
 210    /// Default: 5
 211    pub modeline_lines: Option<usize>,
 212}
 213
 214impl SettingsContent {
 215    pub fn languages_mut(&mut self) -> &mut HashMap<String, LanguageSettingsContent> {
 216        &mut self.project.all_languages.languages.0
 217    }
 218}
 219
 220// These impls are there to optimize builds by avoiding monomorphization downstream. Yes, they're repetitive, but using default impls
 221// break the optimization, for whatever reason.
 222pub trait RootUserSettings: Sized + DeserializeOwned {
 223    fn parse_json(json: &str) -> (Option<Self>, ParseStatus);
 224    fn parse_json_with_comments(json: &str) -> anyhow::Result<Self>;
 225}
 226
 227impl RootUserSettings for SettingsContent {
 228    fn parse_json(json: &str) -> (Option<Self>, ParseStatus) {
 229        fallible_options::parse_json(json)
 230    }
 231    fn parse_json_with_comments(json: &str) -> anyhow::Result<Self> {
 232        parse_json_with_comments(json)
 233    }
 234}
 235// Explicit opt-in instead of blanket impl to avoid monomorphizing downstream. Just a hunch though.
 236impl RootUserSettings for Option<SettingsContent> {
 237    fn parse_json(json: &str) -> (Option<Self>, ParseStatus) {
 238        fallible_options::parse_json(json)
 239    }
 240    fn parse_json_with_comments(json: &str) -> anyhow::Result<Self> {
 241        parse_json_with_comments(json)
 242    }
 243}
 244impl RootUserSettings for UserSettingsContent {
 245    fn parse_json(json: &str) -> (Option<Self>, ParseStatus) {
 246        fallible_options::parse_json(json)
 247    }
 248    fn parse_json_with_comments(json: &str) -> anyhow::Result<Self> {
 249        parse_json_with_comments(json)
 250    }
 251}
 252
 253settings_overrides! {
 254    #[with_fallible_options]
 255    #[derive(Debug, Default, PartialEq, Clone, Serialize, Deserialize, JsonSchema, MergeFrom)]
 256    pub struct ReleaseChannelOverrides { dev, nightly, preview, stable }
 257}
 258
 259settings_overrides! {
 260    #[with_fallible_options]
 261    #[derive(Debug, Default, PartialEq, Clone, Serialize, Deserialize, JsonSchema, MergeFrom)]
 262    pub struct PlatformOverrides { macos, linux, windows }
 263}
 264
 265#[with_fallible_options]
 266#[derive(Debug, Default, PartialEq, Clone, Serialize, Deserialize, JsonSchema, MergeFrom)]
 267pub struct UserSettingsContent {
 268    #[serde(flatten)]
 269    pub content: Box<SettingsContent>,
 270
 271    #[serde(flatten)]
 272    pub release_channel_overrides: ReleaseChannelOverrides,
 273
 274    #[serde(flatten)]
 275    pub platform_overrides: PlatformOverrides,
 276
 277    #[serde(default)]
 278    pub profiles: IndexMap<String, SettingsContent>,
 279}
 280
 281pub struct ExtensionsSettingsContent {
 282    pub all_languages: AllLanguageSettingsContent,
 283}
 284
 285/// Base key bindings scheme. Base keymaps can be overridden with user keymaps.
 286///
 287/// Default: VSCode
 288#[derive(
 289    Copy,
 290    Clone,
 291    Debug,
 292    Serialize,
 293    Deserialize,
 294    JsonSchema,
 295    MergeFrom,
 296    PartialEq,
 297    Eq,
 298    Default,
 299    strum::VariantArray,
 300)]
 301pub enum BaseKeymapContent {
 302    #[default]
 303    VSCode,
 304    JetBrains,
 305    SublimeText,
 306    Atom,
 307    TextMate,
 308    Emacs,
 309    Cursor,
 310    None,
 311}
 312
 313impl strum::VariantNames for BaseKeymapContent {
 314    const VARIANTS: &'static [&'static str] = &[
 315        "VSCode",
 316        "JetBrains",
 317        "Sublime Text",
 318        "Atom",
 319        "TextMate",
 320        "Emacs",
 321        "Cursor",
 322        "None",
 323    ];
 324}
 325
 326#[with_fallible_options]
 327#[derive(Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)]
 328pub struct TitleBarSettingsContent {
 329    /// Whether to show the branch icon beside branch switcher in the title bar.
 330    ///
 331    /// Default: false
 332    pub show_branch_icon: Option<bool>,
 333    /// Whether to show onboarding banners in the title bar.
 334    ///
 335    /// Default: true
 336    pub show_onboarding_banner: Option<bool>,
 337    /// Whether to show user avatar in the title bar.
 338    ///
 339    /// Default: true
 340    pub show_user_picture: Option<bool>,
 341    /// Whether to show the branch name button in the titlebar.
 342    ///
 343    /// Default: true
 344    pub show_branch_name: Option<bool>,
 345    /// Whether to show the project host and name in the titlebar.
 346    ///
 347    /// Default: true
 348    pub show_project_items: Option<bool>,
 349    /// Whether to show the sign in button in the title bar.
 350    ///
 351    /// Default: true
 352    pub show_sign_in: Option<bool>,
 353    /// Whether to show the user menu button in the title bar.
 354    ///
 355    /// Default: true
 356    pub show_user_menu: Option<bool>,
 357    /// Whether to show the menus in the title bar.
 358    ///
 359    /// Default: false
 360    pub show_menus: Option<bool>,
 361}
 362
 363/// Configuration of audio in Zed.
 364#[with_fallible_options]
 365#[derive(Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)]
 366pub struct AudioSettingsContent {
 367    /// Opt into the new audio system.
 368    ///
 369    /// You need to rejoin a call for this setting to apply
 370    #[serde(rename = "experimental.rodio_audio")]
 371    pub rodio_audio: Option<bool>, // default is false
 372    /// Requires 'rodio_audio: true'
 373    ///
 374    /// Automatically increase or decrease you microphone's volume. This affects how
 375    /// loud you sound to others.
 376    ///
 377    /// Recommended: off (default)
 378    /// Microphones are too quite in zed, until everyone is on experimental
 379    /// audio and has auto speaker volume on this will make you very loud
 380    /// compared to other speakers.
 381    #[serde(rename = "experimental.auto_microphone_volume")]
 382    pub auto_microphone_volume: Option<bool>,
 383    /// Requires 'rodio_audio: true'
 384    ///
 385    /// Automatically increate or decrease the volume of other call members.
 386    /// This only affects how things sound for you.
 387    #[serde(rename = "experimental.auto_speaker_volume")]
 388    pub auto_speaker_volume: Option<bool>,
 389    /// Requires 'rodio_audio: true'
 390    ///
 391    /// Remove background noises. Works great for typing, cars, dogs, AC. Does
 392    /// not work well on music.
 393    #[serde(rename = "experimental.denoise")]
 394    pub denoise: Option<bool>,
 395    /// Requires 'rodio_audio: true'
 396    ///
 397    /// Use audio parameters compatible with the previous versions of
 398    /// experimental audio and non-experimental audio. When this is false you
 399    /// will sound strange to anyone not on the latest experimental audio. In
 400    /// the future we will migrate by setting this to false
 401    ///
 402    /// You need to rejoin a call for this setting to apply
 403    #[serde(rename = "experimental.legacy_audio_compatible")]
 404    pub legacy_audio_compatible: Option<bool>,
 405    /// Requires 'rodio_audio: true'
 406    ///
 407    /// Select specific output audio device.
 408    #[serde(rename = "experimental.output_audio_device")]
 409    pub output_audio_device: Option<AudioOutputDeviceName>,
 410    /// Requires 'rodio_audio: true'
 411    ///
 412    /// Select specific input audio device.
 413    #[serde(rename = "experimental.input_audio_device")]
 414    pub input_audio_device: Option<AudioInputDeviceName>,
 415}
 416
 417#[derive(Clone, Default, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq)]
 418#[serde(transparent)]
 419pub struct AudioOutputDeviceName(pub Option<String>);
 420
 421impl AsRef<Option<String>> for AudioInputDeviceName {
 422    fn as_ref(&self) -> &Option<String> {
 423        &self.0
 424    }
 425}
 426
 427impl From<Option<String>> for AudioInputDeviceName {
 428    fn from(value: Option<String>) -> Self {
 429        Self(value)
 430    }
 431}
 432
 433#[derive(Clone, Default, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq)]
 434#[serde(transparent)]
 435pub struct AudioInputDeviceName(pub Option<String>);
 436
 437impl AsRef<Option<String>> for AudioOutputDeviceName {
 438    fn as_ref(&self) -> &Option<String> {
 439        &self.0
 440    }
 441}
 442
 443impl From<Option<String>> for AudioOutputDeviceName {
 444    fn from(value: Option<String>) -> Self {
 445        Self(value)
 446    }
 447}
 448
 449/// Control what info is collected by Zed.
 450#[with_fallible_options]
 451#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, Debug, MergeFrom)]
 452pub struct TelemetrySettingsContent {
 453    /// Send debug info like crash reports.
 454    ///
 455    /// Default: true
 456    pub diagnostics: Option<bool>,
 457    /// Send anonymized usage data like what languages you're using Zed with.
 458    ///
 459    /// Default: true
 460    pub metrics: Option<bool>,
 461}
 462
 463impl Default for TelemetrySettingsContent {
 464    fn default() -> Self {
 465        Self {
 466            diagnostics: Some(true),
 467            metrics: Some(true),
 468        }
 469    }
 470}
 471
 472#[with_fallible_options]
 473#[derive(Default, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema, Clone, MergeFrom)]
 474pub struct DebuggerSettingsContent {
 475    /// Determines the stepping granularity.
 476    ///
 477    /// Default: line
 478    pub stepping_granularity: Option<SteppingGranularity>,
 479    /// Whether the breakpoints should be reused across Zed sessions.
 480    ///
 481    /// Default: true
 482    pub save_breakpoints: Option<bool>,
 483    /// Whether to show the debug button in the status bar.
 484    ///
 485    /// Default: true
 486    pub button: Option<bool>,
 487    /// Time in milliseconds until timeout error when connecting to a TCP debug adapter
 488    ///
 489    /// Default: 2000ms
 490    pub timeout: Option<u64>,
 491    /// Whether to log messages between active debug adapters and Zed
 492    ///
 493    /// Default: true
 494    pub log_dap_communications: Option<bool>,
 495    /// Whether to format dap messages in when adding them to debug adapter logger
 496    ///
 497    /// Default: true
 498    pub format_dap_log_messages: Option<bool>,
 499    /// The dock position of the debug panel
 500    ///
 501    /// Default: Bottom
 502    pub dock: Option<DockPosition>,
 503}
 504
 505/// The granularity of one 'step' in the stepping requests `next`, `stepIn`, `stepOut`, and `stepBack`.
 506#[derive(
 507    PartialEq,
 508    Eq,
 509    Debug,
 510    Hash,
 511    Clone,
 512    Copy,
 513    Deserialize,
 514    Serialize,
 515    JsonSchema,
 516    MergeFrom,
 517    strum::VariantArray,
 518    strum::VariantNames,
 519)]
 520#[serde(rename_all = "snake_case")]
 521pub enum SteppingGranularity {
 522    /// The step should allow the program to run until the current statement has finished executing.
 523    /// The meaning of a statement is determined by the adapter and it may be considered equivalent to a line.
 524    /// For example 'for(int i = 0; i < 10; i++)' could be considered to have 3 statements 'int i = 0', 'i < 10', and 'i++'.
 525    Statement,
 526    /// The step should allow the program to run until the current source line has executed.
 527    Line,
 528    /// The step should allow one instruction to execute (e.g. one x86 instruction).
 529    Instruction,
 530}
 531
 532#[derive(
 533    Copy,
 534    Clone,
 535    Debug,
 536    Serialize,
 537    Deserialize,
 538    JsonSchema,
 539    MergeFrom,
 540    PartialEq,
 541    Eq,
 542    strum::VariantArray,
 543    strum::VariantNames,
 544)]
 545#[serde(rename_all = "snake_case")]
 546pub enum DockPosition {
 547    Left,
 548    Bottom,
 549    Right,
 550}
 551
 552/// Settings for slash commands.
 553#[with_fallible_options]
 554#[derive(Deserialize, Serialize, Debug, Default, Clone, JsonSchema, MergeFrom, PartialEq, Eq)]
 555pub struct SlashCommandSettings {
 556    /// Settings for the `/cargo-workspace` slash command.
 557    pub cargo_workspace: Option<CargoWorkspaceCommandSettings>,
 558}
 559
 560/// Settings for the `/cargo-workspace` slash command.
 561#[with_fallible_options]
 562#[derive(Deserialize, Serialize, Debug, Default, Clone, JsonSchema, MergeFrom, PartialEq, Eq)]
 563pub struct CargoWorkspaceCommandSettings {
 564    /// Whether `/cargo-workspace` is enabled.
 565    pub enabled: Option<bool>,
 566}
 567
 568/// Configuration of voice calls in Zed.
 569#[with_fallible_options]
 570#[derive(Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)]
 571pub struct CallSettingsContent {
 572    /// Whether the microphone should be muted when joining a channel or a call.
 573    ///
 574    /// Default: false
 575    pub mute_on_join: Option<bool>,
 576
 577    /// Whether your current project should be shared when joining an empty channel.
 578    ///
 579    /// Default: false
 580    pub share_on_join: Option<bool>,
 581}
 582
 583#[with_fallible_options]
 584#[derive(Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)]
 585pub struct GitPanelSettingsContent {
 586    /// Whether to show the panel button in the status bar.
 587    ///
 588    /// Default: true
 589    pub button: Option<bool>,
 590    /// Where to dock the panel.
 591    ///
 592    /// Default: left
 593    pub dock: Option<DockPosition>,
 594    /// Default width of the panel in pixels.
 595    ///
 596    /// Default: 360
 597    #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
 598    pub default_width: Option<f32>,
 599    /// How entry statuses are displayed.
 600    ///
 601    /// Default: icon
 602    pub status_style: Option<StatusStyle>,
 603    /// How and when the scrollbar should be displayed.
 604    ///
 605    /// Default: inherits editor scrollbar settings
 606    pub scrollbar: Option<ScrollbarSettings>,
 607
 608    /// What the default branch name should be when
 609    /// `init.defaultBranch` is not set in git
 610    ///
 611    /// Default: main
 612    pub fallback_branch_name: Option<String>,
 613
 614    /// Whether to sort entries in the panel by path
 615    /// or by status (the default).
 616    ///
 617    /// Default: false
 618    pub sort_by_path: Option<bool>,
 619
 620    /// Whether to collapse untracked files in the diff panel.
 621    ///
 622    /// Default: false
 623    pub collapse_untracked_diff: Option<bool>,
 624
 625    /// Whether to show entries with tree or flat view in the panel
 626    ///
 627    /// Default: false
 628    pub tree_view: Option<bool>,
 629
 630    /// Whether to show the addition/deletion change count next to each file in the Git panel.
 631    ///
 632    /// Default: true
 633    pub diff_stats: Option<bool>,
 634}
 635
 636#[derive(
 637    Default,
 638    Copy,
 639    Clone,
 640    Debug,
 641    Serialize,
 642    Deserialize,
 643    JsonSchema,
 644    MergeFrom,
 645    PartialEq,
 646    Eq,
 647    strum::VariantArray,
 648    strum::VariantNames,
 649)]
 650#[serde(rename_all = "snake_case")]
 651pub enum StatusStyle {
 652    #[default]
 653    Icon,
 654    LabelColor,
 655}
 656
 657#[with_fallible_options]
 658#[derive(
 659    Copy, Clone, Default, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq,
 660)]
 661pub struct ScrollbarSettings {
 662    pub show: Option<ShowScrollbar>,
 663}
 664
 665#[with_fallible_options]
 666#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq)]
 667pub struct NotificationPanelSettingsContent {
 668    /// Whether to show the panel button in the status bar.
 669    ///
 670    /// Default: true
 671    pub button: Option<bool>,
 672    /// Where to dock the panel.
 673    ///
 674    /// Default: right
 675    pub dock: Option<DockPosition>,
 676    /// Default width of the panel in pixels.
 677    ///
 678    /// Default: 300
 679    #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
 680    pub default_width: Option<f32>,
 681}
 682
 683#[with_fallible_options]
 684#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq)]
 685pub struct PanelSettingsContent {
 686    /// Whether to show the panel button in the status bar.
 687    ///
 688    /// Default: true
 689    pub button: Option<bool>,
 690    /// Where to dock the panel.
 691    ///
 692    /// Default: left
 693    pub dock: Option<DockPosition>,
 694    /// Default width of the panel in pixels.
 695    ///
 696    /// Default: 240
 697    #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
 698    pub default_width: Option<f32>,
 699}
 700
 701#[with_fallible_options]
 702#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq)]
 703pub struct MessageEditorSettings {
 704    /// Whether to automatically replace emoji shortcodes with emoji characters.
 705    /// For example: typing `:wave:` gets replaced with `👋`.
 706    ///
 707    /// Default: false
 708    pub auto_replace_emoji_shortcode: Option<bool>,
 709}
 710
 711#[with_fallible_options]
 712#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq)]
 713pub struct FileFinderSettingsContent {
 714    /// Whether to show file icons in the file finder.
 715    ///
 716    /// Default: true
 717    pub file_icons: Option<bool>,
 718    /// Determines how much space the file finder can take up in relation to the available window width.
 719    ///
 720    /// Default: small
 721    pub modal_max_width: Option<FileFinderWidthContent>,
 722    /// Determines whether the file finder should skip focus for the active file in search results.
 723    ///
 724    /// Default: true
 725    pub skip_focus_for_active_in_search: Option<bool>,
 726    /// Whether to use gitignored files when searching.
 727    /// Only the file Zed had indexed will be used, not necessary all the gitignored files.
 728    ///
 729    /// Default: Smart
 730    pub include_ignored: Option<IncludeIgnoredContent>,
 731}
 732
 733#[derive(
 734    Debug,
 735    PartialEq,
 736    Eq,
 737    Clone,
 738    Copy,
 739    Default,
 740    Serialize,
 741    Deserialize,
 742    JsonSchema,
 743    MergeFrom,
 744    strum::VariantArray,
 745    strum::VariantNames,
 746)]
 747#[serde(rename_all = "snake_case")]
 748pub enum IncludeIgnoredContent {
 749    /// Use all gitignored files
 750    All,
 751    /// Use only the files Zed had indexed
 752    Indexed,
 753    /// Be smart and search for ignored when called from a gitignored worktree
 754    #[default]
 755    Smart,
 756}
 757
 758#[derive(
 759    Debug,
 760    PartialEq,
 761    Eq,
 762    Clone,
 763    Copy,
 764    Default,
 765    Serialize,
 766    Deserialize,
 767    JsonSchema,
 768    MergeFrom,
 769    strum::VariantArray,
 770    strum::VariantNames,
 771)]
 772#[serde(rename_all = "lowercase")]
 773pub enum FileFinderWidthContent {
 774    #[default]
 775    Small,
 776    Medium,
 777    Large,
 778    XLarge,
 779    Full,
 780}
 781
 782#[with_fallible_options]
 783#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Debug, JsonSchema, MergeFrom)]
 784pub struct VimSettingsContent {
 785    pub default_mode: Option<ModeContent>,
 786    pub toggle_relative_line_numbers: Option<bool>,
 787    pub use_system_clipboard: Option<UseSystemClipboard>,
 788    pub use_smartcase_find: Option<bool>,
 789    /// When enabled, the `:substitute` command replaces all matches in a line
 790    /// by default. The 'g' flag then toggles this behavior.,
 791    pub gdefault: Option<bool>,
 792    pub custom_digraphs: Option<HashMap<String, Arc<str>>>,
 793    pub highlight_on_yank_duration: Option<u64>,
 794    pub cursor_shape: Option<CursorShapeSettings>,
 795}
 796
 797#[derive(
 798    Copy,
 799    Clone,
 800    Default,
 801    Serialize,
 802    Deserialize,
 803    JsonSchema,
 804    MergeFrom,
 805    PartialEq,
 806    Debug,
 807    strum::VariantArray,
 808    strum::VariantNames,
 809)]
 810#[serde(rename_all = "snake_case")]
 811pub enum ModeContent {
 812    #[default]
 813    Normal,
 814    Insert,
 815}
 816
 817/// Controls when to use system clipboard.
 818#[derive(
 819    Copy,
 820    Clone,
 821    Debug,
 822    Serialize,
 823    Deserialize,
 824    PartialEq,
 825    Eq,
 826    JsonSchema,
 827    MergeFrom,
 828    strum::VariantArray,
 829    strum::VariantNames,
 830)]
 831#[serde(rename_all = "snake_case")]
 832pub enum UseSystemClipboard {
 833    /// Don't use system clipboard.
 834    Never,
 835    /// Use system clipboard.
 836    Always,
 837    /// Use system clipboard for yank operations.
 838    OnYank,
 839}
 840
 841/// Cursor shape configuration for insert mode in Vim.
 842#[derive(
 843    Copy,
 844    Clone,
 845    Debug,
 846    Serialize,
 847    Deserialize,
 848    PartialEq,
 849    Eq,
 850    JsonSchema,
 851    MergeFrom,
 852    strum::VariantArray,
 853    strum::VariantNames,
 854)]
 855#[serde(rename_all = "snake_case")]
 856pub enum VimInsertModeCursorShape {
 857    /// Inherit cursor shape from the editor's base cursor_shape setting.
 858    Inherit,
 859    /// Vertical bar cursor.
 860    Bar,
 861    /// Block cursor that surrounds the character.
 862    Block,
 863    /// Underline cursor.
 864    Underline,
 865    /// Hollow box cursor.
 866    Hollow,
 867}
 868
 869/// The settings for cursor shape.
 870#[with_fallible_options]
 871#[derive(
 872    Copy, Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom,
 873)]
 874pub struct CursorShapeSettings {
 875    /// Cursor shape for the normal mode.
 876    ///
 877    /// Default: block
 878    pub normal: Option<CursorShape>,
 879    /// Cursor shape for the replace mode.
 880    ///
 881    /// Default: underline
 882    pub replace: Option<CursorShape>,
 883    /// Cursor shape for the visual mode.
 884    ///
 885    /// Default: block
 886    pub visual: Option<CursorShape>,
 887    /// Cursor shape for the insert mode.
 888    ///
 889    /// The default value follows the primary cursor_shape.
 890    pub insert: Option<VimInsertModeCursorShape>,
 891}
 892
 893/// Settings specific to journaling
 894#[with_fallible_options]
 895#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq)]
 896pub struct JournalSettingsContent {
 897    /// The path of the directory where journal entries are stored.
 898    ///
 899    /// Default: `~`
 900    pub path: Option<String>,
 901    /// What format to display the hours in.
 902    ///
 903    /// Default: hour12
 904    pub hour_format: Option<HourFormat>,
 905}
 906
 907#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq)]
 908#[serde(rename_all = "snake_case")]
 909pub enum HourFormat {
 910    #[default]
 911    Hour12,
 912    Hour24,
 913}
 914
 915#[with_fallible_options]
 916#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq)]
 917pub struct OutlinePanelSettingsContent {
 918    /// Whether to show the outline panel button in the status bar.
 919    ///
 920    /// Default: true
 921    pub button: Option<bool>,
 922    /// Customize default width (in pixels) taken by outline panel
 923    ///
 924    /// Default: 240
 925    #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
 926    pub default_width: Option<f32>,
 927    /// The position of outline panel
 928    ///
 929    /// Default: left
 930    pub dock: Option<DockSide>,
 931    /// Whether to show file icons in the outline panel.
 932    ///
 933    /// Default: true
 934    pub file_icons: Option<bool>,
 935    /// Whether to show folder icons or chevrons for directories in the outline panel.
 936    ///
 937    /// Default: true
 938    pub folder_icons: Option<bool>,
 939    /// Whether to show the git status in the outline panel.
 940    ///
 941    /// Default: true
 942    pub git_status: Option<bool>,
 943    /// Amount of indentation (in pixels) for nested items.
 944    ///
 945    /// Default: 20
 946    #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
 947    pub indent_size: Option<f32>,
 948    /// Whether to reveal it in the outline panel automatically,
 949    /// when a corresponding project entry becomes active.
 950    /// Gitignored entries are never auto revealed.
 951    ///
 952    /// Default: true
 953    pub auto_reveal_entries: Option<bool>,
 954    /// Whether to fold directories automatically
 955    /// when directory has only one directory inside.
 956    ///
 957    /// Default: true
 958    pub auto_fold_dirs: Option<bool>,
 959    /// Settings related to indent guides in the outline panel.
 960    pub indent_guides: Option<IndentGuidesSettingsContent>,
 961    /// Scrollbar-related settings
 962    pub scrollbar: Option<ScrollbarSettingsContent>,
 963    /// Default depth to expand outline items in the current file.
 964    /// The default depth to which outline entries are expanded on reveal.
 965    /// - Set to 0 to collapse all items that have children
 966    /// - Set to 1 or higher to collapse items at that depth or deeper
 967    ///
 968    /// Default: 100
 969    pub expand_outlines_with_depth: Option<usize>,
 970}
 971
 972#[derive(
 973    Clone,
 974    Copy,
 975    Debug,
 976    PartialEq,
 977    Eq,
 978    Serialize,
 979    Deserialize,
 980    JsonSchema,
 981    MergeFrom,
 982    strum::VariantArray,
 983    strum::VariantNames,
 984)]
 985#[serde(rename_all = "snake_case")]
 986pub enum DockSide {
 987    Left,
 988    Right,
 989}
 990
 991#[derive(
 992    Copy,
 993    Clone,
 994    Debug,
 995    PartialEq,
 996    Eq,
 997    Deserialize,
 998    Serialize,
 999    JsonSchema,
1000    MergeFrom,
1001    strum::VariantArray,
1002    strum::VariantNames,
1003)]
1004#[serde(rename_all = "snake_case")]
1005pub enum ShowIndentGuides {
1006    Always,
1007    Never,
1008}
1009
1010#[with_fallible_options]
1011#[derive(
1012    Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq, Default,
1013)]
1014pub struct IndentGuidesSettingsContent {
1015    /// When to show the scrollbar in the outline panel.
1016    pub show: Option<ShowIndentGuides>,
1017}
1018
1019#[derive(Clone, Copy, Default, PartialEq, Debug, JsonSchema, MergeFrom, Deserialize, Serialize)]
1020#[serde(rename_all = "snake_case")]
1021pub enum LineIndicatorFormat {
1022    Short,
1023    #[default]
1024    Long,
1025}
1026
1027/// The settings for the image viewer.
1028#[with_fallible_options]
1029#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, Default, PartialEq)]
1030pub struct ImageViewerSettingsContent {
1031    /// The unit to use for displaying image file sizes.
1032    ///
1033    /// Default: "binary"
1034    pub unit: Option<ImageFileSizeUnit>,
1035}
1036
1037#[with_fallible_options]
1038#[derive(
1039    Clone,
1040    Copy,
1041    Debug,
1042    Serialize,
1043    Deserialize,
1044    JsonSchema,
1045    MergeFrom,
1046    Default,
1047    PartialEq,
1048    strum::VariantArray,
1049    strum::VariantNames,
1050)]
1051#[serde(rename_all = "snake_case")]
1052pub enum ImageFileSizeUnit {
1053    /// Displays file size in binary units (e.g., KiB, MiB).
1054    #[default]
1055    Binary,
1056    /// Displays file size in decimal units (e.g., KB, MB).
1057    Decimal,
1058}
1059
1060#[with_fallible_options]
1061#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq)]
1062pub struct RemoteSettingsContent {
1063    pub ssh_connections: Option<Vec<SshConnection>>,
1064    pub wsl_connections: Option<Vec<WslConnection>>,
1065    pub dev_container_connections: Option<Vec<DevContainerConnection>>,
1066    pub read_ssh_config: Option<bool>,
1067    pub use_podman: Option<bool>,
1068}
1069
1070#[with_fallible_options]
1071#[derive(
1072    Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom, Hash,
1073)]
1074pub struct DevContainerConnection {
1075    pub name: String,
1076    pub remote_user: String,
1077    pub container_id: String,
1078    pub use_podman: bool,
1079}
1080
1081#[with_fallible_options]
1082#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, JsonSchema, MergeFrom)]
1083pub struct SshConnection {
1084    pub host: String,
1085    pub username: Option<String>,
1086    pub port: Option<u16>,
1087    #[serde(default)]
1088    pub args: Vec<String>,
1089    #[serde(default)]
1090    pub projects: collections::BTreeSet<RemoteProject>,
1091    /// Name to use for this server in UI.
1092    pub nickname: Option<String>,
1093    // By default Zed will download the binary to the host directly.
1094    // If this is set to true, Zed will download the binary to your local machine,
1095    // and then upload it over the SSH connection. Useful if your SSH server has
1096    // limited outbound internet access.
1097    pub upload_binary_over_ssh: Option<bool>,
1098
1099    pub port_forwards: Option<Vec<SshPortForwardOption>>,
1100    /// Timeout in seconds for SSH connection and downloading the remote server binary.
1101    /// Defaults to 10 seconds if not specified.
1102    pub connection_timeout: Option<u16>,
1103}
1104
1105#[derive(Clone, Default, Serialize, Deserialize, PartialEq, JsonSchema, MergeFrom, Debug)]
1106pub struct WslConnection {
1107    pub distro_name: String,
1108    pub user: Option<String>,
1109    #[serde(default)]
1110    pub projects: BTreeSet<RemoteProject>,
1111}
1112
1113#[with_fallible_options]
1114#[derive(
1115    Clone, Debug, Default, Serialize, PartialEq, Eq, PartialOrd, Ord, Deserialize, JsonSchema,
1116)]
1117pub struct RemoteProject {
1118    pub paths: Vec<String>,
1119}
1120
1121#[with_fallible_options]
1122#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize, JsonSchema, MergeFrom)]
1123pub struct SshPortForwardOption {
1124    pub local_host: Option<String>,
1125    pub local_port: u16,
1126    pub remote_host: Option<String>,
1127    pub remote_port: u16,
1128}
1129
1130/// Settings for configuring REPL display and behavior.
1131#[with_fallible_options]
1132#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)]
1133pub struct ReplSettingsContent {
1134    /// Maximum number of lines to keep in REPL's scrollback buffer.
1135    /// Clamped with [4, 256] range.
1136    ///
1137    /// Default: 32
1138    pub max_lines: Option<usize>,
1139    /// Maximum number of columns to keep in REPL's scrollback buffer.
1140    /// Clamped with [20, 512] range.
1141    ///
1142    /// Default: 128
1143    pub max_columns: Option<usize>,
1144    /// Whether to show small single-line outputs inline instead of in a block.
1145    ///
1146    /// Default: true
1147    pub inline_output: Option<bool>,
1148    /// Maximum number of characters for an output to be shown inline.
1149    /// Only applies when `inline_output` is true.
1150    ///
1151    /// Default: 50
1152    pub inline_output_max_length: Option<usize>,
1153    /// Maximum number of lines of output to display before scrolling.
1154    /// Set to 0 to disable output height limits.
1155    ///
1156    /// Default: 0
1157    pub output_max_height_lines: Option<usize>,
1158}
1159
1160/// Settings for configuring the which-key popup behaviour.
1161#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)]
1162pub struct WhichKeySettingsContent {
1163    /// Whether to show the which-key popup when holding down key combinations
1164    ///
1165    /// Default: false
1166    pub enabled: Option<bool>,
1167    /// Delay in milliseconds before showing the which-key popup.
1168    ///
1169    /// Default: 700
1170    pub delay_ms: Option<u64>,
1171}
1172
1173#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
1174/// An ExtendingVec in the settings can only accumulate new values.
1175///
1176/// This is useful for things like private files where you only want
1177/// to allow new values to be added.
1178///
1179/// Consider using a HashMap<String, bool> instead of this type
1180/// (like auto_install_extensions) so that user settings files can both add
1181/// and remove values from the set.
1182pub struct ExtendingVec<T>(pub Vec<T>);
1183
1184impl<T> Into<Vec<T>> for ExtendingVec<T> {
1185    fn into(self) -> Vec<T> {
1186        self.0
1187    }
1188}
1189impl<T> From<Vec<T>> for ExtendingVec<T> {
1190    fn from(vec: Vec<T>) -> Self {
1191        ExtendingVec(vec)
1192    }
1193}
1194
1195impl<T: Clone> merge_from::MergeFrom for ExtendingVec<T> {
1196    fn merge_from(&mut self, other: &Self) {
1197        self.0.extend_from_slice(other.0.as_slice());
1198    }
1199}
1200
1201/// A SaturatingBool in the settings can only ever be set to true,
1202/// later attempts to set it to false will be ignored.
1203///
1204/// Used by `disable_ai`.
1205#[derive(Debug, Default, Copy, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
1206pub struct SaturatingBool(pub bool);
1207
1208impl From<bool> for SaturatingBool {
1209    fn from(value: bool) -> Self {
1210        SaturatingBool(value)
1211    }
1212}
1213
1214impl From<SaturatingBool> for bool {
1215    fn from(value: SaturatingBool) -> bool {
1216        value.0
1217    }
1218}
1219
1220impl merge_from::MergeFrom for SaturatingBool {
1221    fn merge_from(&mut self, other: &Self) {
1222        self.0 |= other.0
1223    }
1224}
1225
1226#[derive(
1227    Copy,
1228    Clone,
1229    Default,
1230    Debug,
1231    PartialEq,
1232    Eq,
1233    PartialOrd,
1234    Ord,
1235    Serialize,
1236    Deserialize,
1237    MergeFrom,
1238    JsonSchema,
1239    derive_more::FromStr,
1240)]
1241#[serde(transparent)]
1242pub struct DelayMs(pub u64);
1243
1244impl From<u64> for DelayMs {
1245    fn from(n: u64) -> Self {
1246        Self(n)
1247    }
1248}
1249
1250impl std::fmt::Display for DelayMs {
1251    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1252        write!(f, "{}ms", self.0)
1253    }
1254}