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