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