project.rs

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