1use std::{path::PathBuf, sync::Arc};
2
3use collections::{BTreeMap, HashMap};
4use schemars::JsonSchema;
5use serde::{Deserialize, Serialize};
6use settings_macros::{MergeFrom, with_fallible_options};
7use util::serde::default_true;
8
9use crate::{
10 AllLanguageSettingsContent, DelayMs, ExtendingVec, ProjectTerminalSettingsContent,
11 SlashCommandSettings,
12};
13
14#[with_fallible_options]
15#[derive(Debug, PartialEq, Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
16pub struct ProjectSettingsContent {
17 #[serde(flatten)]
18 pub all_languages: AllLanguageSettingsContent,
19
20 #[serde(flatten)]
21 pub worktree: WorktreeSettingsContent,
22
23 /// Configuration for language servers.
24 ///
25 /// The following settings can be overridden for specific language servers:
26 /// - initialization_options
27 ///
28 /// To override settings for a language, add an entry for that language server's
29 /// name to the lsp value.
30 /// Default: null
31 #[serde(default)]
32 pub lsp: HashMap<Arc<str>, LspSettings>,
33
34 pub terminal: Option<ProjectTerminalSettingsContent>,
35
36 /// Configuration for Debugger-related features
37 #[serde(default)]
38 pub dap: HashMap<Arc<str>, DapSettingsContent>,
39
40 /// Settings for context servers used for AI-related features.
41 #[serde(default)]
42 pub context_servers: HashMap<Arc<str>, ContextServerSettingsContent>,
43
44 /// Configuration for how direnv configuration should be loaded
45 pub load_direnv: Option<DirenvSettings>,
46
47 /// Settings for slash commands.
48 pub slash_commands: Option<SlashCommandSettings>,
49
50 /// The list of custom Git hosting providers.
51 pub git_hosting_providers: Option<ExtendingVec<GitHostingProviderConfig>>,
52}
53
54#[with_fallible_options]
55#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)]
56pub struct WorktreeSettingsContent {
57 /// The displayed name of this project. If not set or null, the root directory name
58 /// will be displayed.
59 ///
60 /// Default: null
61 pub project_name: Option<String>,
62
63 /// Whether to prevent this project from being shared in public channels.
64 ///
65 /// Default: false
66 #[serde(default)]
67 pub prevent_sharing_in_public_channels: bool,
68
69 /// Completely ignore files matching globs from `file_scan_exclusions`. Overrides
70 /// `file_scan_inclusions`.
71 ///
72 /// Default: [
73 /// "**/.git",
74 /// "**/.svn",
75 /// "**/.hg",
76 /// "**/.jj",
77 /// "**/CVS",
78 /// "**/.DS_Store",
79 /// "**/Thumbs.db",
80 /// "**/.classpath",
81 /// "**/.settings"
82 /// ]
83 pub file_scan_exclusions: Option<Vec<String>>,
84
85 /// Always include files that match these globs when scanning for files, even if they're
86 /// ignored by git. This setting is overridden by `file_scan_exclusions`.
87 /// Default: [
88 /// ".env*",
89 /// "docker-compose.*.yml",
90 /// ]
91 pub file_scan_inclusions: Option<Vec<String>>,
92
93 /// Treat the files matching these globs as `.env` files.
94 /// Default: ["**/.env*", "**/*.pem", "**/*.key", "**/*.cert", "**/*.crt", "**/secrets.yml"]
95 pub private_files: Option<ExtendingVec<String>>,
96
97 /// Treat the files matching these globs as hidden files. You can hide hidden files in the project panel.
98 /// Default: ["**/.*"]
99 pub hidden_files: Option<Vec<String>>,
100}
101
102#[with_fallible_options]
103#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom, Hash)]
104#[serde(rename_all = "snake_case")]
105pub struct LspSettings {
106 pub binary: Option<BinarySettings>,
107 /// Options passed to the language server at startup.
108 ///
109 /// Ref: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#initialize
110 ///
111 /// Consult the documentation for the specific language server to see which settings are supported.
112 pub initialization_options: Option<serde_json::Value>,
113 /// Language server settings.
114 ///
115 /// Ref: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_configuration
116 ///
117 /// Consult the documentation for the specific language server to see which settings are supported.
118 pub settings: Option<serde_json::Value>,
119 /// If the server supports sending tasks over LSP extensions,
120 /// this setting can be used to enable or disable them in Zed.
121 /// Default: true
122 #[serde(default = "default_true")]
123 pub enable_lsp_tasks: bool,
124 pub fetch: Option<FetchSettings>,
125}
126
127impl Default for LspSettings {
128 fn default() -> Self {
129 Self {
130 binary: None,
131 initialization_options: None,
132 settings: None,
133 enable_lsp_tasks: true,
134 fetch: None,
135 }
136 }
137}
138
139#[with_fallible_options]
140#[derive(
141 Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom, Hash,
142)]
143pub struct BinarySettings {
144 pub path: Option<String>,
145 pub arguments: Option<Vec<String>>,
146 pub env: Option<BTreeMap<String, String>>,
147 pub ignore_system_version: Option<bool>,
148}
149
150#[with_fallible_options]
151#[derive(
152 Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom, Hash,
153)]
154pub struct FetchSettings {
155 // Whether to consider pre-releases for fetching
156 pub pre_release: Option<bool>,
157}
158
159/// Common language server settings.
160#[with_fallible_options]
161#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, MergeFrom)]
162pub struct GlobalLspSettingsContent {
163 /// Whether to show the LSP servers button in the status bar.
164 ///
165 /// Default: `true`
166 pub button: Option<bool>,
167}
168
169#[with_fallible_options]
170#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema, MergeFrom)]
171#[serde(rename_all = "snake_case")]
172pub struct DapSettingsContent {
173 pub binary: Option<String>,
174 pub args: Option<Vec<String>>,
175 pub env: Option<HashMap<String, String>>,
176}
177
178#[with_fallible_options]
179#[derive(
180 Default, Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, JsonSchema, MergeFrom,
181)]
182pub struct SessionSettingsContent {
183 /// Whether or not to restore unsaved buffers on restart.
184 ///
185 /// If this is true, user won't be prompted whether to save/discard
186 /// dirty files when closing the application.
187 ///
188 /// Default: true
189 pub restore_unsaved_buffers: Option<bool>,
190}
191
192#[derive(Deserialize, Serialize, Clone, PartialEq, Eq, JsonSchema, MergeFrom, Debug)]
193#[serde(untagged, rename_all = "snake_case")]
194pub enum ContextServerSettingsContent {
195 Stdio {
196 /// Whether the context server is enabled.
197 #[serde(default = "default_true")]
198 enabled: bool,
199
200 #[serde(flatten)]
201 command: ContextServerCommand,
202 },
203 Http {
204 /// Whether the context server is enabled.
205 #[serde(default = "default_true")]
206 enabled: bool,
207 /// The URL of the remote context server.
208 url: String,
209 /// Optional headers to send.
210 #[serde(skip_serializing_if = "HashMap::is_empty", default)]
211 headers: HashMap<String, String>,
212 },
213 Extension {
214 /// Whether the context server is enabled.
215 #[serde(default = "default_true")]
216 enabled: bool,
217 /// The settings for this context server specified by the extension.
218 ///
219 /// Consult the documentation for the context server to see what settings
220 /// are supported.
221 settings: serde_json::Value,
222 },
223}
224
225impl ContextServerSettingsContent {
226 pub fn set_enabled(&mut self, enabled: bool) {
227 match self {
228 ContextServerSettingsContent::Stdio {
229 enabled: custom_enabled,
230 ..
231 } => {
232 *custom_enabled = enabled;
233 }
234 ContextServerSettingsContent::Extension {
235 enabled: ext_enabled,
236 ..
237 } => *ext_enabled = enabled,
238 ContextServerSettingsContent::Http {
239 enabled: remote_enabled,
240 ..
241 } => *remote_enabled = enabled,
242 }
243 }
244}
245
246#[with_fallible_options]
247#[derive(Deserialize, Serialize, Clone, PartialEq, Eq, JsonSchema, MergeFrom)]
248pub struct ContextServerCommand {
249 #[serde(rename = "command")]
250 pub path: PathBuf,
251 pub args: Vec<String>,
252 pub env: Option<HashMap<String, String>>,
253 /// Timeout for tool calls in milliseconds. Defaults to 60000 (60 seconds) if not specified.
254 pub timeout: Option<u64>,
255}
256
257impl std::fmt::Debug for ContextServerCommand {
258 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
259 let filtered_env = self.env.as_ref().map(|env| {
260 env.iter()
261 .map(|(k, v)| {
262 (
263 k,
264 if util::redact::should_redact(k) {
265 "[REDACTED]"
266 } else {
267 v
268 },
269 )
270 })
271 .collect::<Vec<_>>()
272 });
273
274 f.debug_struct("ContextServerCommand")
275 .field("path", &self.path)
276 .field("args", &self.args)
277 .field("env", &filtered_env)
278 .finish()
279 }
280}
281
282#[with_fallible_options]
283#[derive(Copy, Clone, Debug, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
284pub struct GitSettings {
285 /// Whether or not to show the git gutter.
286 ///
287 /// Default: tracked_files
288 pub git_gutter: Option<GitGutterSetting>,
289 /// Sets the debounce threshold (in milliseconds) after which changes are reflected in the git gutter.
290 ///
291 /// Default: 0
292 pub gutter_debounce: Option<u64>,
293 /// Whether or not to show git blame data inline in
294 /// the currently focused line.
295 ///
296 /// Default: on
297 pub inline_blame: Option<InlineBlameSettings>,
298 /// Git blame settings.
299 pub blame: Option<BlameSettings>,
300 /// Which information to show in the branch picker.
301 ///
302 /// Default: on
303 pub branch_picker: Option<BranchPickerSettingsContent>,
304 /// How hunks are displayed visually in the editor.
305 ///
306 /// Default: staged_hollow
307 pub hunk_style: Option<GitHunkStyleSetting>,
308 /// How file paths are displayed in the git gutter.
309 ///
310 /// Default: file_name_first
311 pub path_style: Option<GitPathStyle>,
312}
313
314#[derive(
315 Clone,
316 Copy,
317 Debug,
318 PartialEq,
319 Default,
320 Serialize,
321 Deserialize,
322 JsonSchema,
323 MergeFrom,
324 strum::VariantArray,
325 strum::VariantNames,
326)]
327#[serde(rename_all = "snake_case")]
328pub enum GitGutterSetting {
329 /// Show git gutter in tracked files.
330 #[default]
331 TrackedFiles,
332 /// Hide git gutter
333 Hide,
334}
335
336#[with_fallible_options]
337#[derive(Clone, Copy, Debug, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
338#[serde(rename_all = "snake_case")]
339pub struct InlineBlameSettings {
340 /// Whether or not to show git blame data inline in
341 /// the currently focused line.
342 ///
343 /// Default: true
344 pub enabled: Option<bool>,
345 /// Whether to only show the inline blame information
346 /// after a delay once the cursor stops moving.
347 ///
348 /// Default: 0
349 pub delay_ms: Option<DelayMs>,
350 /// The amount of padding between the end of the source line and the start
351 /// of the inline blame in units of columns.
352 ///
353 /// Default: 7
354 pub padding: Option<u32>,
355 /// The minimum column number to show the inline blame information at
356 ///
357 /// Default: 0
358 pub min_column: Option<u32>,
359 /// Whether to show commit summary as part of the inline blame.
360 ///
361 /// Default: false
362 pub show_commit_summary: Option<bool>,
363}
364
365#[with_fallible_options]
366#[derive(Clone, Copy, Debug, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
367#[serde(rename_all = "snake_case")]
368pub struct BlameSettings {
369 /// Whether to show the avatar of the author of the commit.
370 ///
371 /// Default: true
372 pub show_avatar: Option<bool>,
373}
374
375#[with_fallible_options]
376#[derive(Clone, Copy, PartialEq, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
377#[serde(rename_all = "snake_case")]
378pub struct BranchPickerSettingsContent {
379 /// Whether to show author name as part of the commit information.
380 ///
381 /// Default: false
382 pub show_author_name: Option<bool>,
383}
384
385#[derive(
386 Clone,
387 Copy,
388 PartialEq,
389 Debug,
390 Default,
391 Serialize,
392 Deserialize,
393 JsonSchema,
394 MergeFrom,
395 strum::VariantArray,
396 strum::VariantNames,
397)]
398#[serde(rename_all = "snake_case")]
399pub enum GitHunkStyleSetting {
400 /// Show unstaged hunks with a filled background and staged hunks hollow.
401 #[default]
402 StagedHollow,
403 /// Show unstaged hunks hollow and staged hunks with a filled background.
404 UnstagedHollow,
405}
406
407#[with_fallible_options]
408#[derive(
409 Copy,
410 Clone,
411 Debug,
412 PartialEq,
413 Default,
414 Serialize,
415 Deserialize,
416 JsonSchema,
417 MergeFrom,
418 strum::VariantArray,
419 strum::VariantNames,
420)]
421#[serde(rename_all = "snake_case")]
422pub enum GitPathStyle {
423 /// Show file name first, then path
424 #[default]
425 FileNameFirst,
426 /// Show full path first
427 FilePathFirst,
428}
429
430#[with_fallible_options]
431#[derive(Clone, Debug, PartialEq, Eq, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
432pub struct DiagnosticsSettingsContent {
433 /// Whether to show the project diagnostics button in the status bar.
434 pub button: Option<bool>,
435
436 /// Whether or not to include warning diagnostics.
437 pub include_warnings: Option<bool>,
438
439 /// Settings for using LSP pull diagnostics mechanism in Zed.
440 pub lsp_pull_diagnostics: Option<LspPullDiagnosticsSettingsContent>,
441
442 /// Settings for showing inline diagnostics.
443 pub inline: Option<InlineDiagnosticsSettingsContent>,
444}
445
446#[with_fallible_options]
447#[derive(
448 Clone, Copy, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq,
449)]
450pub struct LspPullDiagnosticsSettingsContent {
451 /// Whether to pull for diagnostics or not.
452 ///
453 /// Default: true
454 pub enabled: Option<bool>,
455 /// Minimum time to wait before pulling diagnostics from the language server(s).
456 /// 0 turns the debounce off.
457 ///
458 /// Default: 50
459 pub debounce_ms: Option<DelayMs>,
460}
461
462#[with_fallible_options]
463#[derive(
464 Clone, Copy, Debug, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Eq,
465)]
466pub struct InlineDiagnosticsSettingsContent {
467 /// Whether or not to show inline diagnostics
468 ///
469 /// Default: false
470 pub enabled: Option<bool>,
471 /// Whether to only show the inline diagnostics after a delay after the
472 /// last editor event.
473 ///
474 /// Default: 150
475 pub update_debounce_ms: Option<DelayMs>,
476 /// The amount of padding between the end of the source line and the start
477 /// of the inline diagnostic in units of columns.
478 ///
479 /// Default: 4
480 pub padding: Option<u32>,
481 /// The minimum column to display inline diagnostics. This setting can be
482 /// used to horizontally align inline diagnostics at some position. Lines
483 /// longer than this value will still push diagnostics further to the right.
484 ///
485 /// Default: 0
486 pub min_column: Option<u32>,
487
488 pub max_severity: Option<DiagnosticSeverityContent>,
489}
490
491#[with_fallible_options]
492#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema, MergeFrom)]
493pub struct NodeBinarySettings {
494 /// The path to the Node binary.
495 pub path: Option<String>,
496 /// The path to the npm binary Zed should use (defaults to `.path/../npm`).
497 pub npm_path: Option<String>,
498 /// If enabled, Zed will download its own copy of Node.
499 pub ignore_system_version: Option<bool>,
500}
501
502#[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
503#[serde(rename_all = "snake_case")]
504pub enum DirenvSettings {
505 /// Load direnv configuration through a shell hook
506 ShellHook,
507 /// Load direnv configuration directly using `direnv export json`
508 #[default]
509 Direct,
510 /// Do not load direnv configuration
511 Disabled,
512}
513
514#[derive(
515 Clone,
516 Copy,
517 Debug,
518 Eq,
519 PartialEq,
520 Ord,
521 PartialOrd,
522 Serialize,
523 Deserialize,
524 JsonSchema,
525 MergeFrom,
526 strum::VariantArray,
527 strum::VariantNames,
528)]
529#[serde(rename_all = "snake_case")]
530pub enum DiagnosticSeverityContent {
531 // No diagnostics are shown.
532 Off,
533 Error,
534 Warning,
535 Info,
536 Hint,
537 All,
538}
539
540/// A custom Git hosting provider.
541#[with_fallible_options]
542#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, JsonSchema, MergeFrom)]
543pub struct GitHostingProviderConfig {
544 /// The type of the provider.
545 ///
546 /// Must be one of `github`, `gitlab`, or `bitbucket`.
547 pub provider: GitHostingProviderKind,
548
549 /// The base URL for the provider (e.g., "https://code.corp.big.com").
550 pub base_url: String,
551
552 /// The display name for the provider (e.g., "BigCorp GitHub").
553 pub name: String,
554}
555
556#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)]
557#[serde(rename_all = "snake_case")]
558pub enum GitHostingProviderKind {
559 Github,
560 Gitlab,
561 Bitbucket,
562}