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