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