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