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    /// When enabled, the `:substitute` command replaces all matches in a line
 705    /// by default. The 'g' flag then toggles this behavior.,
 706    pub gdefault: Option<bool>,
 707    pub custom_digraphs: Option<HashMap<String, Arc<str>>>,
 708    pub highlight_on_yank_duration: Option<u64>,
 709    pub cursor_shape: Option<CursorShapeSettings>,
 710}
 711
 712#[derive(
 713    Copy,
 714    Clone,
 715    Default,
 716    Serialize,
 717    Deserialize,
 718    JsonSchema,
 719    MergeFrom,
 720    PartialEq,
 721    Debug,
 722    strum::VariantArray,
 723    strum::VariantNames,
 724)]
 725#[serde(rename_all = "snake_case")]
 726pub enum ModeContent {
 727    #[default]
 728    Normal,
 729    Insert,
 730}
 731
 732/// Controls when to use system clipboard.
 733#[derive(
 734    Copy,
 735    Clone,
 736    Debug,
 737    Serialize,
 738    Deserialize,
 739    PartialEq,
 740    Eq,
 741    JsonSchema,
 742    MergeFrom,
 743    strum::VariantArray,
 744    strum::VariantNames,
 745)]
 746#[serde(rename_all = "snake_case")]
 747pub enum UseSystemClipboard {
 748    /// Don't use system clipboard.
 749    Never,
 750    /// Use system clipboard.
 751    Always,
 752    /// Use system clipboard for yank operations.
 753    OnYank,
 754}
 755
 756/// Cursor shape configuration for insert mode in Vim.
 757#[derive(
 758    Copy,
 759    Clone,
 760    Debug,
 761    Serialize,
 762    Deserialize,
 763    PartialEq,
 764    Eq,
 765    JsonSchema,
 766    MergeFrom,
 767    strum::VariantArray,
 768    strum::VariantNames,
 769)]
 770#[serde(rename_all = "snake_case")]
 771pub enum VimInsertModeCursorShape {
 772    /// Inherit cursor shape from the editor's base cursor_shape setting.
 773    Inherit,
 774    /// Vertical bar cursor.
 775    Bar,
 776    /// Block cursor that surrounds the character.
 777    Block,
 778    /// Underline cursor.
 779    Underline,
 780    /// Hollow box cursor.
 781    Hollow,
 782}
 783
 784/// The settings for cursor shape.
 785#[with_fallible_options]
 786#[derive(
 787    Copy, Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom,
 788)]
 789pub struct CursorShapeSettings {
 790    /// Cursor shape for the normal mode.
 791    ///
 792    /// Default: block
 793    pub normal: Option<CursorShape>,
 794    /// Cursor shape for the replace mode.
 795    ///
 796    /// Default: underline
 797    pub replace: Option<CursorShape>,
 798    /// Cursor shape for the visual mode.
 799    ///
 800    /// Default: block
 801    pub visual: Option<CursorShape>,
 802    /// Cursor shape for the insert mode.
 803    ///
 804    /// The default value follows the primary cursor_shape.
 805    pub insert: Option<VimInsertModeCursorShape>,
 806}
 807
 808/// Settings specific to journaling
 809#[with_fallible_options]
 810#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq)]
 811pub struct JournalSettingsContent {
 812    /// The path of the directory where journal entries are stored.
 813    ///
 814    /// Default: `~`
 815    pub path: Option<String>,
 816    /// What format to display the hours in.
 817    ///
 818    /// Default: hour12
 819    pub hour_format: Option<HourFormat>,
 820}
 821
 822#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq)]
 823#[serde(rename_all = "snake_case")]
 824pub enum HourFormat {
 825    #[default]
 826    Hour12,
 827    Hour24,
 828}
 829
 830#[with_fallible_options]
 831#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq)]
 832pub struct OutlinePanelSettingsContent {
 833    /// Whether to show the outline panel button in the status bar.
 834    ///
 835    /// Default: true
 836    pub button: Option<bool>,
 837    /// Customize default width (in pixels) taken by outline panel
 838    ///
 839    /// Default: 240
 840    #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
 841    pub default_width: Option<f32>,
 842    /// The position of outline panel
 843    ///
 844    /// Default: left
 845    pub dock: Option<DockSide>,
 846    /// Whether to show file icons in the outline panel.
 847    ///
 848    /// Default: true
 849    pub file_icons: Option<bool>,
 850    /// Whether to show folder icons or chevrons for directories in the outline panel.
 851    ///
 852    /// Default: true
 853    pub folder_icons: Option<bool>,
 854    /// Whether to show the git status in the outline panel.
 855    ///
 856    /// Default: true
 857    pub git_status: Option<bool>,
 858    /// Amount of indentation (in pixels) for nested items.
 859    ///
 860    /// Default: 20
 861    #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
 862    pub indent_size: Option<f32>,
 863    /// Whether to reveal it in the outline panel automatically,
 864    /// when a corresponding project entry becomes active.
 865    /// Gitignored entries are never auto revealed.
 866    ///
 867    /// Default: true
 868    pub auto_reveal_entries: Option<bool>,
 869    /// Whether to fold directories automatically
 870    /// when directory has only one directory inside.
 871    ///
 872    /// Default: true
 873    pub auto_fold_dirs: Option<bool>,
 874    /// Settings related to indent guides in the outline panel.
 875    pub indent_guides: Option<IndentGuidesSettingsContent>,
 876    /// Scrollbar-related settings
 877    pub scrollbar: Option<ScrollbarSettingsContent>,
 878    /// Default depth to expand outline items in the current file.
 879    /// The default depth to which outline entries are expanded on reveal.
 880    /// - Set to 0 to collapse all items that have children
 881    /// - Set to 1 or higher to collapse items at that depth or deeper
 882    ///
 883    /// Default: 100
 884    pub expand_outlines_with_depth: Option<usize>,
 885}
 886
 887#[derive(
 888    Clone,
 889    Copy,
 890    Debug,
 891    PartialEq,
 892    Eq,
 893    Serialize,
 894    Deserialize,
 895    JsonSchema,
 896    MergeFrom,
 897    strum::VariantArray,
 898    strum::VariantNames,
 899)]
 900#[serde(rename_all = "snake_case")]
 901pub enum DockSide {
 902    Left,
 903    Right,
 904}
 905
 906#[derive(
 907    Copy,
 908    Clone,
 909    Debug,
 910    PartialEq,
 911    Eq,
 912    Deserialize,
 913    Serialize,
 914    JsonSchema,
 915    MergeFrom,
 916    strum::VariantArray,
 917    strum::VariantNames,
 918)]
 919#[serde(rename_all = "snake_case")]
 920pub enum ShowIndentGuides {
 921    Always,
 922    Never,
 923}
 924
 925#[with_fallible_options]
 926#[derive(
 927    Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq, Default,
 928)]
 929pub struct IndentGuidesSettingsContent {
 930    /// When to show the scrollbar in the outline panel.
 931    pub show: Option<ShowIndentGuides>,
 932}
 933
 934#[derive(Clone, Copy, Default, PartialEq, Debug, JsonSchema, MergeFrom, Deserialize, Serialize)]
 935#[serde(rename_all = "snake_case")]
 936pub enum LineIndicatorFormat {
 937    Short,
 938    #[default]
 939    Long,
 940}
 941
 942/// The settings for the image viewer.
 943#[with_fallible_options]
 944#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, Default, PartialEq)]
 945pub struct ImageViewerSettingsContent {
 946    /// The unit to use for displaying image file sizes.
 947    ///
 948    /// Default: "binary"
 949    pub unit: Option<ImageFileSizeUnit>,
 950}
 951
 952#[with_fallible_options]
 953#[derive(
 954    Clone,
 955    Copy,
 956    Debug,
 957    Serialize,
 958    Deserialize,
 959    JsonSchema,
 960    MergeFrom,
 961    Default,
 962    PartialEq,
 963    strum::VariantArray,
 964    strum::VariantNames,
 965)]
 966#[serde(rename_all = "snake_case")]
 967pub enum ImageFileSizeUnit {
 968    /// Displays file size in binary units (e.g., KiB, MiB).
 969    #[default]
 970    Binary,
 971    /// Displays file size in decimal units (e.g., KB, MB).
 972    Decimal,
 973}
 974
 975#[with_fallible_options]
 976#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq)]
 977pub struct RemoteSettingsContent {
 978    pub ssh_connections: Option<Vec<SshConnection>>,
 979    pub wsl_connections: Option<Vec<WslConnection>>,
 980    pub dev_container_connections: Option<Vec<DevContainerConnection>>,
 981    pub read_ssh_config: Option<bool>,
 982    pub use_podman: Option<bool>,
 983}
 984
 985#[with_fallible_options]
 986#[derive(
 987    Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom, Hash,
 988)]
 989pub struct DevContainerConnection {
 990    pub name: String,
 991    pub container_id: String,
 992    pub use_podman: bool,
 993}
 994
 995#[with_fallible_options]
 996#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, JsonSchema, MergeFrom)]
 997pub struct SshConnection {
 998    pub host: String,
 999    pub username: Option<String>,
1000    pub port: Option<u16>,
1001    #[serde(default)]
1002    pub args: Vec<String>,
1003    #[serde(default)]
1004    pub projects: collections::BTreeSet<RemoteProject>,
1005    /// Name to use for this server in UI.
1006    pub nickname: Option<String>,
1007    // By default Zed will download the binary to the host directly.
1008    // If this is set to true, Zed will download the binary to your local machine,
1009    // and then upload it over the SSH connection. Useful if your SSH server has
1010    // limited outbound internet access.
1011    pub upload_binary_over_ssh: Option<bool>,
1012
1013    pub port_forwards: Option<Vec<SshPortForwardOption>>,
1014    /// Timeout in seconds for SSH connection and downloading the remote server binary.
1015    /// Defaults to 10 seconds if not specified.
1016    pub connection_timeout: Option<u16>,
1017}
1018
1019#[derive(Clone, Default, Serialize, Deserialize, PartialEq, JsonSchema, MergeFrom, Debug)]
1020pub struct WslConnection {
1021    pub distro_name: String,
1022    pub user: Option<String>,
1023    #[serde(default)]
1024    pub projects: BTreeSet<RemoteProject>,
1025}
1026
1027#[with_fallible_options]
1028#[derive(
1029    Clone, Debug, Default, Serialize, PartialEq, Eq, PartialOrd, Ord, Deserialize, JsonSchema,
1030)]
1031pub struct RemoteProject {
1032    pub paths: Vec<String>,
1033}
1034
1035#[with_fallible_options]
1036#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize, JsonSchema, MergeFrom)]
1037pub struct SshPortForwardOption {
1038    pub local_host: Option<String>,
1039    pub local_port: u16,
1040    pub remote_host: Option<String>,
1041    pub remote_port: u16,
1042}
1043
1044/// Settings for configuring REPL display and behavior.
1045#[with_fallible_options]
1046#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)]
1047pub struct ReplSettingsContent {
1048    /// Maximum number of lines to keep in REPL's scrollback buffer.
1049    /// Clamped with [4, 256] range.
1050    ///
1051    /// Default: 32
1052    pub max_lines: Option<usize>,
1053    /// Maximum number of columns to keep in REPL's scrollback buffer.
1054    /// Clamped with [20, 512] range.
1055    ///
1056    /// Default: 128
1057    pub max_columns: Option<usize>,
1058    /// Whether to show small single-line outputs inline instead of in a block.
1059    ///
1060    /// Default: true
1061    pub inline_output: Option<bool>,
1062    /// Maximum number of characters for an output to be shown inline.
1063    /// Only applies when `inline_output` is true.
1064    ///
1065    /// Default: 50
1066    pub inline_output_max_length: Option<usize>,
1067}
1068
1069/// Settings for configuring the which-key popup behaviour.
1070#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)]
1071pub struct WhichKeySettingsContent {
1072    /// Whether to show the which-key popup when holding down key combinations
1073    ///
1074    /// Default: false
1075    pub enabled: Option<bool>,
1076    /// Delay in milliseconds before showing the which-key popup.
1077    ///
1078    /// Default: 700
1079    pub delay_ms: Option<u64>,
1080}
1081
1082#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
1083/// An ExtendingVec in the settings can only accumulate new values.
1084///
1085/// This is useful for things like private files where you only want
1086/// to allow new values to be added.
1087///
1088/// Consider using a HashMap<String, bool> instead of this type
1089/// (like auto_install_extensions) so that user settings files can both add
1090/// and remove values from the set.
1091pub struct ExtendingVec<T>(pub Vec<T>);
1092
1093impl<T> Into<Vec<T>> for ExtendingVec<T> {
1094    fn into(self) -> Vec<T> {
1095        self.0
1096    }
1097}
1098impl<T> From<Vec<T>> for ExtendingVec<T> {
1099    fn from(vec: Vec<T>) -> Self {
1100        ExtendingVec(vec)
1101    }
1102}
1103
1104impl<T: Clone> merge_from::MergeFrom for ExtendingVec<T> {
1105    fn merge_from(&mut self, other: &Self) {
1106        self.0.extend_from_slice(other.0.as_slice());
1107    }
1108}
1109
1110/// A SaturatingBool in the settings can only ever be set to true,
1111/// later attempts to set it to false will be ignored.
1112///
1113/// Used by `disable_ai`.
1114#[derive(Debug, Default, Copy, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
1115pub struct SaturatingBool(pub bool);
1116
1117impl From<bool> for SaturatingBool {
1118    fn from(value: bool) -> Self {
1119        SaturatingBool(value)
1120    }
1121}
1122
1123impl From<SaturatingBool> for bool {
1124    fn from(value: SaturatingBool) -> bool {
1125        value.0
1126    }
1127}
1128
1129impl merge_from::MergeFrom for SaturatingBool {
1130    fn merge_from(&mut self, other: &Self) {
1131        self.0 |= other.0
1132    }
1133}
1134
1135#[derive(
1136    Copy,
1137    Clone,
1138    Default,
1139    Debug,
1140    PartialEq,
1141    Eq,
1142    PartialOrd,
1143    Ord,
1144    Serialize,
1145    Deserialize,
1146    MergeFrom,
1147    JsonSchema,
1148    derive_more::FromStr,
1149)]
1150#[serde(transparent)]
1151pub struct DelayMs(pub u64);
1152
1153impl From<u64> for DelayMs {
1154    fn from(n: u64) -> Self {
1155        Self(n)
1156    }
1157}
1158
1159impl std::fmt::Display for DelayMs {
1160    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1161        write!(f, "{}ms", self.0)
1162    }
1163}