1use gpui::AppContext;
2use language::CursorShape;
3use schemars::JsonSchema;
4use serde::{Deserialize, Serialize};
5use settings::{Settings, SettingsSources};
6
7#[derive(Deserialize, Clone)]
8pub struct EditorSettings {
9 pub cursor_blink: bool,
10 pub cursor_shape: Option<CursorShape>,
11 pub current_line_highlight: CurrentLineHighlight,
12 pub hover_popover_enabled: bool,
13 pub toolbar: Toolbar,
14 pub scrollbar: Scrollbar,
15 pub gutter: Gutter,
16 pub scroll_beyond_last_line: ScrollBeyondLastLine,
17 pub vertical_scroll_margin: f32,
18 pub autoscroll_on_clicks: bool,
19 pub scroll_sensitivity: f32,
20 pub relative_line_numbers: bool,
21 pub seed_search_query_from_cursor: SeedQuerySetting,
22 pub use_smartcase_search: bool,
23 pub multi_cursor_modifier: MultiCursorModifier,
24 pub redact_private_values: bool,
25 pub expand_excerpt_lines: u32,
26 pub middle_click_paste: bool,
27 #[serde(default)]
28 pub double_click_in_multibuffer: DoubleClickInMultibuffer,
29 pub search_wrap: bool,
30 #[serde(default)]
31 pub search: SearchSettings,
32 pub auto_signature_help: bool,
33 pub show_signature_help_after_edits: bool,
34 pub jupyter: Jupyter,
35}
36
37#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
38#[serde(rename_all = "snake_case")]
39pub enum CurrentLineHighlight {
40 // Don't highlight the current line.
41 None,
42 // Highlight the gutter area.
43 Gutter,
44 // Highlight the editor area.
45 Line,
46 // Highlight the full line.
47 All,
48}
49
50/// When to populate a new search's query based on the text under the cursor.
51#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
52#[serde(rename_all = "snake_case")]
53pub enum SeedQuerySetting {
54 /// Always populate the search query with the word under the cursor.
55 Always,
56 /// Only populate the search query when there is text selected.
57 Selection,
58 /// Never populate the search query
59 Never,
60}
61
62/// What to do when multibuffer is double clicked in some of its excerpts (parts of singleton buffers).
63#[derive(Default, Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
64#[serde(rename_all = "snake_case")]
65pub enum DoubleClickInMultibuffer {
66 /// Behave as a regular buffer and select the whole word.
67 #[default]
68 Select,
69 /// Open the excerpt clicked as a new buffer in the new tab, if no `alt` modifier was pressed during double click.
70 /// Otherwise, behave as a regular buffer and select the whole word.
71 Open,
72}
73
74#[derive(Debug, Clone, Deserialize)]
75pub struct Jupyter {
76 /// Whether the Jupyter feature is enabled.
77 ///
78 /// Default: true
79 pub enabled: bool,
80}
81
82#[derive(Default, Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
83#[serde(rename_all = "snake_case")]
84pub struct JupyterContent {
85 /// Whether the Jupyter feature is enabled.
86 ///
87 /// Default: true
88 pub enabled: Option<bool>,
89}
90
91#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
92pub struct Toolbar {
93 pub breadcrumbs: bool,
94 pub quick_actions: bool,
95 pub selections_menu: bool,
96}
97
98#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
99pub struct Scrollbar {
100 pub show: ShowScrollbar,
101 pub git_diff: bool,
102 pub selected_symbol: bool,
103 pub search_results: bool,
104 pub diagnostics: bool,
105 pub cursors: bool,
106}
107
108#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
109pub struct Gutter {
110 pub line_numbers: bool,
111 pub code_actions: bool,
112 pub runnables: bool,
113 pub folds: bool,
114}
115
116/// When to show the scrollbar in the editor.
117///
118/// Default: auto
119#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
120#[serde(rename_all = "snake_case")]
121pub enum ShowScrollbar {
122 /// Show the scrollbar if there's important information or
123 /// follow the system's configured behavior.
124 Auto,
125 /// Match the system's configured behavior.
126 System,
127 /// Always show the scrollbar.
128 Always,
129 /// Never show the scrollbar.
130 Never,
131}
132
133/// The key to use for adding multiple cursors
134///
135/// Default: alt
136#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
137#[serde(rename_all = "snake_case")]
138pub enum MultiCursorModifier {
139 Alt,
140 #[serde(alias = "cmd", alias = "ctrl")]
141 CmdOrCtrl,
142}
143
144/// Whether the editor will scroll beyond the last line.
145///
146/// Default: one_page
147#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
148#[serde(rename_all = "snake_case")]
149pub enum ScrollBeyondLastLine {
150 /// The editor will not scroll beyond the last line.
151 Off,
152
153 /// The editor will scroll beyond the last line by one page.
154 OnePage,
155
156 /// The editor will scroll beyond the last line by the same number of lines as vertical_scroll_margin.
157 VerticalScrollMargin,
158}
159
160/// Default options for buffer and project search items.
161#[derive(Copy, Clone, Default, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
162pub struct SearchSettings {
163 #[serde(default)]
164 pub whole_word: bool,
165 #[serde(default)]
166 pub case_sensitive: bool,
167 #[serde(default)]
168 pub include_ignored: bool,
169 #[serde(default)]
170 pub regex: bool,
171}
172
173#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
174pub struct EditorSettingsContent {
175 /// Whether the cursor blinks in the editor.
176 ///
177 /// Default: true
178 pub cursor_blink: Option<bool>,
179 /// Cursor shape for the default editor.
180 /// Can be "bar", "block", "underline", or "hollow".
181 ///
182 /// Default: None
183 pub cursor_shape: Option<CursorShape>,
184 /// How to highlight the current line in the editor.
185 ///
186 /// Default: all
187 pub current_line_highlight: Option<CurrentLineHighlight>,
188 /// Whether to show the informational hover box when moving the mouse
189 /// over symbols in the editor.
190 ///
191 /// Default: true
192 pub hover_popover_enabled: Option<bool>,
193
194 /// Toolbar related settings
195 pub toolbar: Option<ToolbarContent>,
196 /// Scrollbar related settings
197 pub scrollbar: Option<ScrollbarContent>,
198 /// Gutter related settings
199 pub gutter: Option<GutterContent>,
200 /// Whether the editor will scroll beyond the last line.
201 ///
202 /// Default: one_page
203 pub scroll_beyond_last_line: Option<ScrollBeyondLastLine>,
204 /// The number of lines to keep above/below the cursor when auto-scrolling.
205 ///
206 /// Default: 3.
207 pub vertical_scroll_margin: Option<f32>,
208 /// Whether to scroll when clicking near the edge of the visible text area.
209 ///
210 /// Default: false
211 pub autoscroll_on_clicks: Option<bool>,
212 /// Scroll sensitivity multiplier. This multiplier is applied
213 /// to both the horizontal and vertical delta values while scrolling.
214 ///
215 /// Default: 1.0
216 pub scroll_sensitivity: Option<f32>,
217 /// Whether the line numbers on editors gutter are relative or not.
218 ///
219 /// Default: false
220 pub relative_line_numbers: Option<bool>,
221 /// When to populate a new search's query based on the text under the cursor.
222 ///
223 /// Default: always
224 pub seed_search_query_from_cursor: Option<SeedQuerySetting>,
225 pub use_smartcase_search: Option<bool>,
226 /// The key to use for adding multiple cursors
227 ///
228 /// Default: alt
229 pub multi_cursor_modifier: Option<MultiCursorModifier>,
230 /// Hide the values of variables in `private` files, as defined by the
231 /// private_files setting. This only changes the visual representation,
232 /// the values are still present in the file and can be selected / copied / pasted
233 ///
234 /// Default: false
235 pub redact_private_values: Option<bool>,
236
237 /// How many lines to expand the multibuffer excerpts by default
238 ///
239 /// Default: 3
240 pub expand_excerpt_lines: Option<u32>,
241
242 /// Whether to enable middle-click paste on Linux
243 ///
244 /// Default: true
245 pub middle_click_paste: Option<bool>,
246
247 /// What to do when multibuffer is double clicked in some of its excerpts
248 /// (parts of singleton buffers).
249 ///
250 /// Default: select
251 pub double_click_in_multibuffer: Option<DoubleClickInMultibuffer>,
252 /// Whether the editor search results will loop
253 ///
254 /// Default: true
255 pub search_wrap: Option<bool>,
256
257 /// Defaults to use when opening a new buffer and project search items.
258 ///
259 /// Default: nothing is enabled
260 pub search: Option<SearchSettings>,
261
262 /// Whether to automatically show a signature help pop-up or not.
263 ///
264 /// Default: false
265 pub auto_signature_help: Option<bool>,
266
267 /// Whether to show the signature help pop-up after completions or bracket pairs inserted.
268 ///
269 /// Default: false
270 pub show_signature_help_after_edits: Option<bool>,
271
272 /// Jupyter REPL settings.
273 pub jupyter: Option<JupyterContent>,
274}
275
276// Toolbar related settings
277#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
278pub struct ToolbarContent {
279 /// Whether to display breadcrumbs in the editor toolbar.
280 ///
281 /// Default: true
282 pub breadcrumbs: Option<bool>,
283 /// Whether to display quick action buttons in the editor toolbar.
284 ///
285 /// Default: true
286 pub quick_actions: Option<bool>,
287
288 /// Whether to show the selections menu in the editor toolbar
289 ///
290 /// Default: true
291 pub selections_menu: Option<bool>,
292}
293
294/// Scrollbar related settings
295#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq)]
296pub struct ScrollbarContent {
297 /// When to show the scrollbar in the editor.
298 ///
299 /// Default: auto
300 pub show: Option<ShowScrollbar>,
301 /// Whether to show git diff indicators in the scrollbar.
302 ///
303 /// Default: true
304 pub git_diff: Option<bool>,
305 /// Whether to show buffer search result indicators in the scrollbar.
306 ///
307 /// Default: true
308 pub search_results: Option<bool>,
309 /// Whether to show selected symbol occurrences in the scrollbar.
310 ///
311 /// Default: true
312 pub selected_symbol: Option<bool>,
313 /// Whether to show diagnostic indicators in the scrollbar.
314 ///
315 /// Default: true
316 pub diagnostics: Option<bool>,
317 /// Whether to show cursor positions in the scrollbar.
318 ///
319 /// Default: true
320 pub cursors: Option<bool>,
321}
322
323/// Gutter related settings
324#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
325pub struct GutterContent {
326 /// Whether to show line numbers in the gutter.
327 ///
328 /// Default: true
329 pub line_numbers: Option<bool>,
330 /// Whether to show code action buttons in the gutter.
331 ///
332 /// Default: true
333 pub code_actions: Option<bool>,
334 /// Whether to show runnable buttons in the gutter.
335 ///
336 /// Default: true
337 pub runnables: Option<bool>,
338 /// Whether to show fold buttons in the gutter.
339 ///
340 /// Default: true
341 pub folds: Option<bool>,
342}
343
344impl EditorSettings {
345 pub fn jupyter_enabled(cx: &AppContext) -> bool {
346 EditorSettings::get_global(cx).jupyter.enabled
347 }
348}
349
350impl Settings for EditorSettings {
351 const KEY: Option<&'static str> = None;
352
353 type FileContent = EditorSettingsContent;
354
355 fn load(
356 sources: SettingsSources<Self::FileContent>,
357 _: &mut AppContext,
358 ) -> anyhow::Result<Self> {
359 sources.json_merge()
360 }
361}