settings_content.rs

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