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