workspace.rs

   1use std::num::NonZeroUsize;
   2
   3use collections::HashMap;
   4use schemars::JsonSchema;
   5use serde::{Deserialize, Serialize};
   6use settings_macros::{MergeFrom, with_fallible_options};
   7
   8use crate::{
   9    CenteredPaddingSettings, DelayMs, DockPosition, DockSide, InactiveOpacity, ShowIndentGuides,
  10    ShowScrollbar, serialize_optional_f32_with_two_decimal_places,
  11};
  12
  13#[with_fallible_options]
  14#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
  15pub struct WorkspaceSettingsContent {
  16    /// Active pane styling settings.
  17    pub active_pane_modifiers: Option<ActivePaneModifiers>,
  18    /// The text rendering mode to use.
  19    ///
  20    /// Default: platform_default
  21    pub text_rendering_mode: Option<TextRenderingMode>,
  22    /// Layout mode for the bottom dock
  23    ///
  24    /// Default: contained
  25    pub bottom_dock_layout: Option<BottomDockLayout>,
  26    /// Direction to split horizontally.
  27    ///
  28    /// Default: "up"
  29    pub pane_split_direction_horizontal: Option<PaneSplitDirectionHorizontal>,
  30    /// Direction to split vertically.
  31    ///
  32    /// Default: "left"
  33    pub pane_split_direction_vertical: Option<PaneSplitDirectionVertical>,
  34    /// Centered layout related settings.
  35    pub centered_layout: Option<CenteredLayoutSettings>,
  36    /// Whether or not to prompt the user to confirm before closing the application.
  37    ///
  38    /// Default: false
  39    pub confirm_quit: Option<bool>,
  40    /// Whether or not to show the call status icon in the status bar.
  41    ///
  42    /// Default: true
  43    pub show_call_status_icon: Option<bool>,
  44    /// When to automatically save edited buffers.
  45    ///
  46    /// Default: off
  47    pub autosave: Option<AutosaveSetting>,
  48    /// Controls previous session restoration in freshly launched Zed instance.
  49    /// Values: empty_tab, last_workspace, last_session, launchpad
  50    /// Default: last_session
  51    pub restore_on_startup: Option<RestoreOnStartupBehavior>,
  52    /// The default behavior when opening paths from the CLI without
  53    /// an explicit `-e` or `-n` flag.
  54    ///
  55    /// Default: existing_window
  56    pub cli_default_open_behavior: Option<CliDefaultOpenBehavior>,
  57    /// Whether to attempt to restore previous file's state when opening it again.
  58    /// The state is stored per pane.
  59    /// When disabled, defaults are applied instead of the state restoration.
  60    ///
  61    /// E.g. for editors, selections, folds and scroll positions are restored, if the same file is closed and, later, opened again in the same pane.
  62    /// When disabled, a single selection in the very beginning of the file, zero scroll position and no folds state is used as a default.
  63    ///
  64    /// Default: true
  65    pub restore_on_file_reopen: Option<bool>,
  66    /// The size of the workspace split drop targets on the outer edges.
  67    /// Given as a fraction that will be multiplied by the smaller dimension of the workspace.
  68    ///
  69    /// Default: `0.2` (20% of the smaller dimension of the workspace)
  70    #[serde(serialize_with = "serialize_optional_f32_with_two_decimal_places")]
  71    pub drop_target_size: Option<f32>,
  72    /// Whether to close the window when using 'close active item' on a workspace with no tabs
  73    ///
  74    /// Default: auto ("on" on macOS, "off" otherwise)
  75    pub when_closing_with_no_tabs: Option<CloseWindowWhenNoItems>,
  76    /// Whether to use the system provided dialogs for Open and Save As.
  77    /// When set to false, Zed will use the built-in keyboard-first pickers.
  78    ///
  79    /// Default: true
  80    pub use_system_path_prompts: Option<bool>,
  81    /// Whether to use the system provided prompts.
  82    /// When set to false, Zed will use the built-in prompts.
  83    /// Note that this setting has no effect on Linux, where Zed will always
  84    /// use the built-in prompts.
  85    ///
  86    /// Default: true
  87    pub use_system_prompts: Option<bool>,
  88    /// Aliases for the command palette. When you type a key in this map,
  89    /// it will be assumed to equal the value.
  90    ///
  91    /// Default: true
  92    #[serde(default)]
  93    pub command_aliases: HashMap<String, String>,
  94    /// Maximum open tabs in a pane. Will not close an unsaved
  95    /// tab. Set to `None` for unlimited tabs.
  96    ///
  97    /// Default: none
  98    pub max_tabs: Option<NonZeroUsize>,
  99    /// What to do when the last window is closed
 100    ///
 101    /// Default: auto (nothing on macOS, "app quit" otherwise)
 102    pub on_last_window_closed: Option<OnLastWindowClosed>,
 103    /// Whether to resize all the panels in a dock when resizing the dock.
 104    ///
 105    /// Default: ["left"]
 106    pub resize_all_panels_in_dock: Option<Vec<DockPosition>>,
 107    /// Whether to automatically close files that have been deleted on disk.
 108    ///
 109    /// Default: false
 110    pub close_on_file_delete: Option<bool>,
 111    /// Whether to allow windows to tab together based on the user’s tabbing preference (macOS only).
 112    ///
 113    /// Default: false
 114    pub use_system_window_tabs: Option<bool>,
 115    /// Whether to show padding for zoomed panels.
 116    /// When enabled, zoomed bottom panels will have some top padding,
 117    /// while zoomed left/right panels will have padding to the right/left (respectively).
 118    ///
 119    /// Default: true
 120    pub zoomed_padding: Option<bool>,
 121    /// Whether toggling a panel (e.g. with its keyboard shortcut) also closes
 122    /// the panel when it is already focused, instead of just moving focus back
 123    /// to the editor.
 124    ///
 125    /// Default: false
 126    pub close_panel_on_toggle: Option<bool>,
 127    /// What draws window decorations/titlebar, the client application (Zed) or display server
 128    /// Default: client
 129    pub window_decorations: Option<WindowDecorations>,
 130    /// Whether the focused panel follows the mouse location
 131    /// Default: false
 132    pub focus_follows_mouse: Option<FocusFollowsMouse>,
 133}
 134
 135#[with_fallible_options]
 136#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)]
 137pub struct ItemSettingsContent {
 138    /// Whether to show the Git file status on a tab item.
 139    ///
 140    /// Default: false
 141    pub git_status: Option<bool>,
 142    /// Position of the close button in a tab.
 143    ///
 144    /// Default: right
 145    pub close_position: Option<ClosePosition>,
 146    /// Whether to show the file icon for a tab.
 147    ///
 148    /// Default: false
 149    pub file_icons: Option<bool>,
 150    /// What to do after closing the current tab.
 151    ///
 152    /// Default: history
 153    pub activate_on_close: Option<ActivateOnClose>,
 154    /// Which files containing diagnostic errors/warnings to mark in the tabs.
 155    /// This setting can take the following three values:
 156    ///
 157    /// Default: off
 158    pub show_diagnostics: Option<ShowDiagnostics>,
 159    /// Whether to always show the close button on tabs.
 160    ///
 161    /// Default: false
 162    pub show_close_button: Option<ShowCloseButton>,
 163}
 164
 165#[with_fallible_options]
 166#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)]
 167pub struct PreviewTabsSettingsContent {
 168    /// Whether to show opened editors as preview tabs.
 169    /// Preview tabs do not stay open, are reused until explicitly set to be kept open opened (via double-click or editing) and show file names in italic.
 170    ///
 171    /// Default: true
 172    pub enabled: Option<bool>,
 173    /// Whether to open tabs in preview mode when opened from the project panel with a single click.
 174    ///
 175    /// Default: true
 176    pub enable_preview_from_project_panel: Option<bool>,
 177    /// Whether to open tabs in preview mode when selected from the file finder.
 178    ///
 179    /// Default: false
 180    pub enable_preview_from_file_finder: Option<bool>,
 181    /// Whether to open tabs in preview mode when opened from a multibuffer.
 182    ///
 183    /// Default: true
 184    pub enable_preview_from_multibuffer: Option<bool>,
 185    /// Whether to open tabs in preview mode when code navigation is used to open a multibuffer.
 186    ///
 187    /// Default: false
 188    pub enable_preview_multibuffer_from_code_navigation: Option<bool>,
 189    /// Whether to open tabs in preview mode when code navigation is used to open a single file.
 190    ///
 191    /// Default: true
 192    pub enable_preview_file_from_code_navigation: Option<bool>,
 193    /// Whether to keep tabs in preview mode when code navigation is used to navigate away from them.
 194    /// If `enable_preview_file_from_code_navigation` or `enable_preview_multibuffer_from_code_navigation` is also true, the new tab may replace the existing one.
 195    ///
 196    /// Default: false
 197    pub enable_keep_preview_on_code_navigation: Option<bool>,
 198}
 199
 200#[derive(
 201    Copy,
 202    Clone,
 203    Debug,
 204    PartialEq,
 205    Default,
 206    Serialize,
 207    Deserialize,
 208    JsonSchema,
 209    MergeFrom,
 210    strum::VariantArray,
 211    strum::VariantNames,
 212)]
 213#[serde(rename_all = "lowercase")]
 214pub enum ClosePosition {
 215    Left,
 216    #[default]
 217    Right,
 218}
 219
 220#[derive(
 221    Copy,
 222    Clone,
 223    Debug,
 224    PartialEq,
 225    Default,
 226    Serialize,
 227    Deserialize,
 228    JsonSchema,
 229    MergeFrom,
 230    strum::VariantArray,
 231    strum::VariantNames,
 232)]
 233#[serde(rename_all = "lowercase")]
 234pub enum ShowCloseButton {
 235    Always,
 236    #[default]
 237    Hover,
 238    Hidden,
 239}
 240
 241#[derive(
 242    Copy,
 243    Clone,
 244    Debug,
 245    Default,
 246    Serialize,
 247    Deserialize,
 248    JsonSchema,
 249    MergeFrom,
 250    PartialEq,
 251    Eq,
 252    strum::VariantArray,
 253    strum::VariantNames,
 254)]
 255#[serde(rename_all = "snake_case")]
 256pub enum ShowDiagnostics {
 257    #[default]
 258    Off,
 259    Errors,
 260    All,
 261}
 262
 263#[derive(
 264    Copy,
 265    Clone,
 266    Debug,
 267    PartialEq,
 268    Default,
 269    Serialize,
 270    Deserialize,
 271    JsonSchema,
 272    MergeFrom,
 273    strum::VariantArray,
 274    strum::VariantNames,
 275)]
 276#[serde(rename_all = "snake_case")]
 277pub enum ActivateOnClose {
 278    #[default]
 279    History,
 280    Neighbour,
 281    LeftNeighbour,
 282}
 283
 284#[with_fallible_options]
 285#[derive(Copy, Clone, PartialEq, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
 286#[serde(rename_all = "snake_case")]
 287pub struct ActivePaneModifiers {
 288    /// Size of the border surrounding the active pane.
 289    /// When set to 0, the active pane doesn't have any border.
 290    /// The border is drawn inset.
 291    ///
 292    /// Default: `0.0`
 293    #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
 294    pub border_size: Option<f32>,
 295    /// Opacity of inactive panels.
 296    /// When set to 1.0, the inactive panes have the same opacity as the active one.
 297    /// If set to 0, the inactive panes content will not be visible at all.
 298    /// Values are clamped to the [0.0, 1.0] range.
 299    ///
 300    /// Default: `1.0`
 301    #[schemars(range(min = 0.0, max = 1.0))]
 302    pub inactive_opacity: Option<InactiveOpacity>,
 303}
 304
 305#[derive(
 306    Copy,
 307    Clone,
 308    Debug,
 309    Default,
 310    Serialize,
 311    Deserialize,
 312    PartialEq,
 313    JsonSchema,
 314    MergeFrom,
 315    strum::VariantArray,
 316    strum::VariantNames,
 317)]
 318#[serde(rename_all = "snake_case")]
 319pub enum BottomDockLayout {
 320    /// Contained between the left and right docks
 321    #[default]
 322    Contained,
 323    /// Takes up the full width of the window
 324    Full,
 325    /// Extends under the left dock while snapping to the right dock
 326    LeftAligned,
 327    /// Extends under the right dock while snapping to the left dock
 328    RightAligned,
 329}
 330
 331#[derive(
 332    Copy,
 333    Clone,
 334    Default,
 335    Debug,
 336    Serialize,
 337    Deserialize,
 338    PartialEq,
 339    JsonSchema,
 340    MergeFrom,
 341    strum::VariantArray,
 342    strum::VariantNames,
 343)]
 344#[serde(rename_all = "snake_case")]
 345pub enum WindowDecorations {
 346    /// Zed draws its own window decorations/titlebar (client-side decoration)
 347    #[default]
 348    Client,
 349    /// Show system's window titlebar (server-side decoration; not supported by GNOME Wayland)
 350    Server,
 351}
 352
 353#[derive(
 354    Copy,
 355    Clone,
 356    PartialEq,
 357    Default,
 358    Serialize,
 359    Deserialize,
 360    JsonSchema,
 361    MergeFrom,
 362    Debug,
 363    strum::VariantArray,
 364    strum::VariantNames,
 365)]
 366#[serde(rename_all = "snake_case")]
 367pub enum CloseWindowWhenNoItems {
 368    /// Match platform conventions by default, so "on" on macOS and "off" everywhere else
 369    #[default]
 370    PlatformDefault,
 371    /// Close the window when there are no tabs
 372    CloseWindow,
 373    /// Leave the window open when there are no tabs
 374    KeepWindowOpen,
 375}
 376
 377impl CloseWindowWhenNoItems {
 378    pub fn should_close(&self) -> bool {
 379        match self {
 380            CloseWindowWhenNoItems::PlatformDefault => cfg!(target_os = "macos"),
 381            CloseWindowWhenNoItems::CloseWindow => true,
 382            CloseWindowWhenNoItems::KeepWindowOpen => false,
 383        }
 384    }
 385}
 386
 387#[derive(
 388    Copy,
 389    Clone,
 390    PartialEq,
 391    Eq,
 392    Default,
 393    Serialize,
 394    Deserialize,
 395    JsonSchema,
 396    MergeFrom,
 397    Debug,
 398    strum::VariantArray,
 399    strum::VariantNames,
 400)]
 401#[serde(rename_all = "snake_case")]
 402pub enum CliDefaultOpenBehavior {
 403    /// Add to the existing Zed window as a new workspace.
 404    #[default]
 405    #[strum(serialize = "Add to Existing Window")]
 406    ExistingWindow,
 407    /// Open a new Zed window.
 408    #[strum(serialize = "Open a New Window")]
 409    NewWindow,
 410}
 411
 412#[derive(
 413    Copy,
 414    Clone,
 415    PartialEq,
 416    Eq,
 417    Default,
 418    Serialize,
 419    Deserialize,
 420    JsonSchema,
 421    MergeFrom,
 422    Debug,
 423    strum::VariantArray,
 424    strum::VariantNames,
 425)]
 426#[serde(rename_all = "snake_case")]
 427pub enum RestoreOnStartupBehavior {
 428    /// Always start with an empty editor tab
 429    #[serde(alias = "none")]
 430    EmptyTab,
 431    /// Restore the workspace that was closed last.
 432    LastWorkspace,
 433    /// Restore all workspaces that were open when quitting Zed.
 434    #[default]
 435    LastSession,
 436    /// Show the launchpad with recent projects (no tabs).
 437    Launchpad,
 438}
 439
 440#[with_fallible_options]
 441#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq)]
 442pub struct TabBarSettingsContent {
 443    /// Whether or not to show the tab bar in the editor.
 444    ///
 445    /// Default: true
 446    pub show: Option<bool>,
 447    /// Whether or not to show the navigation history buttons in the tab bar.
 448    ///
 449    /// Default: true
 450    pub show_nav_history_buttons: Option<bool>,
 451    /// Whether or not to show the tab bar buttons.
 452    ///
 453    /// Default: true
 454    pub show_tab_bar_buttons: Option<bool>,
 455    /// Whether or not to show pinned tabs in a separate row.
 456    /// When enabled, pinned tabs appear in a top row and unpinned tabs in a bottom row.
 457    ///
 458    /// Default: false
 459    pub show_pinned_tabs_in_separate_row: Option<bool>,
 460}
 461
 462#[with_fallible_options]
 463#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq, Eq)]
 464pub struct StatusBarSettingsContent {
 465    /// Whether to show the status bar.
 466    ///
 467    /// Default: true
 468    #[serde(rename = "experimental.show")]
 469    pub show: Option<bool>,
 470    /// Whether to show the name of the active file in the status bar.
 471    ///
 472    /// Default: false
 473    pub show_active_file: Option<bool>,
 474    /// Whether to display the active language button in the status bar.
 475    ///
 476    /// Default: true
 477    pub active_language_button: Option<bool>,
 478    /// Whether to show the cursor position button in the status bar.
 479    ///
 480    /// Default: true
 481    pub cursor_position_button: Option<bool>,
 482    /// Whether to show active line endings button in the status bar.
 483    ///
 484    /// Default: false
 485    pub line_endings_button: Option<bool>,
 486    /// Whether to show the active encoding button in the status bar.
 487    ///
 488    /// Default: non_utf8
 489    pub active_encoding_button: Option<EncodingDisplayOptions>,
 490}
 491
 492#[derive(
 493    Copy,
 494    Clone,
 495    Debug,
 496    Eq,
 497    PartialEq,
 498    Default,
 499    Serialize,
 500    Deserialize,
 501    JsonSchema,
 502    MergeFrom,
 503    strum::VariantNames,
 504    strum::VariantArray,
 505)]
 506#[serde(rename_all = "snake_case")]
 507pub enum EncodingDisplayOptions {
 508    Enabled,
 509    Disabled,
 510    #[default]
 511    NonUtf8,
 512}
 513impl EncodingDisplayOptions {
 514    pub fn should_show(&self, is_utf8: bool, has_bom: bool) -> bool {
 515        match self {
 516            Self::Disabled => false,
 517            Self::Enabled => true,
 518            Self::NonUtf8 => {
 519                let is_standard_utf8 = is_utf8 && !has_bom;
 520                !is_standard_utf8
 521            }
 522        }
 523    }
 524}
 525
 526#[derive(
 527    Copy,
 528    Clone,
 529    Debug,
 530    Serialize,
 531    Deserialize,
 532    PartialEq,
 533    Eq,
 534    JsonSchema,
 535    MergeFrom,
 536    strum::EnumDiscriminants,
 537)]
 538#[strum_discriminants(derive(strum::VariantArray, strum::VariantNames, strum::FromRepr))]
 539#[serde(rename_all = "snake_case")]
 540pub enum AutosaveSetting {
 541    /// Disable autosave.
 542    Off,
 543    /// Save after inactivity period of `milliseconds`.
 544    AfterDelay { milliseconds: DelayMs },
 545    /// Autosave when focus changes.
 546    OnFocusChange,
 547    /// Autosave when the active window changes.
 548    OnWindowChange,
 549}
 550
 551impl AutosaveSetting {
 552    pub fn should_save_on_close(&self) -> bool {
 553        matches!(
 554            &self,
 555            AutosaveSetting::OnFocusChange
 556                | AutosaveSetting::OnWindowChange
 557                | AutosaveSetting::AfterDelay { .. }
 558        )
 559    }
 560}
 561
 562#[derive(
 563    Copy,
 564    Clone,
 565    Debug,
 566    Serialize,
 567    Deserialize,
 568    PartialEq,
 569    Eq,
 570    JsonSchema,
 571    MergeFrom,
 572    strum::VariantArray,
 573    strum::VariantNames,
 574)]
 575#[serde(rename_all = "snake_case")]
 576pub enum PaneSplitDirectionHorizontal {
 577    Up,
 578    Down,
 579}
 580
 581#[derive(
 582    Copy,
 583    Clone,
 584    Debug,
 585    Serialize,
 586    Deserialize,
 587    PartialEq,
 588    Eq,
 589    JsonSchema,
 590    MergeFrom,
 591    strum::VariantArray,
 592    strum::VariantNames,
 593)]
 594#[serde(rename_all = "snake_case")]
 595pub enum PaneSplitDirectionVertical {
 596    Left,
 597    Right,
 598}
 599
 600#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Default)]
 601#[serde(rename_all = "snake_case")]
 602#[with_fallible_options]
 603pub struct CenteredLayoutSettings {
 604    /// The relative width of the left padding of the central pane from the
 605    /// workspace when the centered layout is used.
 606    ///
 607    /// Default: 0.2
 608    pub left_padding: Option<CenteredPaddingSettings>,
 609    // The relative width of the right padding of the central pane from the
 610    // workspace when the centered layout is used.
 611    ///
 612    /// Default: 0.2
 613    pub right_padding: Option<CenteredPaddingSettings>,
 614}
 615
 616#[derive(
 617    Copy,
 618    Clone,
 619    Default,
 620    Serialize,
 621    Deserialize,
 622    JsonSchema,
 623    MergeFrom,
 624    PartialEq,
 625    Debug,
 626    strum::VariantArray,
 627    strum::VariantNames,
 628)]
 629#[serde(rename_all = "snake_case")]
 630pub enum OnLastWindowClosed {
 631    /// Match platform conventions by default, so don't quit on macOS, and quit on other platforms
 632    #[default]
 633    PlatformDefault,
 634    /// Quit the application the last window is closed
 635    QuitApp,
 636}
 637
 638#[derive(
 639    Copy,
 640    Clone,
 641    Default,
 642    Serialize,
 643    Deserialize,
 644    JsonSchema,
 645    MergeFrom,
 646    PartialEq,
 647    Eq,
 648    Debug,
 649    strum::VariantArray,
 650    strum::VariantNames,
 651)]
 652#[serde(rename_all = "snake_case")]
 653pub enum TextRenderingMode {
 654    /// Use platform default behavior.
 655    #[default]
 656    PlatformDefault,
 657    /// Use subpixel (ClearType-style) text rendering.
 658    Subpixel,
 659    /// Use grayscale text rendering.
 660    Grayscale,
 661}
 662
 663impl OnLastWindowClosed {
 664    pub fn is_quit_app(&self) -> bool {
 665        match self {
 666            OnLastWindowClosed::PlatformDefault => false,
 667            OnLastWindowClosed::QuitApp => true,
 668        }
 669    }
 670}
 671
 672#[with_fallible_options]
 673#[derive(Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)]
 674pub struct ProjectPanelAutoOpenSettings {
 675    /// Whether to automatically open newly created files in the editor.
 676    ///
 677    /// Default: true
 678    pub on_create: Option<bool>,
 679    /// Whether to automatically open files after pasting or duplicating them.
 680    ///
 681    /// Default: true
 682    pub on_paste: Option<bool>,
 683    /// Whether to automatically open files dropped from external sources.
 684    ///
 685    /// Default: true
 686    pub on_drop: Option<bool>,
 687}
 688
 689#[with_fallible_options]
 690#[derive(Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)]
 691pub struct ProjectPanelSettingsContent {
 692    /// Whether to show the project panel button in the status bar.
 693    ///
 694    /// Default: true
 695    pub button: Option<bool>,
 696    /// Whether to hide gitignore files in the project panel.
 697    ///
 698    /// Default: false
 699    pub hide_gitignore: Option<bool>,
 700    /// Customize default width (in pixels) taken by project panel
 701    ///
 702    /// Default: 240
 703    #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
 704    pub default_width: Option<f32>,
 705    /// The position of project panel
 706    ///
 707    /// Default: left
 708    pub dock: Option<DockSide>,
 709    /// Spacing between worktree entries in the project panel.
 710    ///
 711    /// Default: comfortable
 712    pub entry_spacing: Option<ProjectPanelEntrySpacing>,
 713    /// Whether to show file icons in the project panel.
 714    ///
 715    /// Default: true
 716    pub file_icons: Option<bool>,
 717    /// Whether to show folder icons or chevrons for directories in the project panel.
 718    ///
 719    /// Default: true
 720    pub folder_icons: Option<bool>,
 721    /// Whether to show the git status in the project panel.
 722    ///
 723    /// Default: true
 724    pub git_status: Option<bool>,
 725    /// Amount of indentation (in pixels) for nested items.
 726    ///
 727    /// Default: 20
 728    #[serde(serialize_with = "serialize_optional_f32_with_two_decimal_places")]
 729    pub indent_size: Option<f32>,
 730    /// Whether to reveal it in the project panel automatically,
 731    /// when a corresponding project entry becomes active.
 732    /// Gitignored entries are never auto revealed.
 733    ///
 734    /// Default: true
 735    pub auto_reveal_entries: Option<bool>,
 736    /// Whether to fold directories automatically
 737    /// when directory has only one directory inside.
 738    ///
 739    /// Default: true
 740    pub auto_fold_dirs: Option<bool>,
 741    /// Whether to show folder names with bold text in the project panel.
 742    ///
 743    /// Default: false
 744    pub bold_folder_labels: Option<bool>,
 745    /// Whether the project panel should open on startup.
 746    ///
 747    /// Default: true
 748    pub starts_open: Option<bool>,
 749    /// Scrollbar-related settings
 750    pub scrollbar: Option<ProjectPanelScrollbarSettingsContent>,
 751    /// Which files containing diagnostic errors/warnings to mark in the project panel.
 752    ///
 753    /// Default: all
 754    pub show_diagnostics: Option<ShowDiagnostics>,
 755    /// Settings related to indent guides in the project panel.
 756    pub indent_guides: Option<ProjectPanelIndentGuidesSettings>,
 757    /// Whether to hide the root entry when only one folder is open in the window.
 758    ///
 759    /// Default: false
 760    pub hide_root: Option<bool>,
 761    /// Whether to hide the hidden entries in the project panel.
 762    ///
 763    /// Default: false
 764    pub hide_hidden: Option<bool>,
 765    /// Whether to stick parent directories at top of the project panel.
 766    ///
 767    /// Default: true
 768    pub sticky_scroll: Option<bool>,
 769    /// Whether to enable drag-and-drop operations in the project panel.
 770    ///
 771    /// Default: true
 772    pub drag_and_drop: Option<bool>,
 773    /// Settings for automatically opening files.
 774    pub auto_open: Option<ProjectPanelAutoOpenSettings>,
 775    /// How to order sibling entries in the project panel.
 776    ///
 777    /// Default: directories_first
 778    pub sort_mode: Option<ProjectPanelSortMode>,
 779    /// Whether to sort file and folder names case-sensitively in the project panel.
 780    /// This works in combination with `sort_mode`. `sort_mode` controls how files and
 781    /// directories are grouped, while this setting controls how names are compared.
 782    ///
 783    /// Default: default
 784    pub sort_order: Option<ProjectPanelSortOrder>,
 785    /// Whether to show error and warning count badges next to file names in the project panel.
 786    ///
 787    /// Default: false
 788    pub diagnostic_badges: Option<bool>,
 789    /// Whether to show a git status indicator next to file names in the project panel.
 790    ///
 791    /// Default: false
 792    pub git_status_indicator: Option<bool>,
 793}
 794
 795#[derive(
 796    Copy,
 797    Clone,
 798    Debug,
 799    Default,
 800    Serialize,
 801    Deserialize,
 802    JsonSchema,
 803    MergeFrom,
 804    PartialEq,
 805    Eq,
 806    strum::VariantArray,
 807    strum::VariantNames,
 808)]
 809#[serde(rename_all = "snake_case")]
 810pub enum ProjectPanelEntrySpacing {
 811    /// Comfortable spacing of entries.
 812    #[default]
 813    Comfortable,
 814    /// The standard spacing of entries.
 815    Standard,
 816}
 817
 818#[derive(
 819    Copy,
 820    Clone,
 821    Debug,
 822    Default,
 823    Serialize,
 824    Deserialize,
 825    JsonSchema,
 826    MergeFrom,
 827    PartialEq,
 828    Eq,
 829    strum::VariantArray,
 830    strum::VariantNames,
 831)]
 832#[serde(rename_all = "snake_case")]
 833pub enum ProjectPanelSortMode {
 834    /// Show directories first, then files
 835    #[default]
 836    DirectoriesFirst,
 837    /// Mix directories and files together
 838    Mixed,
 839    /// Show files first, then directories
 840    FilesFirst,
 841}
 842
 843#[derive(
 844    Copy,
 845    Clone,
 846    Debug,
 847    Default,
 848    Serialize,
 849    Deserialize,
 850    JsonSchema,
 851    MergeFrom,
 852    PartialEq,
 853    Eq,
 854    strum::VariantArray,
 855    strum::VariantNames,
 856)]
 857#[serde(rename_all = "snake_case")]
 858pub enum ProjectPanelSortOrder {
 859    /// Case-insensitive natural sort with lowercase preferred in ties.
 860    /// Numbers in file names are compared by value (e.g., `file2` before `file10`).
 861    #[default]
 862    Default,
 863    /// Uppercase names are grouped before lowercase names, with case-insensitive
 864    /// natural sort within each group. Dot-prefixed names sort before both groups.
 865    Upper,
 866    /// Lowercase names are grouped before uppercase names, with case-insensitive
 867    /// natural sort within each group. Dot-prefixed names sort before both groups.
 868    Lower,
 869    /// Pure Unicode codepoint comparison. No case folding, no natural number sorting.
 870    /// Uppercase ASCII sorts before lowercase. Accented characters sort after ASCII.
 871    Unicode,
 872}
 873
 874impl From<ProjectPanelSortMode> for util::paths::SortMode {
 875    fn from(mode: ProjectPanelSortMode) -> Self {
 876        match mode {
 877            ProjectPanelSortMode::DirectoriesFirst => Self::DirectoriesFirst,
 878            ProjectPanelSortMode::Mixed => Self::Mixed,
 879            ProjectPanelSortMode::FilesFirst => Self::FilesFirst,
 880        }
 881    }
 882}
 883
 884impl From<ProjectPanelSortOrder> for util::paths::SortOrder {
 885    fn from(order: ProjectPanelSortOrder) -> Self {
 886        match order {
 887            ProjectPanelSortOrder::Default => Self::Default,
 888            ProjectPanelSortOrder::Upper => Self::Upper,
 889            ProjectPanelSortOrder::Lower => Self::Lower,
 890            ProjectPanelSortOrder::Unicode => Self::Unicode,
 891        }
 892    }
 893}
 894
 895#[with_fallible_options]
 896#[derive(
 897    Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq, Default,
 898)]
 899pub struct ProjectPanelScrollbarSettingsContent {
 900    /// When to show the scrollbar in the project panel.
 901    ///
 902    /// Default: inherits editor scrollbar settings
 903    pub show: Option<ShowScrollbar>,
 904    /// Whether to allow horizontal scrolling in the project panel.
 905    /// When false, the view is locked to the leftmost position and
 906    /// long file names are clipped.
 907    ///
 908    /// Default: true
 909    pub horizontal_scroll: Option<bool>,
 910}
 911
 912#[with_fallible_options]
 913#[derive(
 914    Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq, Default,
 915)]
 916pub struct ProjectPanelIndentGuidesSettings {
 917    pub show: Option<ShowIndentGuides>,
 918}
 919
 920/// Controls how semantic tokens from language servers are used for syntax highlighting.
 921#[derive(
 922    Debug,
 923    PartialEq,
 924    Eq,
 925    Clone,
 926    Copy,
 927    Default,
 928    Serialize,
 929    Deserialize,
 930    JsonSchema,
 931    MergeFrom,
 932    strum::VariantArray,
 933    strum::VariantNames,
 934    strum::EnumMessage,
 935)]
 936#[serde(rename_all = "snake_case")]
 937pub enum SemanticTokens {
 938    /// Do not request semantic tokens from language servers.
 939    #[default]
 940    Off,
 941    /// Use LSP semantic tokens together with tree-sitter highlighting.
 942    Combined,
 943    /// Use LSP semantic tokens exclusively, replacing tree-sitter highlighting.
 944    Full,
 945}
 946
 947impl SemanticTokens {
 948    /// Returns true if semantic tokens should be requested from language servers.
 949    pub fn enabled(&self) -> bool {
 950        self != &Self::Off
 951    }
 952
 953    /// Returns true if tree-sitter syntax highlighting should be used.
 954    /// In `full` mode, tree-sitter is disabled in favor of LSP semantic tokens.
 955    pub fn use_tree_sitter(&self) -> bool {
 956        self != &Self::Full
 957    }
 958}
 959
 960#[derive(
 961    Debug,
 962    PartialEq,
 963    Eq,
 964    Clone,
 965    Copy,
 966    Default,
 967    Serialize,
 968    Deserialize,
 969    JsonSchema,
 970    MergeFrom,
 971    strum::VariantArray,
 972    strum::VariantNames,
 973)]
 974#[serde(rename_all = "snake_case")]
 975pub enum DocumentFoldingRanges {
 976    /// Do not request folding ranges from language servers; use tree-sitter and indent-based folding.
 977    #[default]
 978    Off,
 979    /// Use LSP folding wherever possible, falling back to tree-sitter and indent-based folding when no results were returned by the server.
 980    On,
 981}
 982
 983impl DocumentFoldingRanges {
 984    /// Returns true if LSP folding ranges should be requested from language servers.
 985    pub fn enabled(&self) -> bool {
 986        self != &Self::Off
 987    }
 988}
 989
 990#[derive(
 991    Debug,
 992    PartialEq,
 993    Eq,
 994    Clone,
 995    Copy,
 996    Default,
 997    Serialize,
 998    Deserialize,
 999    JsonSchema,
1000    MergeFrom,
1001    strum::VariantArray,
1002    strum::VariantNames,
1003)]
1004#[serde(rename_all = "snake_case")]
1005pub enum DocumentSymbols {
1006    /// Use tree-sitter queries to compute document symbols for outlines and breadcrumbs (default).
1007    #[default]
1008    #[serde(alias = "tree_sitter")]
1009    Off,
1010    /// Use the language server's `textDocument/documentSymbol` LSP response for outlines and
1011    /// breadcrumbs. When enabled, tree-sitter is not used for document symbols.
1012    #[serde(alias = "language_server")]
1013    On,
1014}
1015
1016impl DocumentSymbols {
1017    /// Returns true if LSP document symbols should be used instead of tree-sitter.
1018    pub fn lsp_enabled(&self) -> bool {
1019        self == &Self::On
1020    }
1021}
1022
1023#[with_fallible_options]
1024#[derive(Copy, Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)]
1025pub struct FocusFollowsMouse {
1026    pub enabled: Option<bool>,
1027    pub debounce_ms: Option<u64>,
1028}