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