project.rs

  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#[skip_serializing_none]
141#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
142#[serde(rename_all = "snake_case")]
143pub struct DapSettingsContent {
144    pub binary: Option<String>,
145    #[serde(default)]
146    pub args: Option<Vec<String>>,
147}
148
149#[skip_serializing_none]
150#[derive(Default, Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, JsonSchema)]
151pub struct SessionSettingsContent {
152    /// Whether or not to restore unsaved buffers on restart.
153    ///
154    /// If this is true, user won't be prompted whether to save/discard
155    /// dirty files when closing the application.
156    ///
157    /// Default: true
158    pub restore_unsaved_buffers: Option<bool>,
159}
160
161#[derive(Deserialize, Serialize, Clone, PartialEq, Eq, JsonSchema, Debug)]
162#[serde(tag = "source", rename_all = "snake_case")]
163pub enum ContextServerSettingsContent {
164    Custom {
165        /// Whether the context server is enabled.
166        #[serde(default = "default_true")]
167        enabled: bool,
168
169        #[serde(flatten)]
170        command: ContextServerCommand,
171    },
172    Extension {
173        /// Whether the context server is enabled.
174        #[serde(default = "default_true")]
175        enabled: bool,
176        /// The settings for this context server specified by the extension.
177        ///
178        /// Consult the documentation for the context server to see what settings
179        /// are supported.
180        settings: serde_json::Value,
181    },
182}
183impl ContextServerSettingsContent {
184    pub fn set_enabled(&mut self, enabled: bool) {
185        match self {
186            ContextServerSettingsContent::Custom {
187                enabled: custom_enabled,
188                command: _,
189            } => {
190                *custom_enabled = enabled;
191            }
192            ContextServerSettingsContent::Extension {
193                enabled: ext_enabled,
194                settings: _,
195            } => *ext_enabled = enabled,
196        }
197    }
198}
199
200#[skip_serializing_none]
201#[derive(Deserialize, Serialize, Clone, PartialEq, Eq, JsonSchema)]
202pub struct ContextServerCommand {
203    #[serde(rename = "command")]
204    pub path: PathBuf,
205    pub args: Vec<String>,
206    pub env: Option<HashMap<String, String>>,
207    /// Timeout for tool calls in milliseconds. Defaults to 60000 (60 seconds) if not specified.
208    pub timeout: Option<u64>,
209}
210
211impl std::fmt::Debug for ContextServerCommand {
212    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
213        let filtered_env = self.env.as_ref().map(|env| {
214            env.iter()
215                .map(|(k, v)| {
216                    (
217                        k,
218                        if util::redact::should_redact(k) {
219                            "[REDACTED]"
220                        } else {
221                            v
222                        },
223                    )
224                })
225                .collect::<Vec<_>>()
226        });
227
228        f.debug_struct("ContextServerCommand")
229            .field("path", &self.path)
230            .field("args", &self.args)
231            .field("env", &filtered_env)
232            .finish()
233    }
234}
235
236#[skip_serializing_none]
237#[derive(Copy, Clone, Debug, PartialEq, Default, Serialize, Deserialize, JsonSchema)]
238pub struct GitSettings {
239    /// Whether or not to show the git gutter.
240    ///
241    /// Default: tracked_files
242    pub git_gutter: Option<GitGutterSetting>,
243    /// Sets the debounce threshold (in milliseconds) after which changes are reflected in the git gutter.
244    ///
245    /// Default: null
246    pub gutter_debounce: Option<u64>,
247    /// Whether or not to show git blame data inline in
248    /// the currently focused line.
249    ///
250    /// Default: on
251    pub inline_blame: Option<InlineBlameSettings>,
252    /// Which information to show in the branch picker.
253    ///
254    /// Default: on
255    pub branch_picker: Option<BranchPickerSettingsContent>,
256    /// How hunks are displayed visually in the editor.
257    ///
258    /// Default: staged_hollow
259    pub hunk_style: Option<GitHunkStyleSetting>,
260}
261
262#[derive(Clone, Copy, Debug, PartialEq, Default, Serialize, Deserialize, JsonSchema)]
263#[serde(rename_all = "snake_case")]
264pub enum GitGutterSetting {
265    /// Show git gutter in tracked files.
266    #[default]
267    TrackedFiles,
268    /// Hide git gutter
269    Hide,
270}
271
272#[skip_serializing_none]
273#[derive(Clone, Copy, Debug, PartialEq, Default, Serialize, Deserialize, JsonSchema)]
274#[serde(rename_all = "snake_case")]
275pub struct InlineBlameSettings {
276    /// Whether or not to show git blame data inline in
277    /// the currently focused line.
278    ///
279    /// Default: true
280    pub enabled: Option<bool>,
281    /// Whether to only show the inline blame information
282    /// after a delay once the cursor stops moving.
283    ///
284    /// Default: 0
285    pub delay_ms: Option<u64>,
286    /// The amount of padding between the end of the source line and the start
287    /// of the inline blame in units of columns.
288    ///
289    /// Default: 7
290    pub padding: Option<u32>,
291    /// The minimum column number to show the inline blame information at
292    ///
293    /// Default: 0
294    pub min_column: Option<u32>,
295    /// Whether to show commit summary as part of the inline blame.
296    ///
297    /// Default: false
298    pub show_commit_summary: Option<bool>,
299}
300
301#[skip_serializing_none]
302#[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize, JsonSchema)]
303#[serde(rename_all = "snake_case")]
304pub struct BranchPickerSettingsContent {
305    /// Whether to show author name as part of the commit information.
306    ///
307    /// Default: false
308    pub show_author_name: Option<bool>,
309}
310
311#[derive(Clone, Copy, PartialEq, Debug, Default, Serialize, Deserialize, JsonSchema)]
312#[serde(rename_all = "snake_case")]
313pub enum GitHunkStyleSetting {
314    /// Show unstaged hunks with a filled background and staged hunks hollow.
315    #[default]
316    StagedHollow,
317    /// Show unstaged hunks hollow and staged hunks with a filled background.
318    UnstagedHollow,
319}
320
321#[skip_serializing_none]
322#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
323pub struct DiagnosticsSettingsContent {
324    /// Whether to show the project diagnostics button in the status bar.
325    pub button: Option<bool>,
326
327    /// Whether or not to include warning diagnostics.
328    pub include_warnings: Option<bool>,
329
330    /// Settings for using LSP pull diagnostics mechanism in Zed.
331    pub lsp_pull_diagnostics: Option<LspPullDiagnosticsSettingsContent>,
332
333    /// Settings for showing inline diagnostics.
334    pub inline: Option<InlineDiagnosticsSettingsContent>,
335}
336
337#[skip_serializing_none]
338#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
339pub struct LspPullDiagnosticsSettingsContent {
340    /// Whether to pull for diagnostics or not.
341    ///
342    /// Default: true
343    pub enabled: Option<bool>,
344    /// Minimum time to wait before pulling diagnostics from the language server(s).
345    /// 0 turns the debounce off.
346    ///
347    /// Default: 50
348    pub debounce_ms: Option<u64>,
349}
350
351#[skip_serializing_none]
352#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, JsonSchema, Eq)]
353pub struct InlineDiagnosticsSettingsContent {
354    /// Whether or not to show inline diagnostics
355    ///
356    /// Default: false
357    pub enabled: Option<bool>,
358    /// Whether to only show the inline diagnostics after a delay after the
359    /// last editor event.
360    ///
361    /// Default: 150
362    pub update_debounce_ms: Option<u64>,
363    /// The amount of padding between the end of the source line and the start
364    /// of the inline diagnostic in units of columns.
365    ///
366    /// Default: 4
367    pub padding: Option<u32>,
368    /// The minimum column to display inline diagnostics. This setting can be
369    /// used to horizontally align inline diagnostics at some position. Lines
370    /// longer than this value will still push diagnostics further to the right.
371    ///
372    /// Default: 0
373    pub min_column: Option<u32>,
374
375    pub max_severity: Option<DiagnosticSeverityContent>,
376}
377
378#[skip_serializing_none]
379#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
380pub struct NodeBinarySettings {
381    /// The path to the Node binary.
382    pub path: Option<String>,
383    /// The path to the npm binary Zed should use (defaults to `.path/../npm`).
384    pub npm_path: Option<String>,
385    /// If enabled, Zed will download its own copy of Node.
386    pub ignore_system_version: Option<bool>,
387}
388
389#[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize, JsonSchema)]
390#[serde(rename_all = "snake_case")]
391pub enum DirenvSettings {
392    /// Load direnv configuration through a shell hook
393    ShellHook,
394    /// Load direnv configuration directly using `direnv export json`
395    #[default]
396    Direct,
397}
398
399#[derive(
400    Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, JsonSchema,
401)]
402#[serde(rename_all = "snake_case")]
403pub enum DiagnosticSeverityContent {
404    // No diagnostics are shown.
405    Off,
406    Error,
407    Warning,
408    Info,
409    #[serde(alias = "all")]
410    Hint,
411}
412
413/// A custom Git hosting provider.
414#[skip_serializing_none]
415#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, JsonSchema)]
416pub struct GitHostingProviderConfig {
417    /// The type of the provider.
418    ///
419    /// Must be one of `github`, `gitlab`, or `bitbucket`.
420    pub provider: GitHostingProviderKind,
421
422    /// The base URL for the provider (e.g., "https://code.corp.big.com").
423    pub base_url: String,
424
425    /// The display name for the provider (e.g., "BigCorp GitHub").
426    pub name: String,
427}
428
429#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
430#[serde(rename_all = "snake_case")]
431pub enum GitHostingProviderKind {
432    Github,
433    Gitlab,
434    Bitbucket,
435}