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