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    /// Open directories as a new workspace in the current Zed window's sidebar.
 404    #[default]
 405    #[strum(serialize = "Add to Existing Window")]
 406    ExistingWindow,
 407    /// Open directories in a new window, but reuse an existing window when
 408    /// opening files that are already part of an open project.
 409    #[strum(serialize = "Open a New Window")]
 410    NewWindow,
 411}
 412
 413#[derive(
 414    Copy,
 415    Clone,
 416    PartialEq,
 417    Eq,
 418    Default,
 419    Serialize,
 420    Deserialize,
 421    JsonSchema,
 422    MergeFrom,
 423    Debug,
 424    strum::VariantArray,
 425    strum::VariantNames,
 426)]
 427#[serde(rename_all = "snake_case")]
 428pub enum RestoreOnStartupBehavior {
 429    /// Always start with an empty editor tab
 430    #[serde(alias = "none")]
 431    EmptyTab,
 432    /// Restore the workspace that was closed last.
 433    LastWorkspace,
 434    /// Restore all workspaces that were open when quitting Zed.
 435    #[default]
 436    LastSession,
 437    /// Show the launchpad with recent projects (no tabs).
 438    Launchpad,
 439}
 440
 441#[with_fallible_options]
 442#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq)]
 443pub struct TabBarSettingsContent {
 444    /// Whether or not to show the tab bar in the editor.
 445    ///
 446    /// Default: true
 447    pub show: Option<bool>,
 448    /// Whether or not to show the navigation history buttons in the tab bar.
 449    ///
 450    /// Default: true
 451    pub show_nav_history_buttons: Option<bool>,
 452    /// Whether or not to show the tab bar buttons.
 453    ///
 454    /// Default: true
 455    pub show_tab_bar_buttons: Option<bool>,
 456    /// Whether or not to show pinned tabs in a separate row.
 457    /// When enabled, pinned tabs appear in a top row and unpinned tabs in a bottom row.
 458    ///
 459    /// Default: false
 460    pub show_pinned_tabs_in_separate_row: Option<bool>,
 461}
 462
 463#[with_fallible_options]
 464#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq, Eq)]
 465pub struct StatusBarSettingsContent {
 466    /// Whether to show the status bar.
 467    ///
 468    /// Default: true
 469    #[serde(rename = "experimental.show")]
 470    pub show: Option<bool>,
 471    /// Whether to show the name of the active file in the status bar.
 472    ///
 473    /// Default: false
 474    pub show_active_file: Option<bool>,
 475    /// Whether to display the active language button in the status bar.
 476    ///
 477    /// Default: true
 478    pub active_language_button: Option<bool>,
 479    /// Whether to show the cursor position button in the status bar.
 480    ///
 481    /// Default: true
 482    pub cursor_position_button: Option<bool>,
 483    /// Whether to show active line endings button in the status bar.
 484    ///
 485    /// Default: false
 486    pub line_endings_button: Option<bool>,
 487    /// Whether to show the active encoding button in the status bar.
 488    ///
 489    /// Default: non_utf8
 490    pub active_encoding_button: Option<EncodingDisplayOptions>,
 491}
 492
 493#[derive(
 494    Copy,
 495    Clone,
 496    Debug,
 497    Eq,
 498    PartialEq,
 499    Default,
 500    Serialize,
 501    Deserialize,
 502    JsonSchema,
 503    MergeFrom,
 504    strum::VariantNames,
 505    strum::VariantArray,
 506)]
 507#[serde(rename_all = "snake_case")]
 508pub enum EncodingDisplayOptions {
 509    Enabled,
 510    Disabled,
 511    #[default]
 512    NonUtf8,
 513}
 514impl EncodingDisplayOptions {
 515    pub fn should_show(&self, is_utf8: bool, has_bom: bool) -> bool {
 516        match self {
 517            Self::Disabled => false,
 518            Self::Enabled => true,
 519            Self::NonUtf8 => {
 520                let is_standard_utf8 = is_utf8 && !has_bom;
 521                !is_standard_utf8
 522            }
 523        }
 524    }
 525}
 526
 527#[derive(
 528    Copy,
 529    Clone,
 530    Debug,
 531    Serialize,
 532    Deserialize,
 533    PartialEq,
 534    Eq,
 535    JsonSchema,
 536    MergeFrom,
 537    strum::EnumDiscriminants,
 538)]
 539#[strum_discriminants(derive(strum::VariantArray, strum::VariantNames, strum::FromRepr))]
 540#[serde(rename_all = "snake_case")]
 541pub enum AutosaveSetting {
 542    /// Disable autosave.
 543    Off,
 544    /// Save after inactivity period of `milliseconds`.
 545    AfterDelay { milliseconds: DelayMs },
 546    /// Autosave when focus changes.
 547    OnFocusChange,
 548    /// Autosave when the active window changes.
 549    OnWindowChange,
 550}
 551
 552impl AutosaveSetting {
 553    pub fn should_save_on_close(&self) -> bool {
 554        matches!(
 555            &self,
 556            AutosaveSetting::OnFocusChange
 557                | AutosaveSetting::OnWindowChange
 558                | AutosaveSetting::AfterDelay { .. }
 559        )
 560    }
 561}
 562
 563#[derive(
 564    Copy,
 565    Clone,
 566    Debug,
 567    Serialize,
 568    Deserialize,
 569    PartialEq,
 570    Eq,
 571    JsonSchema,
 572    MergeFrom,
 573    strum::VariantArray,
 574    strum::VariantNames,
 575)]
 576#[serde(rename_all = "snake_case")]
 577pub enum PaneSplitDirectionHorizontal {
 578    Up,
 579    Down,
 580}
 581
 582#[derive(
 583    Copy,
 584    Clone,
 585    Debug,
 586    Serialize,
 587    Deserialize,
 588    PartialEq,
 589    Eq,
 590    JsonSchema,
 591    MergeFrom,
 592    strum::VariantArray,
 593    strum::VariantNames,
 594)]
 595#[serde(rename_all = "snake_case")]
 596pub enum PaneSplitDirectionVertical {
 597    Left,
 598    Right,
 599}
 600
 601#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Default)]
 602#[serde(rename_all = "snake_case")]
 603#[with_fallible_options]
 604pub struct CenteredLayoutSettings {
 605    /// The relative width of the left padding of the central pane from the
 606    /// workspace when the centered layout is used.
 607    ///
 608    /// Default: 0.2
 609    pub left_padding: Option<CenteredPaddingSettings>,
 610    // The relative width of the right padding of the central pane from the
 611    // workspace when the centered layout is used.
 612    ///
 613    /// Default: 0.2
 614    pub right_padding: Option<CenteredPaddingSettings>,
 615}
 616
 617#[derive(
 618    Copy,
 619    Clone,
 620    Default,
 621    Serialize,
 622    Deserialize,
 623    JsonSchema,
 624    MergeFrom,
 625    PartialEq,
 626    Debug,
 627    strum::VariantArray,
 628    strum::VariantNames,
 629)]
 630#[serde(rename_all = "snake_case")]
 631pub enum OnLastWindowClosed {
 632    /// Match platform conventions by default, so don't quit on macOS, and quit on other platforms
 633    #[default]
 634    PlatformDefault,
 635    /// Quit the application the last window is closed
 636    QuitApp,
 637}
 638
 639#[derive(
 640    Copy,
 641    Clone,
 642    Default,
 643    Serialize,
 644    Deserialize,
 645    JsonSchema,
 646    MergeFrom,
 647    PartialEq,
 648    Eq,
 649    Debug,
 650    strum::VariantArray,
 651    strum::VariantNames,
 652)]
 653#[serde(rename_all = "snake_case")]
 654pub enum TextRenderingMode {
 655    /// Use platform default behavior.
 656    #[default]
 657    PlatformDefault,
 658    /// Use subpixel (ClearType-style) text rendering.
 659    Subpixel,
 660    /// Use grayscale text rendering.
 661    Grayscale,
 662}
 663
 664impl OnLastWindowClosed {
 665    pub fn is_quit_app(&self) -> bool {
 666        match self {
 667            OnLastWindowClosed::PlatformDefault => false,
 668            OnLastWindowClosed::QuitApp => true,
 669        }
 670    }
 671}
 672
 673#[with_fallible_options]
 674#[derive(Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)]
 675pub struct ProjectPanelAutoOpenSettings {
 676    /// Whether to automatically open newly created files in the editor.
 677    ///
 678    /// Default: true
 679    pub on_create: Option<bool>,
 680    /// Whether to automatically open files after pasting or duplicating them.
 681    ///
 682    /// Default: true
 683    pub on_paste: Option<bool>,
 684    /// Whether to automatically open files dropped from external sources.
 685    ///
 686    /// Default: true
 687    pub on_drop: Option<bool>,
 688}
 689
 690#[with_fallible_options]
 691#[derive(Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)]
 692pub struct ProjectPanelSettingsContent {
 693    /// Whether to show the project panel button in the status bar.
 694    ///
 695    /// Default: true
 696    pub button: Option<bool>,
 697    /// Whether to hide gitignore files in the project panel.
 698    ///
 699    /// Default: false
 700    pub hide_gitignore: Option<bool>,
 701    /// Customize default width (in pixels) taken by project panel
 702    ///
 703    /// Default: 240
 704    #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
 705    pub default_width: Option<f32>,
 706    /// The position of project panel
 707    ///
 708    /// Default: left
 709    pub dock: Option<DockSide>,
 710    /// Spacing between worktree entries in the project panel.
 711    ///
 712    /// Default: comfortable
 713    pub entry_spacing: Option<ProjectPanelEntrySpacing>,
 714    /// Whether to show file icons in the project panel.
 715    ///
 716    /// Default: true
 717    pub file_icons: Option<bool>,
 718    /// Whether to show folder icons or chevrons for directories in the project panel.
 719    ///
 720    /// Default: true
 721    pub folder_icons: Option<bool>,
 722    /// Whether to show the git status in the project panel.
 723    ///
 724    /// Default: true
 725    pub git_status: Option<bool>,
 726    /// Amount of indentation (in pixels) for nested items.
 727    ///
 728    /// Default: 20
 729    #[serde(serialize_with = "serialize_optional_f32_with_two_decimal_places")]
 730    pub indent_size: Option<f32>,
 731    /// Whether to reveal it in the project panel automatically,
 732    /// when a corresponding project entry becomes active.
 733    /// Gitignored entries are never auto revealed.
 734    ///
 735    /// Default: true
 736    pub auto_reveal_entries: Option<bool>,
 737    /// Whether to fold directories automatically
 738    /// when directory has only one directory inside.
 739    ///
 740    /// Default: true
 741    pub auto_fold_dirs: Option<bool>,
 742    /// Whether to show folder names with bold text in the project panel.
 743    ///
 744    /// Default: false
 745    pub bold_folder_labels: Option<bool>,
 746    /// Whether the project panel should open on startup.
 747    ///
 748    /// Default: true
 749    pub starts_open: Option<bool>,
 750    /// Scrollbar-related settings
 751    pub scrollbar: Option<ProjectPanelScrollbarSettingsContent>,
 752    /// Which files containing diagnostic errors/warnings to mark in the project panel.
 753    ///
 754    /// Default: all
 755    pub show_diagnostics: Option<ShowDiagnostics>,
 756    /// Settings related to indent guides in the project panel.
 757    pub indent_guides: Option<ProjectPanelIndentGuidesSettings>,
 758    /// Whether to hide the root entry when only one folder is open in the window.
 759    ///
 760    /// Default: false
 761    pub hide_root: Option<bool>,
 762    /// Whether to hide the hidden entries in the project panel.
 763    ///
 764    /// Default: false
 765    pub hide_hidden: Option<bool>,
 766    /// Whether to stick parent directories at top of the project panel.
 767    ///
 768    /// Default: true
 769    pub sticky_scroll: Option<bool>,
 770    /// Whether to enable drag-and-drop operations in the project panel.
 771    ///
 772    /// Default: true
 773    pub drag_and_drop: Option<bool>,
 774    /// Settings for automatically opening files.
 775    pub auto_open: Option<ProjectPanelAutoOpenSettings>,
 776    /// How to order sibling entries in the project panel.
 777    ///
 778    /// Default: directories_first
 779    pub sort_mode: Option<ProjectPanelSortMode>,
 780    /// Whether to sort file and folder names case-sensitively in the project panel.
 781    /// This works in combination with `sort_mode`. `sort_mode` controls how files and
 782    /// directories are grouped, while this setting controls how names are compared.
 783    ///
 784    /// Default: default
 785    pub sort_order: Option<ProjectPanelSortOrder>,
 786    /// Whether to show error and warning count badges next to file names in the project panel.
 787    ///
 788    /// Default: false
 789    pub diagnostic_badges: Option<bool>,
 790    /// Whether to show a git status indicator next to file names in the project panel.
 791    ///
 792    /// Default: false
 793    pub git_status_indicator: Option<bool>,
 794}
 795
 796#[derive(
 797    Copy,
 798    Clone,
 799    Debug,
 800    Default,
 801    Serialize,
 802    Deserialize,
 803    JsonSchema,
 804    MergeFrom,
 805    PartialEq,
 806    Eq,
 807    strum::VariantArray,
 808    strum::VariantNames,
 809)]
 810#[serde(rename_all = "snake_case")]
 811pub enum ProjectPanelEntrySpacing {
 812    /// Comfortable spacing of entries.
 813    #[default]
 814    Comfortable,
 815    /// The standard spacing of entries.
 816    Standard,
 817}
 818
 819#[derive(
 820    Copy,
 821    Clone,
 822    Debug,
 823    Default,
 824    Serialize,
 825    Deserialize,
 826    JsonSchema,
 827    MergeFrom,
 828    PartialEq,
 829    Eq,
 830    strum::VariantArray,
 831    strum::VariantNames,
 832)]
 833#[serde(rename_all = "snake_case")]
 834pub enum ProjectPanelSortMode {
 835    /// Show directories first, then files
 836    #[default]
 837    DirectoriesFirst,
 838    /// Mix directories and files together
 839    Mixed,
 840    /// Show files first, then directories
 841    FilesFirst,
 842}
 843
 844#[derive(
 845    Copy,
 846    Clone,
 847    Debug,
 848    Default,
 849    Serialize,
 850    Deserialize,
 851    JsonSchema,
 852    MergeFrom,
 853    PartialEq,
 854    Eq,
 855    strum::VariantArray,
 856    strum::VariantNames,
 857)]
 858#[serde(rename_all = "snake_case")]
 859pub enum ProjectPanelSortOrder {
 860    /// Case-insensitive natural sort with lowercase preferred in ties.
 861    /// Numbers in file names are compared by value (e.g., `file2` before `file10`).
 862    #[default]
 863    Default,
 864    /// Uppercase names are grouped before lowercase names, with case-insensitive
 865    /// natural sort within each group. Dot-prefixed names sort before both groups.
 866    Upper,
 867    /// Lowercase names are grouped before uppercase names, with case-insensitive
 868    /// natural sort within each group. Dot-prefixed names sort before both groups.
 869    Lower,
 870    /// Pure Unicode codepoint comparison. No case folding, no natural number sorting.
 871    /// Uppercase ASCII sorts before lowercase. Accented characters sort after ASCII.
 872    Unicode,
 873}
 874
 875impl From<ProjectPanelSortMode> for util::paths::SortMode {
 876    fn from(mode: ProjectPanelSortMode) -> Self {
 877        match mode {
 878            ProjectPanelSortMode::DirectoriesFirst => Self::DirectoriesFirst,
 879            ProjectPanelSortMode::Mixed => Self::Mixed,
 880            ProjectPanelSortMode::FilesFirst => Self::FilesFirst,
 881        }
 882    }
 883}
 884
 885impl From<ProjectPanelSortOrder> for util::paths::SortOrder {
 886    fn from(order: ProjectPanelSortOrder) -> Self {
 887        match order {
 888            ProjectPanelSortOrder::Default => Self::Default,
 889            ProjectPanelSortOrder::Upper => Self::Upper,
 890            ProjectPanelSortOrder::Lower => Self::Lower,
 891            ProjectPanelSortOrder::Unicode => Self::Unicode,
 892        }
 893    }
 894}
 895
 896#[with_fallible_options]
 897#[derive(
 898    Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq, Default,
 899)]
 900pub struct ProjectPanelScrollbarSettingsContent {
 901    /// When to show the scrollbar in the project panel.
 902    ///
 903    /// Default: inherits editor scrollbar settings
 904    pub show: Option<ShowScrollbar>,
 905    /// Whether to allow horizontal scrolling in the project panel.
 906    /// When false, the view is locked to the leftmost position and
 907    /// long file names are clipped.
 908    ///
 909    /// Default: true
 910    pub horizontal_scroll: Option<bool>,
 911}
 912
 913#[with_fallible_options]
 914#[derive(
 915    Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq, Default,
 916)]
 917pub struct ProjectPanelIndentGuidesSettings {
 918    pub show: Option<ShowIndentGuides>,
 919}
 920
 921/// Controls how semantic tokens from language servers are used for syntax highlighting.
 922#[derive(
 923    Debug,
 924    PartialEq,
 925    Eq,
 926    Clone,
 927    Copy,
 928    Default,
 929    Serialize,
 930    Deserialize,
 931    JsonSchema,
 932    MergeFrom,
 933    strum::VariantArray,
 934    strum::VariantNames,
 935    strum::EnumMessage,
 936)]
 937#[serde(rename_all = "snake_case")]
 938pub enum SemanticTokens {
 939    /// Do not request semantic tokens from language servers.
 940    #[default]
 941    Off,
 942    /// Use LSP semantic tokens together with tree-sitter highlighting.
 943    Combined,
 944    /// Use LSP semantic tokens exclusively, replacing tree-sitter highlighting.
 945    Full,
 946}
 947
 948impl SemanticTokens {
 949    /// Returns true if semantic tokens should be requested from language servers.
 950    pub fn enabled(&self) -> bool {
 951        self != &Self::Off
 952    }
 953
 954    /// Returns true if tree-sitter syntax highlighting should be used.
 955    /// In `full` mode, tree-sitter is disabled in favor of LSP semantic tokens.
 956    pub fn use_tree_sitter(&self) -> bool {
 957        self != &Self::Full
 958    }
 959}
 960
 961#[derive(
 962    Debug,
 963    PartialEq,
 964    Eq,
 965    Clone,
 966    Copy,
 967    Default,
 968    Serialize,
 969    Deserialize,
 970    JsonSchema,
 971    MergeFrom,
 972    strum::VariantArray,
 973    strum::VariantNames,
 974)]
 975#[serde(rename_all = "snake_case")]
 976pub enum DocumentFoldingRanges {
 977    /// Do not request folding ranges from language servers; use tree-sitter and indent-based folding.
 978    #[default]
 979    Off,
 980    /// Use LSP folding wherever possible, falling back to tree-sitter and indent-based folding when no results were returned by the server.
 981    On,
 982}
 983
 984impl DocumentFoldingRanges {
 985    /// Returns true if LSP folding ranges should be requested from language servers.
 986    pub fn enabled(&self) -> bool {
 987        self != &Self::Off
 988    }
 989}
 990
 991#[derive(
 992    Debug,
 993    PartialEq,
 994    Eq,
 995    Clone,
 996    Copy,
 997    Default,
 998    Serialize,
 999    Deserialize,
1000    JsonSchema,
1001    MergeFrom,
1002    strum::VariantArray,
1003    strum::VariantNames,
1004)]
1005#[serde(rename_all = "snake_case")]
1006pub enum DocumentSymbols {
1007    /// Use tree-sitter queries to compute document symbols for outlines and breadcrumbs (default).
1008    #[default]
1009    #[serde(alias = "tree_sitter")]
1010    Off,
1011    /// Use the language server's `textDocument/documentSymbol` LSP response for outlines and
1012    /// breadcrumbs. When enabled, tree-sitter is not used for document symbols.
1013    #[serde(alias = "language_server")]
1014    On,
1015}
1016
1017impl DocumentSymbols {
1018    /// Returns true if LSP document symbols should be used instead of tree-sitter.
1019    pub fn lsp_enabled(&self) -> bool {
1020        self == &Self::On
1021    }
1022}
1023
1024#[with_fallible_options]
1025#[derive(Copy, Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)]
1026pub struct FocusFollowsMouse {
1027    pub enabled: Option<bool>,
1028    pub debounce_ms: Option<u64>,
1029}