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