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