1mod agent;
2mod editor;
3mod extension;
4mod fallible_options;
5mod language;
6mod language_model;
7pub mod merge_from;
8mod project;
9mod serde_helper;
10mod terminal;
11mod theme;
12mod workspace;
13
14pub use agent::*;
15pub use editor::*;
16pub use extension::*;
17pub use fallible_options::*;
18pub use language::*;
19pub use language_model::*;
20pub use merge_from::MergeFrom as MergeFromTrait;
21pub use project::*;
22use serde::de::DeserializeOwned;
23pub use serde_helper::{
24 serialize_f32_with_two_decimal_places, serialize_optional_f32_with_two_decimal_places,
25};
26use settings_json::parse_json_with_comments;
27pub use terminal::*;
28pub use theme::*;
29pub use workspace::*;
30
31use collections::{HashMap, IndexMap};
32use schemars::JsonSchema;
33use serde::{Deserialize, Serialize};
34use settings_macros::{MergeFrom, with_fallible_options};
35use std::collections::BTreeSet;
36use std::sync::Arc;
37pub use util::serde::default_true;
38
39#[derive(Debug, Clone, PartialEq, Eq)]
40pub enum ParseStatus {
41 /// Settings were parsed successfully
42 Success,
43 /// Settings failed to parse
44 Failed { error: String },
45}
46
47#[with_fallible_options]
48#[derive(Debug, PartialEq, Default, Clone, Serialize, Deserialize, JsonSchema, MergeFrom)]
49pub struct SettingsContent {
50 #[serde(flatten)]
51 pub project: ProjectSettingsContent,
52
53 #[serde(flatten)]
54 pub theme: Box<ThemeSettingsContent>,
55
56 #[serde(flatten)]
57 pub extension: ExtensionSettingsContent,
58
59 #[serde(flatten)]
60 pub workspace: WorkspaceSettingsContent,
61
62 #[serde(flatten)]
63 pub editor: EditorSettingsContent,
64
65 #[serde(flatten)]
66 pub remote: RemoteSettingsContent,
67
68 /// Settings related to the file finder.
69 pub file_finder: Option<FileFinderSettingsContent>,
70
71 pub git_panel: Option<GitPanelSettingsContent>,
72
73 pub tabs: Option<ItemSettingsContent>,
74 pub tab_bar: Option<TabBarSettingsContent>,
75 pub status_bar: Option<StatusBarSettingsContent>,
76
77 pub preview_tabs: Option<PreviewTabsSettingsContent>,
78
79 pub agent: Option<AgentSettingsContent>,
80 pub agent_servers: Option<AllAgentServersSettings>,
81
82 /// Configuration of audio in Zed.
83 pub audio: Option<AudioSettingsContent>,
84
85 /// Whether or not to automatically check for updates.
86 ///
87 /// Default: true
88 pub auto_update: Option<bool>,
89
90 /// This base keymap settings adjusts the default keybindings in Zed to be similar
91 /// to other common code editors. By default, Zed's keymap closely follows VSCode's
92 /// keymap, with minor adjustments, this corresponds to the "VSCode" setting.
93 ///
94 /// Default: VSCode
95 pub base_keymap: Option<BaseKeymapContent>,
96
97 /// Configuration for the collab panel visual settings.
98 pub collaboration_panel: Option<PanelSettingsContent>,
99
100 pub debugger: Option<DebuggerSettingsContent>,
101
102 /// Configuration for Diagnostics-related features.
103 pub diagnostics: Option<DiagnosticsSettingsContent>,
104
105 /// Configuration for Git-related features
106 pub git: Option<GitSettings>,
107
108 /// Common language server settings.
109 pub global_lsp_settings: Option<GlobalLspSettingsContent>,
110
111 /// The settings for the image viewer.
112 pub image_viewer: Option<ImageViewerSettingsContent>,
113
114 pub repl: Option<ReplSettingsContent>,
115
116 /// Whether or not to enable Helix mode.
117 ///
118 /// Default: false
119 pub helix_mode: Option<bool>,
120
121 pub journal: Option<JournalSettingsContent>,
122
123 /// A map of log scopes to the desired log level.
124 /// Useful for filtering out noisy logs or enabling more verbose logging.
125 ///
126 /// Example: {"log": {"client": "warn"}}
127 pub log: Option<HashMap<String, String>>,
128
129 pub line_indicator_format: Option<LineIndicatorFormat>,
130
131 pub language_models: Option<AllLanguageModelSettingsContent>,
132
133 pub outline_panel: Option<OutlinePanelSettingsContent>,
134
135 pub project_panel: Option<ProjectPanelSettingsContent>,
136
137 /// Configuration for the Message Editor
138 pub message_editor: Option<MessageEditorSettings>,
139
140 /// Configuration for Node-related features
141 pub node: Option<NodeBinarySettings>,
142
143 /// Configuration for the Notification Panel
144 pub notification_panel: Option<NotificationPanelSettingsContent>,
145
146 pub proxy: Option<String>,
147
148 /// The URL of the Zed server to connect to.
149 pub server_url: Option<String>,
150
151 /// Configuration for session-related features
152 pub session: Option<SessionSettingsContent>,
153 /// Control what info is collected by Zed.
154 pub telemetry: Option<TelemetrySettingsContent>,
155
156 /// Configuration of the terminal in Zed.
157 pub terminal: Option<TerminalSettingsContent>,
158
159 pub title_bar: Option<TitleBarSettingsContent>,
160
161 /// Whether or not to enable Vim mode.
162 ///
163 /// Default: false
164 pub vim_mode: Option<bool>,
165
166 // Settings related to calls in Zed
167 pub calls: Option<CallSettingsContent>,
168
169 /// Whether to disable all AI features in Zed.
170 ///
171 /// Default: false
172 pub disable_ai: Option<SaturatingBool>,
173
174 /// Settings for the which-key popup.
175 pub which_key: Option<WhichKeySettingsContent>,
176
177 /// Settings related to Vim mode in Zed.
178 pub vim: Option<VimSettingsContent>,
179}
180
181impl SettingsContent {
182 pub fn languages_mut(&mut self) -> &mut HashMap<String, LanguageSettingsContent> {
183 &mut self.project.all_languages.languages.0
184 }
185}
186
187// These impls are there to optimize builds by avoiding monomorphization downstream. Yes, they're repetitive, but using default impls
188// break the optimization, for whatever reason.
189pub trait RootUserSettings: Sized + DeserializeOwned {
190 fn parse_json(json: &str) -> (Option<Self>, ParseStatus);
191 fn parse_json_with_comments(json: &str) -> anyhow::Result<Self>;
192}
193
194impl RootUserSettings for SettingsContent {
195 fn parse_json(json: &str) -> (Option<Self>, ParseStatus) {
196 fallible_options::parse_json(json)
197 }
198 fn parse_json_with_comments(json: &str) -> anyhow::Result<Self> {
199 parse_json_with_comments(json)
200 }
201}
202// Explicit opt-in instead of blanket impl to avoid monomorphizing downstream. Just a hunch though.
203impl RootUserSettings for Option<SettingsContent> {
204 fn parse_json(json: &str) -> (Option<Self>, ParseStatus) {
205 fallible_options::parse_json(json)
206 }
207 fn parse_json_with_comments(json: &str) -> anyhow::Result<Self> {
208 parse_json_with_comments(json)
209 }
210}
211impl RootUserSettings for UserSettingsContent {
212 fn parse_json(json: &str) -> (Option<Self>, ParseStatus) {
213 fallible_options::parse_json(json)
214 }
215 fn parse_json_with_comments(json: &str) -> anyhow::Result<Self> {
216 parse_json_with_comments(json)
217 }
218}
219
220#[with_fallible_options]
221#[derive(Debug, Default, PartialEq, Clone, Serialize, Deserialize, JsonSchema, MergeFrom)]
222pub struct UserSettingsContent {
223 #[serde(flatten)]
224 pub content: Box<SettingsContent>,
225
226 pub dev: Option<Box<SettingsContent>>,
227 pub nightly: Option<Box<SettingsContent>>,
228 pub preview: Option<Box<SettingsContent>>,
229 pub stable: Option<Box<SettingsContent>>,
230
231 pub macos: Option<Box<SettingsContent>>,
232 pub windows: Option<Box<SettingsContent>>,
233 pub linux: Option<Box<SettingsContent>>,
234
235 #[serde(default)]
236 pub profiles: IndexMap<String, SettingsContent>,
237}
238
239pub struct ExtensionsSettingsContent {
240 pub all_languages: AllLanguageSettingsContent,
241}
242
243/// Base key bindings scheme. Base keymaps can be overridden with user keymaps.
244///
245/// Default: VSCode
246#[derive(
247 Copy,
248 Clone,
249 Debug,
250 Serialize,
251 Deserialize,
252 JsonSchema,
253 MergeFrom,
254 PartialEq,
255 Eq,
256 Default,
257 strum::VariantArray,
258)]
259pub enum BaseKeymapContent {
260 #[default]
261 VSCode,
262 JetBrains,
263 SublimeText,
264 Atom,
265 TextMate,
266 Emacs,
267 Cursor,
268 None,
269}
270
271impl strum::VariantNames for BaseKeymapContent {
272 const VARIANTS: &'static [&'static str] = &[
273 "VSCode",
274 "JetBrains",
275 "Sublime Text",
276 "Atom",
277 "TextMate",
278 "Emacs",
279 "Cursor",
280 "None",
281 ];
282}
283
284#[with_fallible_options]
285#[derive(Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)]
286pub struct TitleBarSettingsContent {
287 /// Whether to show the branch icon beside branch switcher in the title bar.
288 ///
289 /// Default: false
290 pub show_branch_icon: Option<bool>,
291 /// Whether to show onboarding banners in the title bar.
292 ///
293 /// Default: true
294 pub show_onboarding_banner: Option<bool>,
295 /// Whether to show user avatar in the title bar.
296 ///
297 /// Default: true
298 pub show_user_picture: Option<bool>,
299 /// Whether to show the branch name button in the titlebar.
300 ///
301 /// Default: true
302 pub show_branch_name: Option<bool>,
303 /// Whether to show the project host and name in the titlebar.
304 ///
305 /// Default: true
306 pub show_project_items: Option<bool>,
307 /// Whether to show the sign in button in the title bar.
308 ///
309 /// Default: true
310 pub show_sign_in: Option<bool>,
311 /// Whether to show the user menu button in the title bar.
312 ///
313 /// Default: true
314 pub show_user_menu: Option<bool>,
315 /// Whether to show the menus in the title bar.
316 ///
317 /// Default: false
318 pub show_menus: Option<bool>,
319}
320
321/// Configuration of audio in Zed.
322#[with_fallible_options]
323#[derive(Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)]
324pub struct AudioSettingsContent {
325 /// Opt into the new audio system.
326 ///
327 /// You need to rejoin a call for this setting to apply
328 #[serde(rename = "experimental.rodio_audio")]
329 pub rodio_audio: Option<bool>, // default is false
330 /// Requires 'rodio_audio: true'
331 ///
332 /// Automatically increase or decrease you microphone's volume. This affects how
333 /// loud you sound to others.
334 ///
335 /// Recommended: off (default)
336 /// Microphones are too quite in zed, until everyone is on experimental
337 /// audio and has auto speaker volume on this will make you very loud
338 /// compared to other speakers.
339 #[serde(rename = "experimental.auto_microphone_volume")]
340 pub auto_microphone_volume: Option<bool>,
341 /// Requires 'rodio_audio: true'
342 ///
343 /// Automatically increate or decrease the volume of other call members.
344 /// This only affects how things sound for you.
345 #[serde(rename = "experimental.auto_speaker_volume")]
346 pub auto_speaker_volume: Option<bool>,
347 /// Requires 'rodio_audio: true'
348 ///
349 /// Remove background noises. Works great for typing, cars, dogs, AC. Does
350 /// not work well on music.
351 #[serde(rename = "experimental.denoise")]
352 pub denoise: Option<bool>,
353 /// Requires 'rodio_audio: true'
354 ///
355 /// Use audio parameters compatible with the previous versions of
356 /// experimental audio and non-experimental audio. When this is false you
357 /// will sound strange to anyone not on the latest experimental audio. In
358 /// the future we will migrate by setting this to false
359 ///
360 /// You need to rejoin a call for this setting to apply
361 #[serde(rename = "experimental.legacy_audio_compatible")]
362 pub legacy_audio_compatible: Option<bool>,
363}
364
365/// Control what info is collected by Zed.
366#[with_fallible_options]
367#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, Debug, MergeFrom)]
368pub struct TelemetrySettingsContent {
369 /// Send debug info like crash reports.
370 ///
371 /// Default: true
372 pub diagnostics: Option<bool>,
373 /// Send anonymized usage data like what languages you're using Zed with.
374 ///
375 /// Default: true
376 pub metrics: Option<bool>,
377}
378
379impl Default for TelemetrySettingsContent {
380 fn default() -> Self {
381 Self {
382 diagnostics: Some(true),
383 metrics: Some(true),
384 }
385 }
386}
387
388#[with_fallible_options]
389#[derive(Default, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema, Clone, MergeFrom)]
390pub struct DebuggerSettingsContent {
391 /// Determines the stepping granularity.
392 ///
393 /// Default: line
394 pub stepping_granularity: Option<SteppingGranularity>,
395 /// Whether the breakpoints should be reused across Zed sessions.
396 ///
397 /// Default: true
398 pub save_breakpoints: Option<bool>,
399 /// Whether to show the debug button in the status bar.
400 ///
401 /// Default: true
402 pub button: Option<bool>,
403 /// Time in milliseconds until timeout error when connecting to a TCP debug adapter
404 ///
405 /// Default: 2000ms
406 pub timeout: Option<u64>,
407 /// Whether to log messages between active debug adapters and Zed
408 ///
409 /// Default: true
410 pub log_dap_communications: Option<bool>,
411 /// Whether to format dap messages in when adding them to debug adapter logger
412 ///
413 /// Default: true
414 pub format_dap_log_messages: Option<bool>,
415 /// The dock position of the debug panel
416 ///
417 /// Default: Bottom
418 pub dock: Option<DockPosition>,
419}
420
421/// The granularity of one 'step' in the stepping requests `next`, `stepIn`, `stepOut`, and `stepBack`.
422#[derive(
423 PartialEq,
424 Eq,
425 Debug,
426 Hash,
427 Clone,
428 Copy,
429 Deserialize,
430 Serialize,
431 JsonSchema,
432 MergeFrom,
433 strum::VariantArray,
434 strum::VariantNames,
435)]
436#[serde(rename_all = "snake_case")]
437pub enum SteppingGranularity {
438 /// The step should allow the program to run until the current statement has finished executing.
439 /// The meaning of a statement is determined by the adapter and it may be considered equivalent to a line.
440 /// For example 'for(int i = 0; i < 10; i++)' could be considered to have 3 statements 'int i = 0', 'i < 10', and 'i++'.
441 Statement,
442 /// The step should allow the program to run until the current source line has executed.
443 Line,
444 /// The step should allow one instruction to execute (e.g. one x86 instruction).
445 Instruction,
446}
447
448#[derive(
449 Copy,
450 Clone,
451 Debug,
452 Serialize,
453 Deserialize,
454 JsonSchema,
455 MergeFrom,
456 PartialEq,
457 Eq,
458 strum::VariantArray,
459 strum::VariantNames,
460)]
461#[serde(rename_all = "snake_case")]
462pub enum DockPosition {
463 Left,
464 Bottom,
465 Right,
466}
467
468/// Settings for slash commands.
469#[with_fallible_options]
470#[derive(Deserialize, Serialize, Debug, Default, Clone, JsonSchema, MergeFrom, PartialEq, Eq)]
471pub struct SlashCommandSettings {
472 /// Settings for the `/cargo-workspace` slash command.
473 pub cargo_workspace: Option<CargoWorkspaceCommandSettings>,
474}
475
476/// Settings for the `/cargo-workspace` slash command.
477#[with_fallible_options]
478#[derive(Deserialize, Serialize, Debug, Default, Clone, JsonSchema, MergeFrom, PartialEq, Eq)]
479pub struct CargoWorkspaceCommandSettings {
480 /// Whether `/cargo-workspace` is enabled.
481 pub enabled: Option<bool>,
482}
483
484/// Configuration of voice calls in Zed.
485#[with_fallible_options]
486#[derive(Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)]
487pub struct CallSettingsContent {
488 /// Whether the microphone should be muted when joining a channel or a call.
489 ///
490 /// Default: false
491 pub mute_on_join: Option<bool>,
492
493 /// Whether your current project should be shared when joining an empty channel.
494 ///
495 /// Default: false
496 pub share_on_join: Option<bool>,
497}
498
499#[with_fallible_options]
500#[derive(Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)]
501pub struct GitPanelSettingsContent {
502 /// Whether to show the panel button in the status bar.
503 ///
504 /// Default: true
505 pub button: Option<bool>,
506 /// Where to dock the panel.
507 ///
508 /// Default: left
509 pub dock: Option<DockPosition>,
510 /// Default width of the panel in pixels.
511 ///
512 /// Default: 360
513 #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
514 pub default_width: Option<f32>,
515 /// How entry statuses are displayed.
516 ///
517 /// Default: icon
518 pub status_style: Option<StatusStyle>,
519 /// How and when the scrollbar should be displayed.
520 ///
521 /// Default: inherits editor scrollbar settings
522 pub scrollbar: Option<ScrollbarSettings>,
523
524 /// What the default branch name should be when
525 /// `init.defaultBranch` is not set in git
526 ///
527 /// Default: main
528 pub fallback_branch_name: Option<String>,
529
530 /// Whether to sort entries in the panel by path
531 /// or by status (the default).
532 ///
533 /// Default: false
534 pub sort_by_path: Option<bool>,
535
536 /// Whether to collapse untracked files in the diff panel.
537 ///
538 /// Default: false
539 pub collapse_untracked_diff: Option<bool>,
540
541 /// Whether to show entries with tree or flat view in the panel
542 ///
543 /// Default: false
544 pub tree_view: Option<bool>,
545}
546
547#[derive(
548 Default,
549 Copy,
550 Clone,
551 Debug,
552 Serialize,
553 Deserialize,
554 JsonSchema,
555 MergeFrom,
556 PartialEq,
557 Eq,
558 strum::VariantArray,
559 strum::VariantNames,
560)]
561#[serde(rename_all = "snake_case")]
562pub enum StatusStyle {
563 #[default]
564 Icon,
565 LabelColor,
566}
567
568#[with_fallible_options]
569#[derive(
570 Copy, Clone, Default, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq,
571)]
572pub struct ScrollbarSettings {
573 pub show: Option<ShowScrollbar>,
574}
575
576#[with_fallible_options]
577#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq)]
578pub struct NotificationPanelSettingsContent {
579 /// Whether to show the panel button in the status bar.
580 ///
581 /// Default: true
582 pub button: Option<bool>,
583 /// Where to dock the panel.
584 ///
585 /// Default: right
586 pub dock: Option<DockPosition>,
587 /// Default width of the panel in pixels.
588 ///
589 /// Default: 300
590 #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
591 pub default_width: Option<f32>,
592}
593
594#[with_fallible_options]
595#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq)]
596pub struct PanelSettingsContent {
597 /// Whether to show the panel button in the status bar.
598 ///
599 /// Default: true
600 pub button: Option<bool>,
601 /// Where to dock the panel.
602 ///
603 /// Default: left
604 pub dock: Option<DockPosition>,
605 /// Default width of the panel in pixels.
606 ///
607 /// Default: 240
608 #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
609 pub default_width: Option<f32>,
610}
611
612#[with_fallible_options]
613#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq)]
614pub struct MessageEditorSettings {
615 /// Whether to automatically replace emoji shortcodes with emoji characters.
616 /// For example: typing `:wave:` gets replaced with `👋`.
617 ///
618 /// Default: false
619 pub auto_replace_emoji_shortcode: Option<bool>,
620}
621
622#[with_fallible_options]
623#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq)]
624pub struct FileFinderSettingsContent {
625 /// Whether to show file icons in the file finder.
626 ///
627 /// Default: true
628 pub file_icons: Option<bool>,
629 /// Determines how much space the file finder can take up in relation to the available window width.
630 ///
631 /// Default: small
632 pub modal_max_width: Option<FileFinderWidthContent>,
633 /// Determines whether the file finder should skip focus for the active file in search results.
634 ///
635 /// Default: true
636 pub skip_focus_for_active_in_search: Option<bool>,
637 /// Determines whether to show the git status in the file finder
638 ///
639 /// Default: true
640 pub git_status: Option<bool>,
641 /// Whether to use gitignored files when searching.
642 /// Only the file Zed had indexed will be used, not necessary all the gitignored files.
643 ///
644 /// Default: Smart
645 pub include_ignored: Option<IncludeIgnoredContent>,
646}
647
648#[derive(
649 Debug,
650 PartialEq,
651 Eq,
652 Clone,
653 Copy,
654 Default,
655 Serialize,
656 Deserialize,
657 JsonSchema,
658 MergeFrom,
659 strum::VariantArray,
660 strum::VariantNames,
661)]
662#[serde(rename_all = "snake_case")]
663pub enum IncludeIgnoredContent {
664 /// Use all gitignored files
665 All,
666 /// Use only the files Zed had indexed
667 Indexed,
668 /// Be smart and search for ignored when called from a gitignored worktree
669 #[default]
670 Smart,
671}
672
673#[derive(
674 Debug,
675 PartialEq,
676 Eq,
677 Clone,
678 Copy,
679 Default,
680 Serialize,
681 Deserialize,
682 JsonSchema,
683 MergeFrom,
684 strum::VariantArray,
685 strum::VariantNames,
686)]
687#[serde(rename_all = "lowercase")]
688pub enum FileFinderWidthContent {
689 #[default]
690 Small,
691 Medium,
692 Large,
693 XLarge,
694 Full,
695}
696
697#[with_fallible_options]
698#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Debug, JsonSchema, MergeFrom)]
699pub struct VimSettingsContent {
700 pub default_mode: Option<ModeContent>,
701 pub toggle_relative_line_numbers: Option<bool>,
702 pub use_system_clipboard: Option<UseSystemClipboard>,
703 pub use_smartcase_find: Option<bool>,
704 /// When enabled, the `:substitute` command replaces all matches in a line
705 /// by default. The 'g' flag then toggles this behavior.,
706 pub gdefault: Option<bool>,
707 pub custom_digraphs: Option<HashMap<String, Arc<str>>>,
708 pub highlight_on_yank_duration: Option<u64>,
709 pub cursor_shape: Option<CursorShapeSettings>,
710}
711
712#[derive(
713 Copy,
714 Clone,
715 Default,
716 Serialize,
717 Deserialize,
718 JsonSchema,
719 MergeFrom,
720 PartialEq,
721 Debug,
722 strum::VariantArray,
723 strum::VariantNames,
724)]
725#[serde(rename_all = "snake_case")]
726pub enum ModeContent {
727 #[default]
728 Normal,
729 Insert,
730}
731
732/// Controls when to use system clipboard.
733#[derive(
734 Copy,
735 Clone,
736 Debug,
737 Serialize,
738 Deserialize,
739 PartialEq,
740 Eq,
741 JsonSchema,
742 MergeFrom,
743 strum::VariantArray,
744 strum::VariantNames,
745)]
746#[serde(rename_all = "snake_case")]
747pub enum UseSystemClipboard {
748 /// Don't use system clipboard.
749 Never,
750 /// Use system clipboard.
751 Always,
752 /// Use system clipboard for yank operations.
753 OnYank,
754}
755
756/// Cursor shape configuration for insert mode in Vim.
757#[derive(
758 Copy,
759 Clone,
760 Debug,
761 Serialize,
762 Deserialize,
763 PartialEq,
764 Eq,
765 JsonSchema,
766 MergeFrom,
767 strum::VariantArray,
768 strum::VariantNames,
769)]
770#[serde(rename_all = "snake_case")]
771pub enum VimInsertModeCursorShape {
772 /// Inherit cursor shape from the editor's base cursor_shape setting.
773 Inherit,
774 /// Vertical bar cursor.
775 Bar,
776 /// Block cursor that surrounds the character.
777 Block,
778 /// Underline cursor.
779 Underline,
780 /// Hollow box cursor.
781 Hollow,
782}
783
784/// The settings for cursor shape.
785#[with_fallible_options]
786#[derive(
787 Copy, Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom,
788)]
789pub struct CursorShapeSettings {
790 /// Cursor shape for the normal mode.
791 ///
792 /// Default: block
793 pub normal: Option<CursorShape>,
794 /// Cursor shape for the replace mode.
795 ///
796 /// Default: underline
797 pub replace: Option<CursorShape>,
798 /// Cursor shape for the visual mode.
799 ///
800 /// Default: block
801 pub visual: Option<CursorShape>,
802 /// Cursor shape for the insert mode.
803 ///
804 /// The default value follows the primary cursor_shape.
805 pub insert: Option<VimInsertModeCursorShape>,
806}
807
808/// Settings specific to journaling
809#[with_fallible_options]
810#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq)]
811pub struct JournalSettingsContent {
812 /// The path of the directory where journal entries are stored.
813 ///
814 /// Default: `~`
815 pub path: Option<String>,
816 /// What format to display the hours in.
817 ///
818 /// Default: hour12
819 pub hour_format: Option<HourFormat>,
820}
821
822#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq)]
823#[serde(rename_all = "snake_case")]
824pub enum HourFormat {
825 #[default]
826 Hour12,
827 Hour24,
828}
829
830#[with_fallible_options]
831#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq)]
832pub struct OutlinePanelSettingsContent {
833 /// Whether to show the outline panel button in the status bar.
834 ///
835 /// Default: true
836 pub button: Option<bool>,
837 /// Customize default width (in pixels) taken by outline panel
838 ///
839 /// Default: 240
840 #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
841 pub default_width: Option<f32>,
842 /// The position of outline panel
843 ///
844 /// Default: left
845 pub dock: Option<DockSide>,
846 /// Whether to show file icons in the outline panel.
847 ///
848 /// Default: true
849 pub file_icons: Option<bool>,
850 /// Whether to show folder icons or chevrons for directories in the outline panel.
851 ///
852 /// Default: true
853 pub folder_icons: Option<bool>,
854 /// Whether to show the git status in the outline panel.
855 ///
856 /// Default: true
857 pub git_status: Option<bool>,
858 /// Amount of indentation (in pixels) for nested items.
859 ///
860 /// Default: 20
861 #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
862 pub indent_size: Option<f32>,
863 /// Whether to reveal it in the outline panel automatically,
864 /// when a corresponding project entry becomes active.
865 /// Gitignored entries are never auto revealed.
866 ///
867 /// Default: true
868 pub auto_reveal_entries: Option<bool>,
869 /// Whether to fold directories automatically
870 /// when directory has only one directory inside.
871 ///
872 /// Default: true
873 pub auto_fold_dirs: Option<bool>,
874 /// Settings related to indent guides in the outline panel.
875 pub indent_guides: Option<IndentGuidesSettingsContent>,
876 /// Scrollbar-related settings
877 pub scrollbar: Option<ScrollbarSettingsContent>,
878 /// Default depth to expand outline items in the current file.
879 /// The default depth to which outline entries are expanded on reveal.
880 /// - Set to 0 to collapse all items that have children
881 /// - Set to 1 or higher to collapse items at that depth or deeper
882 ///
883 /// Default: 100
884 pub expand_outlines_with_depth: Option<usize>,
885}
886
887#[derive(
888 Clone,
889 Copy,
890 Debug,
891 PartialEq,
892 Eq,
893 Serialize,
894 Deserialize,
895 JsonSchema,
896 MergeFrom,
897 strum::VariantArray,
898 strum::VariantNames,
899)]
900#[serde(rename_all = "snake_case")]
901pub enum DockSide {
902 Left,
903 Right,
904}
905
906#[derive(
907 Copy,
908 Clone,
909 Debug,
910 PartialEq,
911 Eq,
912 Deserialize,
913 Serialize,
914 JsonSchema,
915 MergeFrom,
916 strum::VariantArray,
917 strum::VariantNames,
918)]
919#[serde(rename_all = "snake_case")]
920pub enum ShowIndentGuides {
921 Always,
922 Never,
923}
924
925#[with_fallible_options]
926#[derive(
927 Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq, Default,
928)]
929pub struct IndentGuidesSettingsContent {
930 /// When to show the scrollbar in the outline panel.
931 pub show: Option<ShowIndentGuides>,
932}
933
934#[derive(Clone, Copy, Default, PartialEq, Debug, JsonSchema, MergeFrom, Deserialize, Serialize)]
935#[serde(rename_all = "snake_case")]
936pub enum LineIndicatorFormat {
937 Short,
938 #[default]
939 Long,
940}
941
942/// The settings for the image viewer.
943#[with_fallible_options]
944#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, Default, PartialEq)]
945pub struct ImageViewerSettingsContent {
946 /// The unit to use for displaying image file sizes.
947 ///
948 /// Default: "binary"
949 pub unit: Option<ImageFileSizeUnit>,
950}
951
952#[with_fallible_options]
953#[derive(
954 Clone,
955 Copy,
956 Debug,
957 Serialize,
958 Deserialize,
959 JsonSchema,
960 MergeFrom,
961 Default,
962 PartialEq,
963 strum::VariantArray,
964 strum::VariantNames,
965)]
966#[serde(rename_all = "snake_case")]
967pub enum ImageFileSizeUnit {
968 /// Displays file size in binary units (e.g., KiB, MiB).
969 #[default]
970 Binary,
971 /// Displays file size in decimal units (e.g., KB, MB).
972 Decimal,
973}
974
975#[with_fallible_options]
976#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq)]
977pub struct RemoteSettingsContent {
978 pub ssh_connections: Option<Vec<SshConnection>>,
979 pub wsl_connections: Option<Vec<WslConnection>>,
980 pub dev_container_connections: Option<Vec<DevContainerConnection>>,
981 pub read_ssh_config: Option<bool>,
982 pub use_podman: Option<bool>,
983}
984
985#[with_fallible_options]
986#[derive(
987 Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom, Hash,
988)]
989pub struct DevContainerConnection {
990 pub name: String,
991 pub container_id: String,
992 pub use_podman: bool,
993}
994
995#[with_fallible_options]
996#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, JsonSchema, MergeFrom)]
997pub struct SshConnection {
998 pub host: String,
999 pub username: Option<String>,
1000 pub port: Option<u16>,
1001 #[serde(default)]
1002 pub args: Vec<String>,
1003 #[serde(default)]
1004 pub projects: collections::BTreeSet<RemoteProject>,
1005 /// Name to use for this server in UI.
1006 pub nickname: Option<String>,
1007 // By default Zed will download the binary to the host directly.
1008 // If this is set to true, Zed will download the binary to your local machine,
1009 // and then upload it over the SSH connection. Useful if your SSH server has
1010 // limited outbound internet access.
1011 pub upload_binary_over_ssh: Option<bool>,
1012
1013 pub port_forwards: Option<Vec<SshPortForwardOption>>,
1014 /// Timeout in seconds for SSH connection and downloading the remote server binary.
1015 /// Defaults to 10 seconds if not specified.
1016 pub connection_timeout: Option<u16>,
1017}
1018
1019#[derive(Clone, Default, Serialize, Deserialize, PartialEq, JsonSchema, MergeFrom, Debug)]
1020pub struct WslConnection {
1021 pub distro_name: String,
1022 pub user: Option<String>,
1023 #[serde(default)]
1024 pub projects: BTreeSet<RemoteProject>,
1025}
1026
1027#[with_fallible_options]
1028#[derive(
1029 Clone, Debug, Default, Serialize, PartialEq, Eq, PartialOrd, Ord, Deserialize, JsonSchema,
1030)]
1031pub struct RemoteProject {
1032 pub paths: Vec<String>,
1033}
1034
1035#[with_fallible_options]
1036#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize, JsonSchema, MergeFrom)]
1037pub struct SshPortForwardOption {
1038 pub local_host: Option<String>,
1039 pub local_port: u16,
1040 pub remote_host: Option<String>,
1041 pub remote_port: u16,
1042}
1043
1044/// Settings for configuring REPL display and behavior.
1045#[with_fallible_options]
1046#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)]
1047pub struct ReplSettingsContent {
1048 /// Maximum number of lines to keep in REPL's scrollback buffer.
1049 /// Clamped with [4, 256] range.
1050 ///
1051 /// Default: 32
1052 pub max_lines: Option<usize>,
1053 /// Maximum number of columns to keep in REPL's scrollback buffer.
1054 /// Clamped with [20, 512] range.
1055 ///
1056 /// Default: 128
1057 pub max_columns: Option<usize>,
1058 /// Whether to show small single-line outputs inline instead of in a block.
1059 ///
1060 /// Default: true
1061 pub inline_output: Option<bool>,
1062 /// Maximum number of characters for an output to be shown inline.
1063 /// Only applies when `inline_output` is true.
1064 ///
1065 /// Default: 50
1066 pub inline_output_max_length: Option<usize>,
1067}
1068
1069/// Settings for configuring the which-key popup behaviour.
1070#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)]
1071pub struct WhichKeySettingsContent {
1072 /// Whether to show the which-key popup when holding down key combinations
1073 ///
1074 /// Default: false
1075 pub enabled: Option<bool>,
1076 /// Delay in milliseconds before showing the which-key popup.
1077 ///
1078 /// Default: 700
1079 pub delay_ms: Option<u64>,
1080}
1081
1082#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
1083/// An ExtendingVec in the settings can only accumulate new values.
1084///
1085/// This is useful for things like private files where you only want
1086/// to allow new values to be added.
1087///
1088/// Consider using a HashMap<String, bool> instead of this type
1089/// (like auto_install_extensions) so that user settings files can both add
1090/// and remove values from the set.
1091pub struct ExtendingVec<T>(pub Vec<T>);
1092
1093impl<T> Into<Vec<T>> for ExtendingVec<T> {
1094 fn into(self) -> Vec<T> {
1095 self.0
1096 }
1097}
1098impl<T> From<Vec<T>> for ExtendingVec<T> {
1099 fn from(vec: Vec<T>) -> Self {
1100 ExtendingVec(vec)
1101 }
1102}
1103
1104impl<T: Clone> merge_from::MergeFrom for ExtendingVec<T> {
1105 fn merge_from(&mut self, other: &Self) {
1106 self.0.extend_from_slice(other.0.as_slice());
1107 }
1108}
1109
1110/// A SaturatingBool in the settings can only ever be set to true,
1111/// later attempts to set it to false will be ignored.
1112///
1113/// Used by `disable_ai`.
1114#[derive(Debug, Default, Copy, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
1115pub struct SaturatingBool(pub bool);
1116
1117impl From<bool> for SaturatingBool {
1118 fn from(value: bool) -> Self {
1119 SaturatingBool(value)
1120 }
1121}
1122
1123impl From<SaturatingBool> for bool {
1124 fn from(value: SaturatingBool) -> bool {
1125 value.0
1126 }
1127}
1128
1129impl merge_from::MergeFrom for SaturatingBool {
1130 fn merge_from(&mut self, other: &Self) {
1131 self.0 |= other.0
1132 }
1133}
1134
1135#[derive(
1136 Copy,
1137 Clone,
1138 Default,
1139 Debug,
1140 PartialEq,
1141 Eq,
1142 PartialOrd,
1143 Ord,
1144 Serialize,
1145 Deserialize,
1146 MergeFrom,
1147 JsonSchema,
1148 derive_more::FromStr,
1149)]
1150#[serde(transparent)]
1151pub struct DelayMs(pub u64);
1152
1153impl From<u64> for DelayMs {
1154 fn from(n: u64) -> Self {
1155 Self(n)
1156 }
1157}
1158
1159impl std::fmt::Display for DelayMs {
1160 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1161 write!(f, "{}ms", self.0)
1162 }
1163}