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