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