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