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