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