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    /// Whether to disable all AI features in Zed.
 201    ///
 202    /// Default: false
 203    pub disable_ai: Option<SaturatingBool>,
 204
 205    /// Settings for the which-key popup.
 206    pub which_key: Option<WhichKeySettingsContent>,
 207
 208    /// Settings related to Vim mode in Zed.
 209    pub vim: Option<VimSettingsContent>,
 210}
 211
 212impl SettingsContent {
 213    pub fn languages_mut(&mut self) -> &mut HashMap<String, LanguageSettingsContent> {
 214        &mut self.project.all_languages.languages.0
 215    }
 216}
 217
 218// These impls are there to optimize builds by avoiding monomorphization downstream. Yes, they're repetitive, but using default impls
 219// break the optimization, for whatever reason.
 220pub trait RootUserSettings: Sized + DeserializeOwned {
 221    fn parse_json(json: &str) -> (Option<Self>, ParseStatus);
 222    fn parse_json_with_comments(json: &str) -> anyhow::Result<Self>;
 223}
 224
 225impl RootUserSettings for SettingsContent {
 226    fn parse_json(json: &str) -> (Option<Self>, ParseStatus) {
 227        fallible_options::parse_json(json)
 228    }
 229    fn parse_json_with_comments(json: &str) -> anyhow::Result<Self> {
 230        parse_json_with_comments(json)
 231    }
 232}
 233// Explicit opt-in instead of blanket impl to avoid monomorphizing downstream. Just a hunch though.
 234impl RootUserSettings for Option<SettingsContent> {
 235    fn parse_json(json: &str) -> (Option<Self>, ParseStatus) {
 236        fallible_options::parse_json(json)
 237    }
 238    fn parse_json_with_comments(json: &str) -> anyhow::Result<Self> {
 239        parse_json_with_comments(json)
 240    }
 241}
 242impl RootUserSettings for UserSettingsContent {
 243    fn parse_json(json: &str) -> (Option<Self>, ParseStatus) {
 244        fallible_options::parse_json(json)
 245    }
 246    fn parse_json_with_comments(json: &str) -> anyhow::Result<Self> {
 247        parse_json_with_comments(json)
 248    }
 249}
 250
 251settings_overrides! {
 252    #[with_fallible_options]
 253    #[derive(Debug, Default, PartialEq, Clone, Serialize, Deserialize, JsonSchema, MergeFrom)]
 254    pub struct ReleaseChannelOverrides { dev, nightly, preview, stable }
 255}
 256
 257settings_overrides! {
 258    #[with_fallible_options]
 259    #[derive(Debug, Default, PartialEq, Clone, Serialize, Deserialize, JsonSchema, MergeFrom)]
 260    pub struct PlatformOverrides { macos, linux, windows }
 261}
 262
 263#[with_fallible_options]
 264#[derive(Debug, Default, PartialEq, Clone, Serialize, Deserialize, JsonSchema, MergeFrom)]
 265pub struct UserSettingsContent {
 266    #[serde(flatten)]
 267    pub content: Box<SettingsContent>,
 268
 269    #[serde(flatten)]
 270    pub release_channel_overrides: ReleaseChannelOverrides,
 271
 272    #[serde(flatten)]
 273    pub platform_overrides: PlatformOverrides,
 274
 275    #[serde(default)]
 276    pub profiles: IndexMap<String, SettingsContent>,
 277}
 278
 279pub struct ExtensionsSettingsContent {
 280    pub all_languages: AllLanguageSettingsContent,
 281}
 282
 283/// Base key bindings scheme. Base keymaps can be overridden with user keymaps.
 284///
 285/// Default: VSCode
 286#[derive(
 287    Copy,
 288    Clone,
 289    Debug,
 290    Serialize,
 291    Deserialize,
 292    JsonSchema,
 293    MergeFrom,
 294    PartialEq,
 295    Eq,
 296    Default,
 297    strum::VariantArray,
 298)]
 299pub enum BaseKeymapContent {
 300    #[default]
 301    VSCode,
 302    JetBrains,
 303    SublimeText,
 304    Atom,
 305    TextMate,
 306    Emacs,
 307    Cursor,
 308    None,
 309}
 310
 311impl strum::VariantNames for BaseKeymapContent {
 312    const VARIANTS: &'static [&'static str] = &[
 313        "VSCode",
 314        "JetBrains",
 315        "Sublime Text",
 316        "Atom",
 317        "TextMate",
 318        "Emacs",
 319        "Cursor",
 320        "None",
 321    ];
 322}
 323
 324#[with_fallible_options]
 325#[derive(Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)]
 326pub struct TitleBarSettingsContent {
 327    /// Whether to show the branch icon beside branch switcher in the title bar.
 328    ///
 329    /// Default: false
 330    pub show_branch_icon: Option<bool>,
 331    /// Whether to show onboarding banners in the title bar.
 332    ///
 333    /// Default: true
 334    pub show_onboarding_banner: Option<bool>,
 335    /// Whether to show user avatar in the title bar.
 336    ///
 337    /// Default: true
 338    pub show_user_picture: Option<bool>,
 339    /// Whether to show the branch name button in the titlebar.
 340    ///
 341    /// Default: true
 342    pub show_branch_name: Option<bool>,
 343    /// Whether to show the project host and name in the titlebar.
 344    ///
 345    /// Default: true
 346    pub show_project_items: Option<bool>,
 347    /// Whether to show the sign in button in the title bar.
 348    ///
 349    /// Default: true
 350    pub show_sign_in: Option<bool>,
 351    /// Whether to show the user menu button in the title bar.
 352    ///
 353    /// Default: true
 354    pub show_user_menu: Option<bool>,
 355    /// Whether to show the menus in the title bar.
 356    ///
 357    /// Default: false
 358    pub show_menus: Option<bool>,
 359}
 360
 361/// Configuration of audio in Zed.
 362#[with_fallible_options]
 363#[derive(Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)]
 364pub struct AudioSettingsContent {
 365    /// Opt into the new audio system.
 366    ///
 367    /// You need to rejoin a call for this setting to apply
 368    #[serde(rename = "experimental.rodio_audio")]
 369    pub rodio_audio: Option<bool>, // default is false
 370    /// Requires 'rodio_audio: true'
 371    ///
 372    /// Automatically increase or decrease you microphone's volume. This affects how
 373    /// loud you sound to others.
 374    ///
 375    /// Recommended: off (default)
 376    /// Microphones are too quite in zed, until everyone is on experimental
 377    /// audio and has auto speaker volume on this will make you very loud
 378    /// compared to other speakers.
 379    #[serde(rename = "experimental.auto_microphone_volume")]
 380    pub auto_microphone_volume: Option<bool>,
 381    /// Requires 'rodio_audio: true'
 382    ///
 383    /// Automatically increate or decrease the volume of other call members.
 384    /// This only affects how things sound for you.
 385    #[serde(rename = "experimental.auto_speaker_volume")]
 386    pub auto_speaker_volume: Option<bool>,
 387    /// Requires 'rodio_audio: true'
 388    ///
 389    /// Remove background noises. Works great for typing, cars, dogs, AC. Does
 390    /// not work well on music.
 391    #[serde(rename = "experimental.denoise")]
 392    pub denoise: Option<bool>,
 393    /// Requires 'rodio_audio: true'
 394    ///
 395    /// Use audio parameters compatible with the previous versions of
 396    /// experimental audio and non-experimental audio. When this is false you
 397    /// will sound strange to anyone not on the latest experimental audio. In
 398    /// the future we will migrate by setting this to false
 399    ///
 400    /// You need to rejoin a call for this setting to apply
 401    #[serde(rename = "experimental.legacy_audio_compatible")]
 402    pub legacy_audio_compatible: Option<bool>,
 403}
 404
 405/// Control what info is collected by Zed.
 406#[with_fallible_options]
 407#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, Debug, MergeFrom)]
 408pub struct TelemetrySettingsContent {
 409    /// Send debug info like crash reports.
 410    ///
 411    /// Default: true
 412    pub diagnostics: Option<bool>,
 413    /// Send anonymized usage data like what languages you're using Zed with.
 414    ///
 415    /// Default: true
 416    pub metrics: Option<bool>,
 417}
 418
 419impl Default for TelemetrySettingsContent {
 420    fn default() -> Self {
 421        Self {
 422            diagnostics: Some(true),
 423            metrics: Some(true),
 424        }
 425    }
 426}
 427
 428#[with_fallible_options]
 429#[derive(Default, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema, Clone, MergeFrom)]
 430pub struct DebuggerSettingsContent {
 431    /// Determines the stepping granularity.
 432    ///
 433    /// Default: line
 434    pub stepping_granularity: Option<SteppingGranularity>,
 435    /// Whether the breakpoints should be reused across Zed sessions.
 436    ///
 437    /// Default: true
 438    pub save_breakpoints: Option<bool>,
 439    /// Whether to show the debug button in the status bar.
 440    ///
 441    /// Default: true
 442    pub button: Option<bool>,
 443    /// Time in milliseconds until timeout error when connecting to a TCP debug adapter
 444    ///
 445    /// Default: 2000ms
 446    pub timeout: Option<u64>,
 447    /// Whether to log messages between active debug adapters and Zed
 448    ///
 449    /// Default: true
 450    pub log_dap_communications: Option<bool>,
 451    /// Whether to format dap messages in when adding them to debug adapter logger
 452    ///
 453    /// Default: true
 454    pub format_dap_log_messages: Option<bool>,
 455    /// The dock position of the debug panel
 456    ///
 457    /// Default: Bottom
 458    pub dock: Option<DockPosition>,
 459}
 460
 461/// The granularity of one 'step' in the stepping requests `next`, `stepIn`, `stepOut`, and `stepBack`.
 462#[derive(
 463    PartialEq,
 464    Eq,
 465    Debug,
 466    Hash,
 467    Clone,
 468    Copy,
 469    Deserialize,
 470    Serialize,
 471    JsonSchema,
 472    MergeFrom,
 473    strum::VariantArray,
 474    strum::VariantNames,
 475)]
 476#[serde(rename_all = "snake_case")]
 477pub enum SteppingGranularity {
 478    /// The step should allow the program to run until the current statement has finished executing.
 479    /// The meaning of a statement is determined by the adapter and it may be considered equivalent to a line.
 480    /// For example 'for(int i = 0; i < 10; i++)' could be considered to have 3 statements 'int i = 0', 'i < 10', and 'i++'.
 481    Statement,
 482    /// The step should allow the program to run until the current source line has executed.
 483    Line,
 484    /// The step should allow one instruction to execute (e.g. one x86 instruction).
 485    Instruction,
 486}
 487
 488#[derive(
 489    Copy,
 490    Clone,
 491    Debug,
 492    Serialize,
 493    Deserialize,
 494    JsonSchema,
 495    MergeFrom,
 496    PartialEq,
 497    Eq,
 498    strum::VariantArray,
 499    strum::VariantNames,
 500)]
 501#[serde(rename_all = "snake_case")]
 502pub enum DockPosition {
 503    Left,
 504    Bottom,
 505    Right,
 506}
 507
 508/// Settings for slash commands.
 509#[with_fallible_options]
 510#[derive(Deserialize, Serialize, Debug, Default, Clone, JsonSchema, MergeFrom, PartialEq, Eq)]
 511pub struct SlashCommandSettings {
 512    /// Settings for the `/cargo-workspace` slash command.
 513    pub cargo_workspace: Option<CargoWorkspaceCommandSettings>,
 514}
 515
 516/// Settings for the `/cargo-workspace` slash command.
 517#[with_fallible_options]
 518#[derive(Deserialize, Serialize, Debug, Default, Clone, JsonSchema, MergeFrom, PartialEq, Eq)]
 519pub struct CargoWorkspaceCommandSettings {
 520    /// Whether `/cargo-workspace` is enabled.
 521    pub enabled: Option<bool>,
 522}
 523
 524/// Configuration of voice calls in Zed.
 525#[with_fallible_options]
 526#[derive(Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)]
 527pub struct CallSettingsContent {
 528    /// Whether the microphone should be muted when joining a channel or a call.
 529    ///
 530    /// Default: false
 531    pub mute_on_join: Option<bool>,
 532
 533    /// Whether your current project should be shared when joining an empty channel.
 534    ///
 535    /// Default: false
 536    pub share_on_join: Option<bool>,
 537}
 538
 539#[with_fallible_options]
 540#[derive(Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)]
 541pub struct GitPanelSettingsContent {
 542    /// Whether to show the panel button in the status bar.
 543    ///
 544    /// Default: true
 545    pub button: Option<bool>,
 546    /// Where to dock the panel.
 547    ///
 548    /// Default: left
 549    pub dock: Option<DockPosition>,
 550    /// Default width of the panel in pixels.
 551    ///
 552    /// Default: 360
 553    #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
 554    pub default_width: Option<f32>,
 555    /// How entry statuses are displayed.
 556    ///
 557    /// Default: icon
 558    pub status_style: Option<StatusStyle>,
 559    /// How and when the scrollbar should be displayed.
 560    ///
 561    /// Default: inherits editor scrollbar settings
 562    pub scrollbar: Option<ScrollbarSettings>,
 563
 564    /// What the default branch name should be when
 565    /// `init.defaultBranch` is not set in git
 566    ///
 567    /// Default: main
 568    pub fallback_branch_name: Option<String>,
 569
 570    /// Whether to sort entries in the panel by path
 571    /// or by status (the default).
 572    ///
 573    /// Default: false
 574    pub sort_by_path: Option<bool>,
 575
 576    /// Whether to collapse untracked files in the diff panel.
 577    ///
 578    /// Default: false
 579    pub collapse_untracked_diff: Option<bool>,
 580
 581    /// Whether to show entries with tree or flat view in the panel
 582    ///
 583    /// Default: false
 584    pub tree_view: Option<bool>,
 585}
 586
 587#[derive(
 588    Default,
 589    Copy,
 590    Clone,
 591    Debug,
 592    Serialize,
 593    Deserialize,
 594    JsonSchema,
 595    MergeFrom,
 596    PartialEq,
 597    Eq,
 598    strum::VariantArray,
 599    strum::VariantNames,
 600)]
 601#[serde(rename_all = "snake_case")]
 602pub enum StatusStyle {
 603    #[default]
 604    Icon,
 605    LabelColor,
 606}
 607
 608#[with_fallible_options]
 609#[derive(
 610    Copy, Clone, Default, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq,
 611)]
 612pub struct ScrollbarSettings {
 613    pub show: Option<ShowScrollbar>,
 614}
 615
 616#[with_fallible_options]
 617#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq)]
 618pub struct NotificationPanelSettingsContent {
 619    /// Whether to show the panel button in the status bar.
 620    ///
 621    /// Default: true
 622    pub button: Option<bool>,
 623    /// Where to dock the panel.
 624    ///
 625    /// Default: right
 626    pub dock: Option<DockPosition>,
 627    /// Default width of the panel in pixels.
 628    ///
 629    /// Default: 300
 630    #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
 631    pub default_width: Option<f32>,
 632}
 633
 634#[with_fallible_options]
 635#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq)]
 636pub struct PanelSettingsContent {
 637    /// Whether to show the panel button in the status bar.
 638    ///
 639    /// Default: true
 640    pub button: Option<bool>,
 641    /// Where to dock the panel.
 642    ///
 643    /// Default: left
 644    pub dock: Option<DockPosition>,
 645    /// Default width of the panel in pixels.
 646    ///
 647    /// Default: 240
 648    #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
 649    pub default_width: Option<f32>,
 650}
 651
 652#[with_fallible_options]
 653#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq)]
 654pub struct MessageEditorSettings {
 655    /// Whether to automatically replace emoji shortcodes with emoji characters.
 656    /// For example: typing `:wave:` gets replaced with `👋`.
 657    ///
 658    /// Default: false
 659    pub auto_replace_emoji_shortcode: Option<bool>,
 660}
 661
 662#[with_fallible_options]
 663#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq)]
 664pub struct FileFinderSettingsContent {
 665    /// Whether to show file icons in the file finder.
 666    ///
 667    /// Default: true
 668    pub file_icons: Option<bool>,
 669    /// Determines how much space the file finder can take up in relation to the available window width.
 670    ///
 671    /// Default: small
 672    pub modal_max_width: Option<FileFinderWidthContent>,
 673    /// Determines whether the file finder should skip focus for the active file in search results.
 674    ///
 675    /// Default: true
 676    pub skip_focus_for_active_in_search: Option<bool>,
 677    /// Determines whether to show the git status in the file finder
 678    ///
 679    /// Default: true
 680    pub git_status: Option<bool>,
 681    /// Whether to use gitignored files when searching.
 682    /// Only the file Zed had indexed will be used, not necessary all the gitignored files.
 683    ///
 684    /// Default: Smart
 685    pub include_ignored: Option<IncludeIgnoredContent>,
 686}
 687
 688#[derive(
 689    Debug,
 690    PartialEq,
 691    Eq,
 692    Clone,
 693    Copy,
 694    Default,
 695    Serialize,
 696    Deserialize,
 697    JsonSchema,
 698    MergeFrom,
 699    strum::VariantArray,
 700    strum::VariantNames,
 701)]
 702#[serde(rename_all = "snake_case")]
 703pub enum IncludeIgnoredContent {
 704    /// Use all gitignored files
 705    All,
 706    /// Use only the files Zed had indexed
 707    Indexed,
 708    /// Be smart and search for ignored when called from a gitignored worktree
 709    #[default]
 710    Smart,
 711}
 712
 713#[derive(
 714    Debug,
 715    PartialEq,
 716    Eq,
 717    Clone,
 718    Copy,
 719    Default,
 720    Serialize,
 721    Deserialize,
 722    JsonSchema,
 723    MergeFrom,
 724    strum::VariantArray,
 725    strum::VariantNames,
 726)]
 727#[serde(rename_all = "lowercase")]
 728pub enum FileFinderWidthContent {
 729    #[default]
 730    Small,
 731    Medium,
 732    Large,
 733    XLarge,
 734    Full,
 735}
 736
 737#[with_fallible_options]
 738#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Debug, JsonSchema, MergeFrom)]
 739pub struct VimSettingsContent {
 740    pub default_mode: Option<ModeContent>,
 741    pub toggle_relative_line_numbers: Option<bool>,
 742    pub use_system_clipboard: Option<UseSystemClipboard>,
 743    pub use_smartcase_find: 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}
1035
1036#[with_fallible_options]
1037#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, JsonSchema, MergeFrom)]
1038pub struct SshConnection {
1039    pub host: String,
1040    pub username: Option<String>,
1041    pub port: Option<u16>,
1042    #[serde(default)]
1043    pub args: Vec<String>,
1044    #[serde(default)]
1045    pub projects: collections::BTreeSet<RemoteProject>,
1046    /// Name to use for this server in UI.
1047    pub nickname: Option<String>,
1048    // By default Zed will download the binary to the host directly.
1049    // If this is set to true, Zed will download the binary to your local machine,
1050    // and then upload it over the SSH connection. Useful if your SSH server has
1051    // limited outbound internet access.
1052    pub upload_binary_over_ssh: Option<bool>,
1053
1054    pub port_forwards: Option<Vec<SshPortForwardOption>>,
1055    /// Timeout in seconds for SSH connection and downloading the remote server binary.
1056    /// Defaults to 10 seconds if not specified.
1057    pub connection_timeout: Option<u16>,
1058}
1059
1060#[derive(Clone, Default, Serialize, Deserialize, PartialEq, JsonSchema, MergeFrom, Debug)]
1061pub struct WslConnection {
1062    pub distro_name: String,
1063    pub user: Option<String>,
1064    #[serde(default)]
1065    pub projects: BTreeSet<RemoteProject>,
1066}
1067
1068#[with_fallible_options]
1069#[derive(
1070    Clone, Debug, Default, Serialize, PartialEq, Eq, PartialOrd, Ord, Deserialize, JsonSchema,
1071)]
1072pub struct RemoteProject {
1073    pub paths: Vec<String>,
1074}
1075
1076#[with_fallible_options]
1077#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize, JsonSchema, MergeFrom)]
1078pub struct SshPortForwardOption {
1079    pub local_host: Option<String>,
1080    pub local_port: u16,
1081    pub remote_host: Option<String>,
1082    pub remote_port: u16,
1083}
1084
1085/// Settings for configuring REPL display and behavior.
1086#[with_fallible_options]
1087#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)]
1088pub struct ReplSettingsContent {
1089    /// Maximum number of lines to keep in REPL's scrollback buffer.
1090    /// Clamped with [4, 256] range.
1091    ///
1092    /// Default: 32
1093    pub max_lines: Option<usize>,
1094    /// Maximum number of columns to keep in REPL's scrollback buffer.
1095    /// Clamped with [20, 512] range.
1096    ///
1097    /// Default: 128
1098    pub max_columns: Option<usize>,
1099    /// Whether to show small single-line outputs inline instead of in a block.
1100    ///
1101    /// Default: true
1102    pub inline_output: Option<bool>,
1103    /// Maximum number of characters for an output to be shown inline.
1104    /// Only applies when `inline_output` is true.
1105    ///
1106    /// Default: 50
1107    pub inline_output_max_length: Option<usize>,
1108    /// Maximum number of lines of output to display before scrolling.
1109    /// Set to 0 to disable output height limits.
1110    ///
1111    /// Default: 0
1112    pub output_max_height_lines: Option<usize>,
1113    /// Maximum number of columns of output to display before scaling images.
1114    /// Set to 0 to disable output width limits.
1115    ///
1116    /// Default: 0
1117    pub output_max_width_columns: Option<usize>,
1118}
1119
1120/// Settings for configuring the which-key popup behaviour.
1121#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)]
1122pub struct WhichKeySettingsContent {
1123    /// Whether to show the which-key popup when holding down key combinations
1124    ///
1125    /// Default: false
1126    pub enabled: Option<bool>,
1127    /// Delay in milliseconds before showing the which-key popup.
1128    ///
1129    /// Default: 700
1130    pub delay_ms: Option<u64>,
1131}
1132
1133#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
1134/// An ExtendingVec in the settings can only accumulate new values.
1135///
1136/// This is useful for things like private files where you only want
1137/// to allow new values to be added.
1138///
1139/// Consider using a HashMap<String, bool> instead of this type
1140/// (like auto_install_extensions) so that user settings files can both add
1141/// and remove values from the set.
1142pub struct ExtendingVec<T>(pub Vec<T>);
1143
1144impl<T> Into<Vec<T>> for ExtendingVec<T> {
1145    fn into(self) -> Vec<T> {
1146        self.0
1147    }
1148}
1149impl<T> From<Vec<T>> for ExtendingVec<T> {
1150    fn from(vec: Vec<T>) -> Self {
1151        ExtendingVec(vec)
1152    }
1153}
1154
1155impl<T: Clone> merge_from::MergeFrom for ExtendingVec<T> {
1156    fn merge_from(&mut self, other: &Self) {
1157        self.0.extend_from_slice(other.0.as_slice());
1158    }
1159}
1160
1161/// A SaturatingBool in the settings can only ever be set to true,
1162/// later attempts to set it to false will be ignored.
1163///
1164/// Used by `disable_ai`.
1165#[derive(Debug, Default, Copy, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
1166pub struct SaturatingBool(pub bool);
1167
1168impl From<bool> for SaturatingBool {
1169    fn from(value: bool) -> Self {
1170        SaturatingBool(value)
1171    }
1172}
1173
1174impl From<SaturatingBool> for bool {
1175    fn from(value: SaturatingBool) -> bool {
1176        value.0
1177    }
1178}
1179
1180impl merge_from::MergeFrom for SaturatingBool {
1181    fn merge_from(&mut self, other: &Self) {
1182        self.0 |= other.0
1183    }
1184}
1185
1186#[derive(
1187    Copy,
1188    Clone,
1189    Default,
1190    Debug,
1191    PartialEq,
1192    Eq,
1193    PartialOrd,
1194    Ord,
1195    Serialize,
1196    Deserialize,
1197    MergeFrom,
1198    JsonSchema,
1199    derive_more::FromStr,
1200)]
1201#[serde(transparent)]
1202pub struct DelayMs(pub u64);
1203
1204impl From<u64> for DelayMs {
1205    fn from(n: u64) -> Self {
1206        Self(n)
1207    }
1208}
1209
1210impl std::fmt::Display for DelayMs {
1211    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1212        write!(f, "{}ms", self.0)
1213    }
1214}