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