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 /// Automatically increase or decrease you microphone's volume. This affects how
326 /// loud you sound to others.
327 ///
328 /// Recommended: off (default)
329 /// Microphones are too quite in zed, until everyone is on experimental
330 /// audio and has auto speaker volume on this will make you very loud
331 /// compared to other speakers.
332 #[serde(rename = "experimental.auto_microphone_volume")]
333 pub auto_microphone_volume: Option<bool>,
334 /// Remove background noises. Works great for typing, cars, dogs, AC. Does
335 /// not work well on music.
336 /// Select specific output audio device.
337 #[serde(rename = "experimental.output_audio_device")]
338 pub output_audio_device: Option<AudioOutputDeviceName>,
339 /// Select specific input audio device.
340 #[serde(rename = "experimental.input_audio_device")]
341 pub input_audio_device: Option<AudioInputDeviceName>,
342}
343
344#[derive(Clone, Default, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq)]
345#[serde(transparent)]
346pub struct AudioOutputDeviceName(pub Option<String>);
347
348impl AsRef<Option<String>> for AudioInputDeviceName {
349 fn as_ref(&self) -> &Option<String> {
350 &self.0
351 }
352}
353
354impl From<Option<String>> for AudioInputDeviceName {
355 fn from(value: Option<String>) -> Self {
356 Self(value)
357 }
358}
359
360#[derive(Clone, Default, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq)]
361#[serde(transparent)]
362pub struct AudioInputDeviceName(pub Option<String>);
363
364impl AsRef<Option<String>> for AudioOutputDeviceName {
365 fn as_ref(&self) -> &Option<String> {
366 &self.0
367 }
368}
369
370impl From<Option<String>> for AudioOutputDeviceName {
371 fn from(value: Option<String>) -> Self {
372 Self(value)
373 }
374}
375
376/// Control what info is collected by Zed.
377#[with_fallible_options]
378#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, Debug, MergeFrom)]
379pub struct TelemetrySettingsContent {
380 /// Send debug info like crash reports.
381 ///
382 /// Default: true
383 pub diagnostics: Option<bool>,
384 /// Send anonymized usage data like what languages you're using Zed with.
385 ///
386 /// Default: true
387 pub metrics: Option<bool>,
388}
389
390impl Default for TelemetrySettingsContent {
391 fn default() -> Self {
392 Self {
393 diagnostics: Some(true),
394 metrics: Some(true),
395 }
396 }
397}
398
399#[with_fallible_options]
400#[derive(Default, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema, Clone, MergeFrom)]
401pub struct DebuggerSettingsContent {
402 /// Determines the stepping granularity.
403 ///
404 /// Default: line
405 pub stepping_granularity: Option<SteppingGranularity>,
406 /// Whether the breakpoints should be reused across Zed sessions.
407 ///
408 /// Default: true
409 pub save_breakpoints: Option<bool>,
410 /// Whether to show the debug button in the status bar.
411 ///
412 /// Default: true
413 pub button: Option<bool>,
414 /// Time in milliseconds until timeout error when connecting to a TCP debug adapter
415 ///
416 /// Default: 2000ms
417 pub timeout: Option<u64>,
418 /// Whether to log messages between active debug adapters and Zed
419 ///
420 /// Default: true
421 pub log_dap_communications: Option<bool>,
422 /// Whether to format dap messages in when adding them to debug adapter logger
423 ///
424 /// Default: true
425 pub format_dap_log_messages: Option<bool>,
426 /// The dock position of the debug panel
427 ///
428 /// Default: Bottom
429 pub dock: Option<DockPosition>,
430}
431
432/// The granularity of one 'step' in the stepping requests `next`, `stepIn`, `stepOut`, and `stepBack`.
433#[derive(
434 PartialEq,
435 Eq,
436 Debug,
437 Hash,
438 Clone,
439 Copy,
440 Deserialize,
441 Serialize,
442 JsonSchema,
443 MergeFrom,
444 strum::VariantArray,
445 strum::VariantNames,
446)]
447#[serde(rename_all = "snake_case")]
448pub enum SteppingGranularity {
449 /// The step should allow the program to run until the current statement has finished executing.
450 /// The meaning of a statement is determined by the adapter and it may be considered equivalent to a line.
451 /// For example 'for(int i = 0; i < 10; i++)' could be considered to have 3 statements 'int i = 0', 'i < 10', and 'i++'.
452 Statement,
453 /// The step should allow the program to run until the current source line has executed.
454 Line,
455 /// The step should allow one instruction to execute (e.g. one x86 instruction).
456 Instruction,
457}
458
459#[derive(
460 Copy,
461 Clone,
462 Debug,
463 Serialize,
464 Deserialize,
465 JsonSchema,
466 MergeFrom,
467 PartialEq,
468 Eq,
469 strum::VariantArray,
470 strum::VariantNames,
471)]
472#[serde(rename_all = "snake_case")]
473pub enum DockPosition {
474 Left,
475 Bottom,
476 Right,
477}
478
479/// Settings for slash commands.
480#[with_fallible_options]
481#[derive(Deserialize, Serialize, Debug, Default, Clone, JsonSchema, MergeFrom, PartialEq, Eq)]
482pub struct SlashCommandSettings {
483 /// Settings for the `/cargo-workspace` slash command.
484 pub cargo_workspace: Option<CargoWorkspaceCommandSettings>,
485}
486
487/// Settings for the `/cargo-workspace` slash command.
488#[with_fallible_options]
489#[derive(Deserialize, Serialize, Debug, Default, Clone, JsonSchema, MergeFrom, PartialEq, Eq)]
490pub struct CargoWorkspaceCommandSettings {
491 /// Whether `/cargo-workspace` is enabled.
492 pub enabled: Option<bool>,
493}
494
495/// Configuration of voice calls in Zed.
496#[with_fallible_options]
497#[derive(Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)]
498pub struct CallSettingsContent {
499 /// Whether the microphone should be muted when joining a channel or a call.
500 ///
501 /// Default: false
502 pub mute_on_join: Option<bool>,
503
504 /// Whether your current project should be shared when joining an empty channel.
505 ///
506 /// Default: false
507 pub share_on_join: Option<bool>,
508}
509
510#[with_fallible_options]
511#[derive(Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)]
512pub struct GitPanelSettingsContent {
513 /// Whether to show the panel button in the status bar.
514 ///
515 /// Default: true
516 pub button: Option<bool>,
517 /// Where to dock the panel.
518 ///
519 /// Default: left
520 pub dock: Option<DockPosition>,
521 /// Default width of the panel in pixels.
522 ///
523 /// Default: 360
524 #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
525 pub default_width: Option<f32>,
526 /// How entry statuses are displayed.
527 ///
528 /// Default: icon
529 pub status_style: Option<StatusStyle>,
530
531 /// Whether to show file icons in the git panel.
532 ///
533 /// Default: false
534 pub file_icons: Option<bool>,
535
536 /// Whether to show folder icons or chevrons for directories in the git panel.
537 ///
538 /// Default: true
539 pub folder_icons: Option<bool>,
540
541 /// How and when the scrollbar should be displayed.
542 ///
543 /// Default: inherits editor scrollbar settings
544 pub scrollbar: Option<ScrollbarSettings>,
545
546 /// What the default branch name should be when
547 /// `init.defaultBranch` is not set in git
548 ///
549 /// Default: main
550 pub fallback_branch_name: Option<String>,
551
552 /// Whether to sort entries in the panel by path
553 /// or by status (the default).
554 ///
555 /// Default: false
556 pub sort_by_path: Option<bool>,
557
558 /// Whether to collapse untracked files in the diff panel.
559 ///
560 /// Default: false
561 pub collapse_untracked_diff: Option<bool>,
562
563 /// Whether to show entries with tree or flat view in the panel
564 ///
565 /// Default: false
566 pub tree_view: Option<bool>,
567
568 /// Whether to show the addition/deletion change count next to each file in the Git panel.
569 ///
570 /// Default: true
571 pub diff_stats: Option<bool>,
572
573 /// Whether to show a badge on the git panel icon with the count of uncommitted changes.
574 ///
575 /// Default: false
576 pub show_count_badge: Option<bool>,
577
578 /// Whether the git panel should open on startup.
579 ///
580 /// Default: false
581 pub starts_open: Option<bool>,
582}
583
584#[derive(
585 Default,
586 Copy,
587 Clone,
588 Debug,
589 Serialize,
590 Deserialize,
591 JsonSchema,
592 MergeFrom,
593 PartialEq,
594 Eq,
595 strum::VariantArray,
596 strum::VariantNames,
597)]
598#[serde(rename_all = "snake_case")]
599pub enum StatusStyle {
600 #[default]
601 Icon,
602 LabelColor,
603}
604
605#[with_fallible_options]
606#[derive(
607 Copy, Clone, Default, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq,
608)]
609pub struct ScrollbarSettings {
610 pub show: Option<ShowScrollbar>,
611}
612
613#[with_fallible_options]
614#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq)]
615pub struct NotificationPanelSettingsContent {
616 /// Whether to show the panel button in the status bar.
617 ///
618 /// Default: true
619 pub button: Option<bool>,
620 /// Where to dock the panel.
621 ///
622 /// Default: right
623 pub dock: Option<DockPosition>,
624 /// Default width of the panel in pixels.
625 ///
626 /// Default: 300
627 #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
628 pub default_width: Option<f32>,
629 /// Whether to show a badge on the notification panel icon with the count of unread notifications.
630 ///
631 /// Default: false
632 pub show_count_badge: Option<bool>,
633}
634
635#[with_fallible_options]
636#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq)]
637pub struct PanelSettingsContent {
638 /// Whether to show the panel button in the status bar.
639 ///
640 /// Default: true
641 pub button: Option<bool>,
642 /// Where to dock the panel.
643 ///
644 /// Default: left
645 pub dock: Option<DockPosition>,
646 /// Default width of the panel in pixels.
647 ///
648 /// Default: 240
649 #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
650 pub default_width: Option<f32>,
651}
652
653#[with_fallible_options]
654#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq)]
655pub struct MessageEditorSettings {
656 /// Whether to automatically replace emoji shortcodes with emoji characters.
657 /// For example: typing `:wave:` gets replaced with `👋`.
658 ///
659 /// Default: false
660 pub auto_replace_emoji_shortcode: Option<bool>,
661}
662
663#[with_fallible_options]
664#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq)]
665pub struct FileFinderSettingsContent {
666 /// Whether to show file icons in the file finder.
667 ///
668 /// Default: true
669 pub file_icons: Option<bool>,
670 /// Determines how much space the file finder can take up in relation to the available window width.
671 ///
672 /// Default: small
673 pub modal_max_width: Option<FileFinderWidthContent>,
674 /// Determines whether the file finder should skip focus for the active file in search results.
675 ///
676 /// Default: true
677 pub skip_focus_for_active_in_search: Option<bool>,
678 /// Whether to use gitignored files when searching.
679 /// Only the file Zed had indexed will be used, not necessary all the gitignored files.
680 ///
681 /// Default: Smart
682 pub include_ignored: Option<IncludeIgnoredContent>,
683 /// Whether to include text channels in file finder results.
684 ///
685 /// Default: false
686 pub include_channels: Option<bool>,
687}
688
689#[derive(
690 Debug,
691 PartialEq,
692 Eq,
693 Clone,
694 Copy,
695 Default,
696 Serialize,
697 Deserialize,
698 JsonSchema,
699 MergeFrom,
700 strum::VariantArray,
701 strum::VariantNames,
702)]
703#[serde(rename_all = "snake_case")]
704pub enum IncludeIgnoredContent {
705 /// Use all gitignored files
706 All,
707 /// Use only the files Zed had indexed
708 Indexed,
709 /// Be smart and search for ignored when called from a gitignored worktree
710 #[default]
711 Smart,
712}
713
714#[derive(
715 Debug,
716 PartialEq,
717 Eq,
718 Clone,
719 Copy,
720 Default,
721 Serialize,
722 Deserialize,
723 JsonSchema,
724 MergeFrom,
725 strum::VariantArray,
726 strum::VariantNames,
727)]
728#[serde(rename_all = "lowercase")]
729pub enum FileFinderWidthContent {
730 #[default]
731 Small,
732 Medium,
733 Large,
734 XLarge,
735 Full,
736}
737
738#[with_fallible_options]
739#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Debug, JsonSchema, MergeFrom)]
740pub struct VimSettingsContent {
741 pub default_mode: Option<ModeContent>,
742 pub toggle_relative_line_numbers: Option<bool>,
743 pub use_system_clipboard: Option<UseSystemClipboard>,
744 pub use_smartcase_find: Option<bool>,
745 /// When enabled, the `:substitute` command replaces all matches in a line
746 /// by default. The 'g' flag then toggles this behavior.,
747 pub gdefault: Option<bool>,
748 pub custom_digraphs: Option<HashMap<String, Arc<str>>>,
749 pub highlight_on_yank_duration: Option<u64>,
750 pub cursor_shape: Option<CursorShapeSettings>,
751}
752
753#[derive(
754 Copy,
755 Clone,
756 Default,
757 Serialize,
758 Deserialize,
759 JsonSchema,
760 MergeFrom,
761 PartialEq,
762 Debug,
763 strum::VariantArray,
764 strum::VariantNames,
765)]
766#[serde(rename_all = "snake_case")]
767pub enum ModeContent {
768 #[default]
769 Normal,
770 Insert,
771}
772
773/// Controls when to use system clipboard.
774#[derive(
775 Copy,
776 Clone,
777 Debug,
778 Serialize,
779 Deserialize,
780 PartialEq,
781 Eq,
782 JsonSchema,
783 MergeFrom,
784 strum::VariantArray,
785 strum::VariantNames,
786)]
787#[serde(rename_all = "snake_case")]
788pub enum UseSystemClipboard {
789 /// Don't use system clipboard.
790 Never,
791 /// Use system clipboard.
792 Always,
793 /// Use system clipboard for yank operations.
794 OnYank,
795}
796
797/// Cursor shape configuration for insert mode in Vim.
798#[derive(
799 Copy,
800 Clone,
801 Debug,
802 Serialize,
803 Deserialize,
804 PartialEq,
805 Eq,
806 JsonSchema,
807 MergeFrom,
808 strum::VariantArray,
809 strum::VariantNames,
810)]
811#[serde(rename_all = "snake_case")]
812pub enum VimInsertModeCursorShape {
813 /// Inherit cursor shape from the editor's base cursor_shape setting.
814 Inherit,
815 /// Vertical bar cursor.
816 Bar,
817 /// Block cursor that surrounds the character.
818 Block,
819 /// Underline cursor.
820 Underline,
821 /// Hollow box cursor.
822 Hollow,
823}
824
825/// The settings for cursor shape.
826#[with_fallible_options]
827#[derive(
828 Copy, Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom,
829)]
830pub struct CursorShapeSettings {
831 /// Cursor shape for the normal mode.
832 ///
833 /// Default: block
834 pub normal: Option<CursorShape>,
835 /// Cursor shape for the replace mode.
836 ///
837 /// Default: underline
838 pub replace: Option<CursorShape>,
839 /// Cursor shape for the visual mode.
840 ///
841 /// Default: block
842 pub visual: Option<CursorShape>,
843 /// Cursor shape for the insert mode.
844 ///
845 /// The default value follows the primary cursor_shape.
846 pub insert: Option<VimInsertModeCursorShape>,
847}
848
849/// Settings specific to journaling
850#[with_fallible_options]
851#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq)]
852pub struct JournalSettingsContent {
853 /// The path of the directory where journal entries are stored.
854 ///
855 /// Default: `~`
856 pub path: Option<String>,
857 /// What format to display the hours in.
858 ///
859 /// Default: hour12
860 pub hour_format: Option<HourFormat>,
861}
862
863#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq)]
864#[serde(rename_all = "snake_case")]
865pub enum HourFormat {
866 #[default]
867 Hour12,
868 Hour24,
869}
870
871#[with_fallible_options]
872#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq)]
873pub struct OutlinePanelSettingsContent {
874 /// Whether to show the outline panel button in the status bar.
875 ///
876 /// Default: true
877 pub button: Option<bool>,
878 /// Customize default width (in pixels) taken by outline panel
879 ///
880 /// Default: 240
881 #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
882 pub default_width: Option<f32>,
883 /// The position of outline panel
884 ///
885 /// Default: left
886 pub dock: Option<DockSide>,
887 /// Whether to show file icons in the outline panel.
888 ///
889 /// Default: true
890 pub file_icons: Option<bool>,
891 /// Whether to show folder icons or chevrons for directories in the outline panel.
892 ///
893 /// Default: true
894 pub folder_icons: Option<bool>,
895 /// Whether to show the git status in the outline panel.
896 ///
897 /// Default: true
898 pub git_status: Option<bool>,
899 /// Amount of indentation (in pixels) for nested items.
900 ///
901 /// Default: 20
902 #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
903 pub indent_size: Option<f32>,
904 /// Whether to reveal it in the outline panel automatically,
905 /// when a corresponding project entry becomes active.
906 /// Gitignored entries are never auto revealed.
907 ///
908 /// Default: true
909 pub auto_reveal_entries: Option<bool>,
910 /// Whether to fold directories automatically
911 /// when directory has only one directory inside.
912 ///
913 /// Default: true
914 pub auto_fold_dirs: Option<bool>,
915 /// Settings related to indent guides in the outline panel.
916 pub indent_guides: Option<IndentGuidesSettingsContent>,
917 /// Scrollbar-related settings
918 pub scrollbar: Option<ScrollbarSettingsContent>,
919 /// Default depth to expand outline items in the current file.
920 /// The default depth to which outline entries are expanded on reveal.
921 /// - Set to 0 to collapse all items that have children
922 /// - Set to 1 or higher to collapse items at that depth or deeper
923 ///
924 /// Default: 100
925 pub expand_outlines_with_depth: Option<usize>,
926}
927
928#[derive(
929 Clone,
930 Copy,
931 Debug,
932 PartialEq,
933 Eq,
934 Serialize,
935 Deserialize,
936 JsonSchema,
937 MergeFrom,
938 strum::VariantArray,
939 strum::VariantNames,
940)]
941#[serde(rename_all = "snake_case")]
942pub enum DockSide {
943 Left,
944 Right,
945}
946
947#[derive(
948 Copy,
949 Clone,
950 Debug,
951 PartialEq,
952 Eq,
953 Deserialize,
954 Serialize,
955 JsonSchema,
956 MergeFrom,
957 strum::VariantArray,
958 strum::VariantNames,
959)]
960#[serde(rename_all = "snake_case")]
961pub enum ShowIndentGuides {
962 Always,
963 Never,
964}
965
966#[with_fallible_options]
967#[derive(
968 Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq, Default,
969)]
970pub struct IndentGuidesSettingsContent {
971 /// When to show the scrollbar in the outline panel.
972 pub show: Option<ShowIndentGuides>,
973}
974
975#[derive(Clone, Copy, Default, PartialEq, Debug, JsonSchema, MergeFrom, Deserialize, Serialize)]
976#[serde(rename_all = "snake_case")]
977pub enum LineIndicatorFormat {
978 Short,
979 #[default]
980 Long,
981}
982
983/// The settings for the image viewer.
984#[with_fallible_options]
985#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, Default, PartialEq)]
986pub struct ImageViewerSettingsContent {
987 /// The unit to use for displaying image file sizes.
988 ///
989 /// Default: "binary"
990 pub unit: Option<ImageFileSizeUnit>,
991}
992
993#[with_fallible_options]
994#[derive(
995 Clone,
996 Copy,
997 Debug,
998 Serialize,
999 Deserialize,
1000 JsonSchema,
1001 MergeFrom,
1002 Default,
1003 PartialEq,
1004 strum::VariantArray,
1005 strum::VariantNames,
1006)]
1007#[serde(rename_all = "snake_case")]
1008pub enum ImageFileSizeUnit {
1009 /// Displays file size in binary units (e.g., KiB, MiB).
1010 #[default]
1011 Binary,
1012 /// Displays file size in decimal units (e.g., KB, MB).
1013 Decimal,
1014}
1015
1016#[with_fallible_options]
1017#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq)]
1018pub struct RemoteSettingsContent {
1019 pub ssh_connections: Option<Vec<SshConnection>>,
1020 pub wsl_connections: Option<Vec<WslConnection>>,
1021 pub dev_container_connections: Option<Vec<DevContainerConnection>>,
1022 pub read_ssh_config: Option<bool>,
1023 pub use_podman: Option<bool>,
1024}
1025
1026#[with_fallible_options]
1027#[derive(
1028 Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom, Hash,
1029)]
1030pub struct DevContainerConnection {
1031 pub name: String,
1032 pub remote_user: String,
1033 pub container_id: String,
1034 pub use_podman: bool,
1035}
1036
1037#[with_fallible_options]
1038#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, JsonSchema, MergeFrom)]
1039pub struct SshConnection {
1040 pub host: String,
1041 pub username: Option<String>,
1042 pub port: Option<u16>,
1043 #[serde(default)]
1044 pub args: Vec<String>,
1045 #[serde(default)]
1046 pub projects: collections::BTreeSet<RemoteProject>,
1047 /// Name to use for this server in UI.
1048 pub nickname: Option<String>,
1049 // By default Zed will download the binary to the host directly.
1050 // If this is set to true, Zed will download the binary to your local machine,
1051 // and then upload it over the SSH connection. Useful if your SSH server has
1052 // limited outbound internet access.
1053 pub upload_binary_over_ssh: Option<bool>,
1054
1055 pub port_forwards: Option<Vec<SshPortForwardOption>>,
1056 /// Timeout in seconds for SSH connection and downloading the remote server binary.
1057 /// Defaults to 10 seconds if not specified.
1058 pub connection_timeout: Option<u16>,
1059}
1060
1061#[derive(Clone, Default, Serialize, Deserialize, PartialEq, JsonSchema, MergeFrom, Debug)]
1062pub struct WslConnection {
1063 pub distro_name: String,
1064 pub user: Option<String>,
1065 #[serde(default)]
1066 pub projects: BTreeSet<RemoteProject>,
1067}
1068
1069#[with_fallible_options]
1070#[derive(
1071 Clone, Debug, Default, Serialize, PartialEq, Eq, PartialOrd, Ord, Deserialize, JsonSchema,
1072)]
1073pub struct RemoteProject {
1074 pub paths: Vec<String>,
1075}
1076
1077#[with_fallible_options]
1078#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize, JsonSchema, MergeFrom)]
1079pub struct SshPortForwardOption {
1080 pub local_host: Option<String>,
1081 pub local_port: u16,
1082 pub remote_host: Option<String>,
1083 pub remote_port: u16,
1084}
1085
1086/// Settings for configuring REPL display and behavior.
1087#[with_fallible_options]
1088#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)]
1089pub struct ReplSettingsContent {
1090 /// Maximum number of lines to keep in REPL's scrollback buffer.
1091 /// Clamped with [4, 256] range.
1092 ///
1093 /// Default: 32
1094 pub max_lines: Option<usize>,
1095 /// Maximum number of columns to keep in REPL's scrollback buffer.
1096 /// Clamped with [20, 512] range.
1097 ///
1098 /// Default: 128
1099 pub max_columns: Option<usize>,
1100 /// Whether to show small single-line outputs inline instead of in a block.
1101 ///
1102 /// Default: true
1103 pub inline_output: Option<bool>,
1104 /// Maximum number of characters for an output to be shown inline.
1105 /// Only applies when `inline_output` is true.
1106 ///
1107 /// Default: 50
1108 pub inline_output_max_length: Option<usize>,
1109 /// Maximum number of lines of output to display before scrolling.
1110 /// Set to 0 to disable output height limits.
1111 ///
1112 /// Default: 0
1113 pub output_max_height_lines: Option<usize>,
1114}
1115
1116/// Settings for configuring the which-key popup behaviour.
1117#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)]
1118pub struct WhichKeySettingsContent {
1119 /// Whether to show the which-key popup when holding down key combinations
1120 ///
1121 /// Default: false
1122 pub enabled: Option<bool>,
1123 /// Delay in milliseconds before showing the which-key popup.
1124 ///
1125 /// Default: 700
1126 pub delay_ms: Option<u64>,
1127}
1128
1129#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
1130/// An ExtendingVec in the settings can only accumulate new values.
1131///
1132/// This is useful for things like private files where you only want
1133/// to allow new values to be added.
1134///
1135/// Consider using a HashMap<String, bool> instead of this type
1136/// (like auto_install_extensions) so that user settings files can both add
1137/// and remove values from the set.
1138pub struct ExtendingVec<T>(pub Vec<T>);
1139
1140impl<T> Into<Vec<T>> for ExtendingVec<T> {
1141 fn into(self) -> Vec<T> {
1142 self.0
1143 }
1144}
1145impl<T> From<Vec<T>> for ExtendingVec<T> {
1146 fn from(vec: Vec<T>) -> Self {
1147 ExtendingVec(vec)
1148 }
1149}
1150
1151impl<T: Clone> merge_from::MergeFrom for ExtendingVec<T> {
1152 fn merge_from(&mut self, other: &Self) {
1153 self.0.extend_from_slice(other.0.as_slice());
1154 }
1155}
1156
1157/// A SaturatingBool in the settings can only ever be set to true,
1158/// later attempts to set it to false will be ignored.
1159///
1160/// Used by `disable_ai`.
1161#[derive(Debug, Default, Copy, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
1162pub struct SaturatingBool(pub bool);
1163
1164impl From<bool> for SaturatingBool {
1165 fn from(value: bool) -> Self {
1166 SaturatingBool(value)
1167 }
1168}
1169
1170impl From<SaturatingBool> for bool {
1171 fn from(value: SaturatingBool) -> bool {
1172 value.0
1173 }
1174}
1175
1176impl merge_from::MergeFrom for SaturatingBool {
1177 fn merge_from(&mut self, other: &Self) {
1178 self.0 |= other.0
1179 }
1180}
1181
1182#[derive(
1183 Copy,
1184 Clone,
1185 Default,
1186 Debug,
1187 PartialEq,
1188 Eq,
1189 PartialOrd,
1190 Ord,
1191 Serialize,
1192 Deserialize,
1193 MergeFrom,
1194 JsonSchema,
1195 derive_more::FromStr,
1196)]
1197#[serde(transparent)]
1198pub struct DelayMs(pub u64);
1199
1200impl From<u64> for DelayMs {
1201 fn from(n: u64) -> Self {
1202 Self(n)
1203 }
1204}
1205
1206impl std::fmt::Display for DelayMs {
1207 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1208 write!(f, "{}ms", self.0)
1209 }
1210}