editor_settings.rs

  1use core::num;
  2
  3use gpui::App;
  4use language::CursorShape;
  5use project::project_settings::DiagnosticSeverity;
  6pub use settings::{
  7    CodeLens, CompletionDetailAlignment, CurrentLineHighlight, DelayMs, DiffViewStyle, DisplayIn,
  8    DocumentColorsRenderMode, DoubleClickInMultibuffer, GoToDefinitionFallback, HideMouseMode,
  9    MinimapThumb, MinimapThumbBorder, MultiCursorModifier, ScrollBeyondLastLine,
 10    ScrollbarDiagnostics, SeedQuerySetting, ShowMinimap, SnippetSortOrder,
 11};
 12use settings::{RegisterSetting, RelativeLineNumbers, Settings};
 13use ui::scrollbars::ShowScrollbar;
 14
 15/// Imports from the VSCode settings at
 16/// https://code.visualstudio.com/docs/reference/default-settings
 17#[derive(Clone, RegisterSetting)]
 18pub struct EditorSettings {
 19    pub cursor_blink: bool,
 20    pub cursor_shape: Option<CursorShape>,
 21    pub current_line_highlight: CurrentLineHighlight,
 22    pub selection_highlight: bool,
 23    pub rounded_selection: bool,
 24    pub lsp_highlight_debounce: DelayMs,
 25    pub hover_popover_enabled: bool,
 26    pub hover_popover_delay: DelayMs,
 27    pub hover_popover_sticky: bool,
 28    pub hover_popover_hiding_delay: DelayMs,
 29    pub toolbar: Toolbar,
 30    pub scrollbar: Scrollbar,
 31    pub minimap: Minimap,
 32    pub gutter: Gutter,
 33    pub scroll_beyond_last_line: ScrollBeyondLastLine,
 34    pub vertical_scroll_margin: f64,
 35    pub autoscroll_on_clicks: bool,
 36    pub horizontal_scroll_margin: f32,
 37    pub scroll_sensitivity: f32,
 38    pub mouse_wheel_zoom: bool,
 39    pub fast_scroll_sensitivity: f32,
 40    pub sticky_scroll: StickyScroll,
 41    pub relative_line_numbers: RelativeLineNumbers,
 42    pub seed_search_query_from_cursor: SeedQuerySetting,
 43    pub use_smartcase_search: bool,
 44    pub multi_cursor_modifier: MultiCursorModifier,
 45    pub redact_private_values: bool,
 46    pub expand_excerpt_lines: u32,
 47    pub excerpt_context_lines: u32,
 48    pub middle_click_paste: bool,
 49    pub double_click_in_multibuffer: DoubleClickInMultibuffer,
 50    pub search_wrap: bool,
 51    pub search: SearchSettings,
 52    pub auto_signature_help: bool,
 53    pub show_signature_help_after_edits: bool,
 54    pub go_to_definition_fallback: GoToDefinitionFallback,
 55    pub jupyter: Jupyter,
 56    pub hide_mouse: Option<HideMouseMode>,
 57    pub snippet_sort_order: SnippetSortOrder,
 58    pub diagnostics_max_severity: Option<DiagnosticSeverity>,
 59    pub inline_code_actions: bool,
 60    pub drag_and_drop_selection: DragAndDropSelection,
 61    pub code_lens: CodeLens,
 62    pub lsp_document_colors: DocumentColorsRenderMode,
 63    pub minimum_contrast_for_highlights: f32,
 64    pub completion_menu_scrollbar: ShowScrollbar,
 65    pub completion_detail_alignment: CompletionDetailAlignment,
 66    pub diff_view_style: DiffViewStyle,
 67    pub minimum_split_diff_width: f32,
 68}
 69#[derive(Debug, Clone)]
 70pub struct Jupyter {
 71    /// Whether the Jupyter feature is enabled.
 72    ///
 73    /// Default: true
 74    pub enabled: bool,
 75}
 76
 77#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 78pub struct StickyScroll {
 79    pub enabled: bool,
 80}
 81
 82#[derive(Clone, Debug, PartialEq, Eq)]
 83pub struct Toolbar {
 84    pub breadcrumbs: bool,
 85    pub quick_actions: bool,
 86    pub selections_menu: bool,
 87    pub agent_review: bool,
 88    pub code_actions: bool,
 89}
 90
 91#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 92pub struct Scrollbar {
 93    pub show: ShowScrollbar,
 94    pub git_diff: bool,
 95    pub selected_text: bool,
 96    pub selected_symbol: bool,
 97    pub search_results: bool,
 98    pub diagnostics: ScrollbarDiagnostics,
 99    pub cursors: bool,
100    pub axes: ScrollbarAxes,
101}
102
103#[derive(Copy, Clone, Debug, PartialEq)]
104pub struct Minimap {
105    pub show: ShowMinimap,
106    pub display_in: DisplayIn,
107    pub thumb: MinimapThumb,
108    pub thumb_border: MinimapThumbBorder,
109    pub current_line_highlight: Option<CurrentLineHighlight>,
110    pub max_width_columns: num::NonZeroU32,
111}
112
113impl Minimap {
114    pub fn minimap_enabled(&self) -> bool {
115        self.show != ShowMinimap::Never
116    }
117
118    #[inline]
119    pub fn on_active_editor(&self) -> bool {
120        self.display_in == DisplayIn::ActiveEditor
121    }
122
123    pub fn with_show_override(self) -> Self {
124        Self {
125            show: ShowMinimap::Always,
126            ..self
127        }
128    }
129}
130
131#[derive(Copy, Clone, Debug, PartialEq, Eq)]
132pub struct Gutter {
133    pub min_line_number_digits: usize,
134    pub line_numbers: bool,
135    pub runnables: bool,
136    pub breakpoints: bool,
137    pub bookmarks: bool,
138    pub folds: bool,
139}
140
141/// Forcefully enable or disable the scrollbar for each axis
142#[derive(Copy, Clone, Debug, PartialEq, Eq)]
143pub struct ScrollbarAxes {
144    /// When false, forcefully disables the horizontal scrollbar. Otherwise, obey other settings.
145    ///
146    /// Default: true
147    pub horizontal: bool,
148
149    /// When false, forcefully disables the vertical scrollbar. Otherwise, obey other settings.
150    ///
151    /// Default: true
152    pub vertical: bool,
153}
154
155/// Whether to allow drag and drop text selection in buffer.
156#[derive(Copy, Clone, Default, Debug, PartialEq, Eq)]
157pub struct DragAndDropSelection {
158    /// When true, enables drag and drop text selection in buffer.
159    ///
160    /// Default: true
161    pub enabled: bool,
162
163    /// The delay in milliseconds that must elapse before drag and drop is allowed. Otherwise, a new text selection is created.
164    ///
165    /// Default: 300
166    pub delay: DelayMs,
167}
168
169/// Default options for buffer and project search items.
170#[derive(Copy, Clone, Default, Debug, PartialEq, Eq)]
171pub struct SearchSettings {
172    /// Whether to show the project search button in the status bar.
173    pub button: bool,
174    /// Whether to only match on whole words.
175    pub whole_word: bool,
176    /// Whether to match case sensitively.
177    pub case_sensitive: bool,
178    /// Whether to include gitignored files in search results.
179    pub include_ignored: bool,
180    /// Whether to interpret the search query as a regular expression.
181    pub regex: bool,
182    /// Whether to center the cursor on each search match when navigating.
183    pub center_on_match: bool,
184}
185
186impl EditorSettings {
187    pub fn jupyter_enabled(cx: &App) -> bool {
188        EditorSettings::get_global(cx).jupyter.enabled
189    }
190}
191
192impl Settings for EditorSettings {
193    fn from_settings(content: &settings::SettingsContent) -> Self {
194        let editor = content.editor.clone();
195        let scrollbar = editor.scrollbar.unwrap();
196        let minimap = editor.minimap.unwrap();
197        let gutter = editor.gutter.unwrap();
198        let axes = scrollbar.axes.unwrap();
199        let toolbar = editor.toolbar.unwrap();
200        let search = editor.search.unwrap();
201        let drag_and_drop_selection = editor.drag_and_drop_selection.unwrap();
202        let sticky_scroll = editor.sticky_scroll.unwrap();
203        Self {
204            cursor_blink: editor.cursor_blink.unwrap(),
205            cursor_shape: editor.cursor_shape.map(Into::into),
206            current_line_highlight: editor.current_line_highlight.unwrap(),
207            selection_highlight: editor.selection_highlight.unwrap(),
208            rounded_selection: editor.rounded_selection.unwrap(),
209            lsp_highlight_debounce: editor.lsp_highlight_debounce.unwrap(),
210            hover_popover_enabled: editor.hover_popover_enabled.unwrap(),
211            hover_popover_delay: editor.hover_popover_delay.unwrap(),
212            hover_popover_sticky: editor.hover_popover_sticky.unwrap(),
213            hover_popover_hiding_delay: editor.hover_popover_hiding_delay.unwrap(),
214            toolbar: Toolbar {
215                breadcrumbs: toolbar.breadcrumbs.unwrap(),
216                quick_actions: toolbar.quick_actions.unwrap(),
217                selections_menu: toolbar.selections_menu.unwrap(),
218                agent_review: toolbar.agent_review.unwrap(),
219                code_actions: toolbar.code_actions.unwrap(),
220            },
221            scrollbar: Scrollbar {
222                show: scrollbar.show.map(ui_scrollbar_settings_from_raw).unwrap(),
223                git_diff: scrollbar.git_diff.unwrap()
224                    && content
225                        .git
226                        .as_ref()
227                        .unwrap()
228                        .enabled
229                        .unwrap()
230                        .is_git_diff_enabled(),
231                selected_text: scrollbar.selected_text.unwrap(),
232                selected_symbol: scrollbar.selected_symbol.unwrap(),
233                search_results: scrollbar.search_results.unwrap(),
234                diagnostics: scrollbar.diagnostics.unwrap(),
235                cursors: scrollbar.cursors.unwrap(),
236                axes: ScrollbarAxes {
237                    horizontal: axes.horizontal.unwrap(),
238                    vertical: axes.vertical.unwrap(),
239                },
240            },
241            minimap: Minimap {
242                show: minimap.show.unwrap(),
243                display_in: minimap.display_in.unwrap(),
244                thumb: minimap.thumb.unwrap(),
245                thumb_border: minimap.thumb_border.unwrap(),
246                current_line_highlight: minimap.current_line_highlight,
247                max_width_columns: minimap.max_width_columns.unwrap(),
248            },
249            gutter: Gutter {
250                min_line_number_digits: gutter.min_line_number_digits.unwrap(),
251                line_numbers: gutter.line_numbers.unwrap(),
252                runnables: gutter.runnables.unwrap(),
253                bookmarks: gutter.bookmarks.unwrap(),
254                breakpoints: gutter.breakpoints.unwrap(),
255                folds: gutter.folds.unwrap(),
256            },
257            scroll_beyond_last_line: editor.scroll_beyond_last_line.unwrap(),
258            vertical_scroll_margin: editor.vertical_scroll_margin.unwrap() as f64,
259            autoscroll_on_clicks: editor.autoscroll_on_clicks.unwrap(),
260            horizontal_scroll_margin: editor.horizontal_scroll_margin.unwrap(),
261            scroll_sensitivity: editor.scroll_sensitivity.unwrap(),
262            mouse_wheel_zoom: editor.mouse_wheel_zoom.unwrap(),
263            fast_scroll_sensitivity: editor.fast_scroll_sensitivity.unwrap(),
264            sticky_scroll: StickyScroll {
265                enabled: sticky_scroll.enabled.unwrap(),
266            },
267            relative_line_numbers: editor.relative_line_numbers.unwrap(),
268            seed_search_query_from_cursor: editor.seed_search_query_from_cursor.unwrap(),
269            use_smartcase_search: editor.use_smartcase_search.unwrap(),
270            multi_cursor_modifier: editor.multi_cursor_modifier.unwrap(),
271            redact_private_values: editor.redact_private_values.unwrap(),
272            expand_excerpt_lines: editor.expand_excerpt_lines.unwrap(),
273            excerpt_context_lines: editor.excerpt_context_lines.unwrap(),
274            middle_click_paste: editor.middle_click_paste.unwrap(),
275            double_click_in_multibuffer: editor.double_click_in_multibuffer.unwrap(),
276            search_wrap: editor.search_wrap.unwrap(),
277            search: SearchSettings {
278                button: search.button.unwrap(),
279                whole_word: search.whole_word.unwrap(),
280                case_sensitive: search.case_sensitive.unwrap(),
281                include_ignored: search.include_ignored.unwrap(),
282                regex: search.regex.unwrap(),
283                center_on_match: search.center_on_match.unwrap(),
284            },
285            auto_signature_help: editor.auto_signature_help.unwrap(),
286            show_signature_help_after_edits: editor.show_signature_help_after_edits.unwrap(),
287            go_to_definition_fallback: editor.go_to_definition_fallback.unwrap(),
288            jupyter: Jupyter {
289                enabled: editor.jupyter.unwrap().enabled.unwrap(),
290            },
291            hide_mouse: editor.hide_mouse,
292            snippet_sort_order: editor.snippet_sort_order.unwrap(),
293            diagnostics_max_severity: editor.diagnostics_max_severity.map(Into::into),
294            inline_code_actions: editor.inline_code_actions.unwrap(),
295            drag_and_drop_selection: DragAndDropSelection {
296                enabled: drag_and_drop_selection.enabled.unwrap(),
297                delay: drag_and_drop_selection.delay.unwrap(),
298            },
299            code_lens: editor.code_lens.unwrap(),
300            lsp_document_colors: editor.lsp_document_colors.unwrap(),
301            minimum_contrast_for_highlights: editor.minimum_contrast_for_highlights.unwrap().0,
302            completion_menu_scrollbar: editor
303                .completion_menu_scrollbar
304                .map(ui_scrollbar_settings_from_raw)
305                .unwrap(),
306            completion_detail_alignment: editor.completion_detail_alignment.unwrap(),
307            diff_view_style: editor.diff_view_style.unwrap(),
308            minimum_split_diff_width: editor.minimum_split_diff_width.unwrap(),
309        }
310    }
311}
312
313#[derive(Default)]
314pub struct EditorSettingsScrollbarProxy;
315
316impl ui::scrollbars::ScrollbarVisibility for EditorSettingsScrollbarProxy {
317    fn visibility(&self, cx: &App) -> ShowScrollbar {
318        EditorSettings::get_global(cx).scrollbar.show
319    }
320}
321
322pub fn ui_scrollbar_settings_from_raw(
323    value: settings::ShowScrollbar,
324) -> ui::scrollbars::ShowScrollbar {
325    match value {
326        settings::ShowScrollbar::Auto => ShowScrollbar::Auto,
327        settings::ShowScrollbar::System => ShowScrollbar::System,
328        settings::ShowScrollbar::Always => ShowScrollbar::Always,
329        settings::ShowScrollbar::Never => ShowScrollbar::Never,
330    }
331}