settings_content.rs

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