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