editor_settings.rs

  1use gpui::App;
  2use language::CursorShape;
  3use project::project_settings::DiagnosticSeverity;
  4use schemars::JsonSchema;
  5use serde::{Deserialize, Serialize};
  6use settings::{Settings, SettingsSources, VsCodeSettings};
  7use util::serde::default_true;
  8
  9/// Imports from the VSCode settings at
 10/// https://code.visualstudio.com/docs/reference/default-settings
 11#[derive(Deserialize, Clone)]
 12pub struct EditorSettings {
 13    pub cursor_blink: bool,
 14    pub cursor_shape: Option<CursorShape>,
 15    pub current_line_highlight: CurrentLineHighlight,
 16    pub selection_highlight: bool,
 17    pub lsp_highlight_debounce: u64,
 18    pub hover_popover_enabled: bool,
 19    pub hover_popover_delay: u64,
 20    pub toolbar: Toolbar,
 21    pub scrollbar: Scrollbar,
 22    pub minimap: Minimap,
 23    pub gutter: Gutter,
 24    pub scroll_beyond_last_line: ScrollBeyondLastLine,
 25    pub vertical_scroll_margin: f32,
 26    pub autoscroll_on_clicks: bool,
 27    pub horizontal_scroll_margin: f32,
 28    pub scroll_sensitivity: f32,
 29    pub fast_scroll_sensitivity: f32,
 30    pub relative_line_numbers: bool,
 31    pub seed_search_query_from_cursor: SeedQuerySetting,
 32    pub use_smartcase_search: bool,
 33    pub multi_cursor_modifier: MultiCursorModifier,
 34    pub redact_private_values: bool,
 35    pub expand_excerpt_lines: u32,
 36    pub middle_click_paste: bool,
 37    #[serde(default)]
 38    pub double_click_in_multibuffer: DoubleClickInMultibuffer,
 39    pub search_wrap: bool,
 40    #[serde(default)]
 41    pub search: SearchSettings,
 42    pub auto_signature_help: bool,
 43    pub show_signature_help_after_edits: bool,
 44    #[serde(default)]
 45    pub go_to_definition_fallback: GoToDefinitionFallback,
 46    pub jupyter: Jupyter,
 47    pub hide_mouse: Option<HideMouseMode>,
 48    pub snippet_sort_order: SnippetSortOrder,
 49    #[serde(default)]
 50    pub diagnostics_max_severity: Option<DiagnosticSeverity>,
 51    pub inline_code_actions: bool,
 52    pub drag_and_drop_selection: bool,
 53    pub lsp_document_colors: DocumentColorsRenderMode,
 54}
 55
 56/// How to render LSP `textDocument/documentColor` colors in the editor.
 57#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
 58#[serde(rename_all = "snake_case")]
 59pub enum DocumentColorsRenderMode {
 60    /// Do not query and render document colors.
 61    None,
 62    /// Render document colors as inlay hints near the color text.
 63    #[default]
 64    Inlay,
 65    /// Draw a border around the color text.
 66    Border,
 67    /// Draw a background behind the color text.
 68    Background,
 69}
 70
 71#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
 72#[serde(rename_all = "snake_case")]
 73pub enum CurrentLineHighlight {
 74    // Don't highlight the current line.
 75    None,
 76    // Highlight the gutter area.
 77    Gutter,
 78    // Highlight the editor area.
 79    Line,
 80    // Highlight the full line.
 81    All,
 82}
 83
 84/// When to populate a new search's query based on the text under the cursor.
 85#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
 86#[serde(rename_all = "snake_case")]
 87pub enum SeedQuerySetting {
 88    /// Always populate the search query with the word under the cursor.
 89    Always,
 90    /// Only populate the search query when there is text selected.
 91    Selection,
 92    /// Never populate the search query
 93    Never,
 94}
 95
 96/// What to do when multibuffer is double clicked in some of its excerpts (parts of singleton buffers).
 97#[derive(Default, Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
 98#[serde(rename_all = "snake_case")]
 99pub enum DoubleClickInMultibuffer {
100    /// Behave as a regular buffer and select the whole word.
101    #[default]
102    Select,
103    /// Open the excerpt clicked as a new buffer in the new tab, if no `alt` modifier was pressed during double click.
104    /// Otherwise, behave as a regular buffer and select the whole word.
105    Open,
106}
107
108#[derive(Debug, Clone, Deserialize)]
109pub struct Jupyter {
110    /// Whether the Jupyter feature is enabled.
111    ///
112    /// Default: true
113    pub enabled: bool,
114}
115
116#[derive(Default, Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
117#[serde(rename_all = "snake_case")]
118pub struct JupyterContent {
119    /// Whether the Jupyter feature is enabled.
120    ///
121    /// Default: true
122    pub enabled: Option<bool>,
123}
124
125#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
126pub struct Toolbar {
127    pub breadcrumbs: bool,
128    pub quick_actions: bool,
129    pub selections_menu: bool,
130    pub agent_review: bool,
131    pub code_actions: bool,
132}
133
134#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
135pub struct Scrollbar {
136    pub show: ShowScrollbar,
137    pub git_diff: bool,
138    pub selected_text: bool,
139    pub selected_symbol: bool,
140    pub search_results: bool,
141    pub diagnostics: ScrollbarDiagnostics,
142    pub cursors: bool,
143    pub axes: ScrollbarAxes,
144}
145
146#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq)]
147pub struct Minimap {
148    pub show: ShowMinimap,
149    pub display_in: DisplayIn,
150    pub thumb: MinimapThumb,
151    pub thumb_border: MinimapThumbBorder,
152    pub current_line_highlight: Option<CurrentLineHighlight>,
153}
154
155impl Minimap {
156    pub fn minimap_enabled(&self) -> bool {
157        self.show != ShowMinimap::Never
158    }
159
160    #[inline]
161    pub fn on_active_editor(&self) -> bool {
162        self.display_in == DisplayIn::ActiveEditor
163    }
164
165    pub fn with_show_override(self) -> Self {
166        Self {
167            show: ShowMinimap::Always,
168            ..self
169        }
170    }
171}
172
173#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
174pub struct Gutter {
175    pub min_line_number_digits: usize,
176    pub line_numbers: bool,
177    pub runnables: bool,
178    pub breakpoints: bool,
179    pub folds: bool,
180}
181
182/// When to show the scrollbar in the editor.
183///
184/// Default: auto
185#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
186#[serde(rename_all = "snake_case")]
187pub enum ShowScrollbar {
188    /// Show the scrollbar if there's important information or
189    /// follow the system's configured behavior.
190    Auto,
191    /// Match the system's configured behavior.
192    System,
193    /// Always show the scrollbar.
194    Always,
195    /// Never show the scrollbar.
196    Never,
197}
198
199/// When to show the minimap in the editor.
200///
201/// Default: never
202#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
203#[serde(rename_all = "snake_case")]
204pub enum ShowMinimap {
205    /// Follow the visibility of the scrollbar.
206    Auto,
207    /// Always show the minimap.
208    Always,
209    /// Never show the minimap.
210    #[default]
211    Never,
212}
213
214/// Where to show the minimap in the editor.
215///
216/// Default: all_editors
217#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
218#[serde(rename_all = "snake_case")]
219pub enum DisplayIn {
220    /// Show on all open editors.
221    AllEditors,
222    /// Show the minimap on the active editor only.
223    #[default]
224    ActiveEditor,
225}
226
227/// When to show the minimap thumb.
228///
229/// Default: always
230#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
231#[serde(rename_all = "snake_case")]
232pub enum MinimapThumb {
233    /// Show the minimap thumb only when the mouse is hovering over the minimap.
234    Hover,
235    /// Always show the minimap thumb.
236    #[default]
237    Always,
238}
239
240/// Defines the border style for the minimap's scrollbar thumb.
241///
242/// Default: left_open
243#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
244#[serde(rename_all = "snake_case")]
245pub enum MinimapThumbBorder {
246    /// Displays a border on all sides of the thumb.
247    Full,
248    /// Displays a border on all sides except the left side of the thumb.
249    #[default]
250    LeftOpen,
251    /// Displays a border on all sides except the right side of the thumb.
252    RightOpen,
253    /// Displays a border only on the left side of the thumb.
254    LeftOnly,
255    /// Displays the thumb without any border.
256    None,
257}
258
259/// Forcefully enable or disable the scrollbar for each axis
260#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
261#[serde(rename_all = "lowercase")]
262pub struct ScrollbarAxes {
263    /// When false, forcefully disables the horizontal scrollbar. Otherwise, obey other settings.
264    ///
265    /// Default: true
266    pub horizontal: bool,
267
268    /// When false, forcefully disables the vertical scrollbar. Otherwise, obey other settings.
269    ///
270    /// Default: true
271    pub vertical: bool,
272}
273
274/// Which diagnostic indicators to show in the scrollbar.
275///
276/// Default: all
277#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
278#[serde(rename_all = "lowercase")]
279pub enum ScrollbarDiagnostics {
280    /// Show all diagnostic levels: hint, information, warnings, error.
281    All,
282    /// Show only the following diagnostic levels: information, warning, error.
283    Information,
284    /// Show only the following diagnostic levels: warning, error.
285    Warning,
286    /// Show only the following diagnostic level: error.
287    Error,
288    /// Do not show diagnostics.
289    None,
290}
291
292/// The key to use for adding multiple cursors
293///
294/// Default: alt
295#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
296#[serde(rename_all = "snake_case")]
297pub enum MultiCursorModifier {
298    Alt,
299    #[serde(alias = "cmd", alias = "ctrl")]
300    CmdOrCtrl,
301}
302
303/// Whether the editor will scroll beyond the last line.
304///
305/// Default: one_page
306#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
307#[serde(rename_all = "snake_case")]
308pub enum ScrollBeyondLastLine {
309    /// The editor will not scroll beyond the last line.
310    Off,
311
312    /// The editor will scroll beyond the last line by one page.
313    OnePage,
314
315    /// The editor will scroll beyond the last line by the same number of lines as vertical_scroll_margin.
316    VerticalScrollMargin,
317}
318
319/// Default options for buffer and project search items.
320#[derive(Copy, Clone, Default, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
321pub struct SearchSettings {
322    /// Whether to show the project search button in the status bar.
323    #[serde(default = "default_true")]
324    pub button: bool,
325    #[serde(default)]
326    pub whole_word: bool,
327    #[serde(default)]
328    pub case_sensitive: bool,
329    #[serde(default)]
330    pub include_ignored: bool,
331    #[serde(default)]
332    pub regex: bool,
333}
334
335/// What to do when go to definition yields no results.
336#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
337#[serde(rename_all = "snake_case")]
338pub enum GoToDefinitionFallback {
339    /// Disables the fallback.
340    None,
341    /// Looks up references of the same symbol instead.
342    #[default]
343    FindAllReferences,
344}
345
346/// Determines when the mouse cursor should be hidden in an editor or input box.
347///
348/// Default: on_typing_and_movement
349#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
350#[serde(rename_all = "snake_case")]
351pub enum HideMouseMode {
352    /// Never hide the mouse cursor
353    Never,
354    /// Hide only when typing
355    OnTyping,
356    /// Hide on both typing and cursor movement
357    #[default]
358    OnTypingAndMovement,
359}
360
361/// Determines how snippets are sorted relative to other completion items.
362///
363/// Default: inline
364#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
365#[serde(rename_all = "snake_case")]
366pub enum SnippetSortOrder {
367    /// Place snippets at the top of the completion list
368    Top,
369    /// Sort snippets normally using the default comparison logic
370    #[default]
371    Inline,
372    /// Place snippets at the bottom of the completion list
373    Bottom,
374}
375
376#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
377#[schemars(deny_unknown_fields)]
378pub struct EditorSettingsContent {
379    /// Whether the cursor blinks in the editor.
380    ///
381    /// Default: true
382    pub cursor_blink: Option<bool>,
383    /// Cursor shape for the default editor.
384    /// Can be "bar", "block", "underline", or "hollow".
385    ///
386    /// Default: None
387    pub cursor_shape: Option<CursorShape>,
388    /// Determines when the mouse cursor should be hidden in an editor or input box.
389    ///
390    /// Default: on_typing_and_movement
391    pub hide_mouse: Option<HideMouseMode>,
392    /// Determines how snippets are sorted relative to other completion items.
393    ///
394    /// Default: inline
395    pub snippet_sort_order: Option<SnippetSortOrder>,
396    /// How to highlight the current line in the editor.
397    ///
398    /// Default: all
399    pub current_line_highlight: Option<CurrentLineHighlight>,
400    /// Whether to highlight all occurrences of the selected text in an editor.
401    ///
402    /// Default: true
403    pub selection_highlight: Option<bool>,
404    /// The debounce delay before querying highlights from the language
405    /// server based on the current cursor location.
406    ///
407    /// Default: 75
408    pub lsp_highlight_debounce: Option<u64>,
409    /// Whether to show the informational hover box when moving the mouse
410    /// over symbols in the editor.
411    ///
412    /// Default: true
413    pub hover_popover_enabled: Option<bool>,
414    /// Time to wait in milliseconds before showing the informational hover box.
415    ///
416    /// Default: 300
417    pub hover_popover_delay: Option<u64>,
418    /// Toolbar related settings
419    pub toolbar: Option<ToolbarContent>,
420    /// Scrollbar related settings
421    pub scrollbar: Option<ScrollbarContent>,
422    /// Minimap related settings
423    pub minimap: Option<MinimapContent>,
424    /// Gutter related settings
425    pub gutter: Option<GutterContent>,
426    /// Whether the editor will scroll beyond the last line.
427    ///
428    /// Default: one_page
429    pub scroll_beyond_last_line: Option<ScrollBeyondLastLine>,
430    /// The number of lines to keep above/below the cursor when auto-scrolling.
431    ///
432    /// Default: 3.
433    pub vertical_scroll_margin: Option<f32>,
434    /// Whether to scroll when clicking near the edge of the visible text area.
435    ///
436    /// Default: false
437    pub autoscroll_on_clicks: Option<bool>,
438    /// The number of characters to keep on either side when scrolling with the mouse.
439    ///
440    /// Default: 5.
441    pub horizontal_scroll_margin: Option<f32>,
442    /// Scroll sensitivity multiplier. This multiplier is applied
443    /// to both the horizontal and vertical delta values while scrolling.
444    ///
445    /// Default: 1.0
446    pub scroll_sensitivity: Option<f32>,
447    /// Scroll sensitivity multiplier for fast scrolling. This multiplier is applied
448    /// to both the horizontal and vertical delta values while scrolling. Fast scrolling
449    /// happens when a user holds the alt or option key while scrolling.
450    ///
451    /// Default: 4.0
452    pub fast_scroll_sensitivity: Option<f32>,
453    /// Whether the line numbers on editors gutter are relative or not.
454    ///
455    /// Default: false
456    pub relative_line_numbers: Option<bool>,
457    /// When to populate a new search's query based on the text under the cursor.
458    ///
459    /// Default: always
460    pub seed_search_query_from_cursor: Option<SeedQuerySetting>,
461    pub use_smartcase_search: Option<bool>,
462    /// Determines the modifier to be used to add multiple cursors with the mouse. The open hover link mouse gestures will adapt such that it do not conflict with the multicursor modifier.
463    ///
464    /// Default: alt
465    pub multi_cursor_modifier: Option<MultiCursorModifier>,
466    /// Hide the values of variables in `private` files, as defined by the
467    /// private_files setting. This only changes the visual representation,
468    /// the values are still present in the file and can be selected / copied / pasted
469    ///
470    /// Default: false
471    pub redact_private_values: Option<bool>,
472
473    /// How many lines to expand the multibuffer excerpts by default
474    ///
475    /// Default: 3
476    pub expand_excerpt_lines: Option<u32>,
477
478    /// Whether to enable middle-click paste on Linux
479    ///
480    /// Default: true
481    pub middle_click_paste: Option<bool>,
482
483    /// What to do when multibuffer is double clicked in some of its excerpts
484    /// (parts of singleton buffers).
485    ///
486    /// Default: select
487    pub double_click_in_multibuffer: Option<DoubleClickInMultibuffer>,
488    /// Whether the editor search results will loop
489    ///
490    /// Default: true
491    pub search_wrap: Option<bool>,
492
493    /// Defaults to use when opening a new buffer and project search items.
494    ///
495    /// Default: nothing is enabled
496    pub search: Option<SearchSettings>,
497
498    /// Whether to automatically show a signature help pop-up or not.
499    ///
500    /// Default: false
501    pub auto_signature_help: Option<bool>,
502
503    /// Whether to show the signature help pop-up after completions or bracket pairs inserted.
504    ///
505    /// Default: false
506    pub show_signature_help_after_edits: Option<bool>,
507
508    /// Whether to follow-up empty go to definition responses from the language server or not.
509    /// `FindAllReferences` allows to look up references of the same symbol instead.
510    /// `None` disables the fallback.
511    ///
512    /// Default: FindAllReferences
513    pub go_to_definition_fallback: Option<GoToDefinitionFallback>,
514
515    /// Jupyter REPL settings.
516    pub jupyter: Option<JupyterContent>,
517
518    /// Which level to use to filter out diagnostics displayed in the editor.
519    ///
520    /// Affects the editor rendering only, and does not interrupt
521    /// the functionality of diagnostics fetching and project diagnostics editor.
522    /// Which files containing diagnostic errors/warnings to mark in the tabs.
523    /// Diagnostics are only shown when file icons are also active.
524    ///
525    /// Shows all diagnostics if not specified.
526    ///
527    /// Default: warning
528    #[serde(default)]
529    pub diagnostics_max_severity: Option<DiagnosticSeverity>,
530
531    /// Whether to show code action button at start of buffer line.
532    ///
533    /// Default: true
534    pub inline_code_actions: Option<bool>,
535
536    /// Whether to allow drag and drop text selection in buffer.
537    ///
538    /// Default: true
539    pub drag_and_drop_selection: Option<bool>,
540
541    /// How to render LSP `textDocument/documentColor` colors in the editor.
542    ///
543    /// Default: [`DocumentColorsRenderMode::Inlay`]
544    pub lsp_document_colors: Option<DocumentColorsRenderMode>,
545}
546
547// Toolbar related settings
548#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
549pub struct ToolbarContent {
550    /// Whether to display breadcrumbs in the editor toolbar.
551    ///
552    /// Default: true
553    pub breadcrumbs: Option<bool>,
554    /// Whether to display quick action buttons in the editor toolbar.
555    ///
556    /// Default: true
557    pub quick_actions: Option<bool>,
558    /// Whether to show the selections menu in the editor toolbar.
559    ///
560    /// Default: true
561    pub selections_menu: Option<bool>,
562    /// Whether to display Agent review buttons in the editor toolbar.
563    /// Only applicable while reviewing a file edited by the Agent.
564    ///
565    /// Default: true
566    pub agent_review: Option<bool>,
567    /// Whether to display code action buttons in the editor toolbar.
568    ///
569    /// Default: false
570    pub code_actions: Option<bool>,
571}
572
573/// Scrollbar related settings
574#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Default)]
575pub struct ScrollbarContent {
576    /// When to show the scrollbar in the editor.
577    ///
578    /// Default: auto
579    pub show: Option<ShowScrollbar>,
580    /// Whether to show git diff indicators in the scrollbar.
581    ///
582    /// Default: true
583    pub git_diff: Option<bool>,
584    /// Whether to show buffer search result indicators in the scrollbar.
585    ///
586    /// Default: true
587    pub search_results: Option<bool>,
588    /// Whether to show selected text occurrences in the scrollbar.
589    ///
590    /// Default: true
591    pub selected_text: Option<bool>,
592    /// Whether to show selected symbol occurrences in the scrollbar.
593    ///
594    /// Default: true
595    pub selected_symbol: Option<bool>,
596    /// Which diagnostic indicators to show in the scrollbar:
597    ///
598    /// Default: all
599    pub diagnostics: Option<ScrollbarDiagnostics>,
600    /// Whether to show cursor positions in the scrollbar.
601    ///
602    /// Default: true
603    pub cursors: Option<bool>,
604    /// Forcefully enable or disable the scrollbar for each axis
605    pub axes: Option<ScrollbarAxesContent>,
606}
607
608/// Minimap related settings
609#[derive(Copy, Clone, Default, Debug, Serialize, Deserialize, JsonSchema, PartialEq)]
610pub struct MinimapContent {
611    /// When to show the minimap in the editor.
612    ///
613    /// Default: never
614    pub show: Option<ShowMinimap>,
615
616    /// Where to show the minimap in the editor.
617    ///
618    /// Default: [`DisplayIn::ActiveEditor`]
619    pub display_in: Option<DisplayIn>,
620
621    /// When to show the minimap thumb.
622    ///
623    /// Default: always
624    pub thumb: Option<MinimapThumb>,
625
626    /// Defines the border style for the minimap's scrollbar thumb.
627    ///
628    /// Default: left_open
629    pub thumb_border: Option<MinimapThumbBorder>,
630
631    /// How to highlight the current line in the minimap.
632    ///
633    /// Default: inherits editor line highlights setting
634    pub current_line_highlight: Option<Option<CurrentLineHighlight>>,
635}
636
637/// Forcefully enable or disable the scrollbar for each axis
638#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Default)]
639pub struct ScrollbarAxesContent {
640    /// When false, forcefully disables the horizontal scrollbar. Otherwise, obey other settings.
641    ///
642    /// Default: true
643    horizontal: Option<bool>,
644
645    /// When false, forcefully disables the vertical scrollbar. Otherwise, obey other settings.
646    ///
647    /// Default: true
648    vertical: Option<bool>,
649}
650
651/// Gutter related settings
652#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
653pub struct GutterContent {
654    /// Whether to show line numbers in the gutter.
655    ///
656    /// Default: true
657    pub line_numbers: Option<bool>,
658    /// Minimum number of characters to reserve space for in the gutter.
659    ///
660    /// Default: 4
661    pub min_line_number_digits: Option<usize>,
662    /// Whether to show runnable buttons in the gutter.
663    ///
664    /// Default: true
665    pub runnables: Option<bool>,
666    /// Whether to show breakpoints in the gutter.
667    ///
668    /// Default: true
669    pub breakpoints: Option<bool>,
670    /// Whether to show fold buttons in the gutter.
671    ///
672    /// Default: true
673    pub folds: Option<bool>,
674}
675
676impl EditorSettings {
677    pub fn jupyter_enabled(cx: &App) -> bool {
678        EditorSettings::get_global(cx).jupyter.enabled
679    }
680}
681
682impl Settings for EditorSettings {
683    const KEY: Option<&'static str> = None;
684
685    type FileContent = EditorSettingsContent;
686
687    fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> anyhow::Result<Self> {
688        sources.json_merge()
689    }
690
691    fn import_from_vscode(vscode: &VsCodeSettings, current: &mut Self::FileContent) {
692        vscode.enum_setting(
693            "editor.cursorBlinking",
694            &mut current.cursor_blink,
695            |s| match s {
696                "blink" | "phase" | "expand" | "smooth" => Some(true),
697                "solid" => Some(false),
698                _ => None,
699            },
700        );
701        vscode.enum_setting(
702            "editor.cursorStyle",
703            &mut current.cursor_shape,
704            |s| match s {
705                "block" => Some(CursorShape::Block),
706                "block-outline" => Some(CursorShape::Hollow),
707                "line" | "line-thin" => Some(CursorShape::Bar),
708                "underline" | "underline-thin" => Some(CursorShape::Underline),
709                _ => None,
710            },
711        );
712
713        vscode.enum_setting(
714            "editor.renderLineHighlight",
715            &mut current.current_line_highlight,
716            |s| match s {
717                "gutter" => Some(CurrentLineHighlight::Gutter),
718                "line" => Some(CurrentLineHighlight::Line),
719                "all" => Some(CurrentLineHighlight::All),
720                _ => None,
721            },
722        );
723
724        vscode.bool_setting(
725            "editor.selectionHighlight",
726            &mut current.selection_highlight,
727        );
728        vscode.bool_setting("editor.hover.enabled", &mut current.hover_popover_enabled);
729        vscode.u64_setting("editor.hover.delay", &mut current.hover_popover_delay);
730
731        let mut gutter = GutterContent::default();
732        vscode.enum_setting(
733            "editor.showFoldingControls",
734            &mut gutter.folds,
735            |s| match s {
736                "always" | "mouseover" => Some(true),
737                "never" => Some(false),
738                _ => None,
739            },
740        );
741        vscode.enum_setting(
742            "editor.lineNumbers",
743            &mut gutter.line_numbers,
744            |s| match s {
745                "on" | "relative" => Some(true),
746                "off" => Some(false),
747                _ => None,
748            },
749        );
750        if let Some(old_gutter) = current.gutter.as_mut() {
751            if gutter.folds.is_some() {
752                old_gutter.folds = gutter.folds
753            }
754            if gutter.line_numbers.is_some() {
755                old_gutter.line_numbers = gutter.line_numbers
756            }
757        } else {
758            if gutter != GutterContent::default() {
759                current.gutter = Some(gutter)
760            }
761        }
762        if let Some(b) = vscode.read_bool("editor.scrollBeyondLastLine") {
763            current.scroll_beyond_last_line = Some(if b {
764                ScrollBeyondLastLine::OnePage
765            } else {
766                ScrollBeyondLastLine::Off
767            })
768        }
769
770        let mut scrollbar_axes = ScrollbarAxesContent::default();
771        vscode.enum_setting(
772            "editor.scrollbar.horizontal",
773            &mut scrollbar_axes.horizontal,
774            |s| match s {
775                "auto" | "visible" => Some(true),
776                "hidden" => Some(false),
777                _ => None,
778            },
779        );
780        vscode.enum_setting(
781            "editor.scrollbar.vertical",
782            &mut scrollbar_axes.horizontal,
783            |s| match s {
784                "auto" | "visible" => Some(true),
785                "hidden" => Some(false),
786                _ => None,
787            },
788        );
789
790        if scrollbar_axes != ScrollbarAxesContent::default() {
791            let scrollbar_settings = current.scrollbar.get_or_insert_default();
792            let axes_settings = scrollbar_settings.axes.get_or_insert_default();
793
794            if let Some(vertical) = scrollbar_axes.vertical {
795                axes_settings.vertical = Some(vertical);
796            }
797            if let Some(horizontal) = scrollbar_axes.horizontal {
798                axes_settings.horizontal = Some(horizontal);
799            }
800        }
801
802        // TODO: check if this does the int->float conversion?
803        vscode.f32_setting(
804            "editor.cursorSurroundingLines",
805            &mut current.vertical_scroll_margin,
806        );
807        vscode.f32_setting(
808            "editor.mouseWheelScrollSensitivity",
809            &mut current.scroll_sensitivity,
810        );
811        vscode.f32_setting(
812            "editor.fastScrollSensitivity",
813            &mut current.fast_scroll_sensitivity,
814        );
815        if Some("relative") == vscode.read_string("editor.lineNumbers") {
816            current.relative_line_numbers = Some(true);
817        }
818
819        vscode.enum_setting(
820            "editor.find.seedSearchStringFromSelection",
821            &mut current.seed_search_query_from_cursor,
822            |s| match s {
823                "always" => Some(SeedQuerySetting::Always),
824                "selection" => Some(SeedQuerySetting::Selection),
825                "never" => Some(SeedQuerySetting::Never),
826                _ => None,
827            },
828        );
829        vscode.bool_setting("search.smartCase", &mut current.use_smartcase_search);
830        vscode.enum_setting(
831            "editor.multiCursorModifier",
832            &mut current.multi_cursor_modifier,
833            |s| match s {
834                "ctrlCmd" => Some(MultiCursorModifier::CmdOrCtrl),
835                "alt" => Some(MultiCursorModifier::Alt),
836                _ => None,
837            },
838        );
839
840        vscode.bool_setting(
841            "editor.parameterHints.enabled",
842            &mut current.auto_signature_help,
843        );
844        vscode.bool_setting(
845            "editor.parameterHints.enabled",
846            &mut current.show_signature_help_after_edits,
847        );
848
849        if let Some(use_ignored) = vscode.read_bool("search.useIgnoreFiles") {
850            let search = current.search.get_or_insert_default();
851            search.include_ignored = use_ignored;
852        }
853
854        let mut minimap = MinimapContent::default();
855        let minimap_enabled = vscode.read_bool("editor.minimap.enabled").unwrap_or(true);
856        let autohide = vscode.read_bool("editor.minimap.autohide");
857        if minimap_enabled {
858            if let Some(false) = autohide {
859                minimap.show = Some(ShowMinimap::Always);
860            } else {
861                minimap.show = Some(ShowMinimap::Auto);
862            }
863        } else {
864            minimap.show = Some(ShowMinimap::Never);
865        }
866
867        vscode.enum_setting(
868            "editor.minimap.showSlider",
869            &mut minimap.thumb,
870            |s| match s {
871                "always" => Some(MinimapThumb::Always),
872                "mouseover" => Some(MinimapThumb::Hover),
873                _ => None,
874            },
875        );
876
877        if minimap != MinimapContent::default() {
878            current.minimap = Some(minimap)
879        }
880    }
881}