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