1use collections::HashMap;
2use gpui::AppContext;
3use schemars::JsonSchema;
4use serde::{Deserialize, Serialize};
5use settings::{Settings, SettingsSources};
6use std::{sync::Arc, time::Duration};
7
8#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
9pub struct ProjectSettings {
10 /// Configuration for language servers.
11 ///
12 /// The following settings can be overridden for specific language servers:
13 /// - initialization_options
14 /// To override settings for a language, add an entry for that language server's
15 /// name to the lsp value.
16 /// Default: null
17 #[serde(default)]
18 pub lsp: HashMap<Arc<str>, LspSettings>,
19
20 /// Configuration for Git-related features
21 #[serde(default)]
22 pub git: GitSettings,
23
24 /// Configuration for how direnv configuration should be loaded
25 #[serde(default)]
26 pub load_direnv: DirenvSettings,
27}
28
29#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
30#[serde(rename_all = "snake_case")]
31pub enum DirenvSettings {
32 /// Load direnv configuration through a shell hook
33 #[default]
34 ShellHook,
35 /// Load direnv configuration directly using `direnv export json`
36 ///
37 /// Warning: This option is experimental and might cause some inconsistent behaviour compared to using the shell hook.
38 /// If it does, please report it to GitHub
39 Direct,
40}
41
42#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
43pub struct GitSettings {
44 /// Whether or not to show the git gutter.
45 ///
46 /// Default: tracked_files
47 pub git_gutter: Option<GitGutterSetting>,
48 pub gutter_debounce: Option<u64>,
49 /// Whether or not to show git blame data inline in
50 /// the currently focused line.
51 ///
52 /// Default: on
53 pub inline_blame: Option<InlineBlameSettings>,
54}
55
56impl GitSettings {
57 pub fn inline_blame_enabled(&self) -> bool {
58 #[allow(unknown_lints, clippy::manual_unwrap_or_default)]
59 match self.inline_blame {
60 Some(InlineBlameSettings { enabled, .. }) => enabled,
61 _ => false,
62 }
63 }
64
65 pub fn inline_blame_delay(&self) -> Option<Duration> {
66 match self.inline_blame {
67 Some(InlineBlameSettings {
68 delay_ms: Some(delay_ms),
69 ..
70 }) if delay_ms > 0 => Some(Duration::from_millis(delay_ms)),
71 _ => None,
72 }
73 }
74}
75
76#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, JsonSchema)]
77#[serde(rename_all = "snake_case")]
78pub enum GitGutterSetting {
79 /// Show git gutter in tracked files.
80 #[default]
81 TrackedFiles,
82 /// Hide git gutter
83 Hide,
84}
85
86#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, JsonSchema)]
87#[serde(rename_all = "snake_case")]
88pub struct InlineBlameSettings {
89 /// Whether or not to show git blame data inline in
90 /// the currently focused line.
91 ///
92 /// Default: true
93 #[serde(default = "true_value")]
94 pub enabled: bool,
95 /// Whether to only show the inline blame information
96 /// after a delay once the cursor stops moving.
97 ///
98 /// Default: 0
99 pub delay_ms: Option<u64>,
100 /// The minimum column number to show the inline blame information at
101 ///
102 /// Default: 0
103 pub min_column: Option<u32>,
104}
105
106const fn true_value() -> bool {
107 true
108}
109
110#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
111pub struct BinarySettings {
112 pub path: Option<String>,
113 pub arguments: Option<Vec<String>>,
114 pub path_lookup: Option<bool>,
115}
116
117#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
118#[serde(rename_all = "snake_case")]
119pub struct LspSettings {
120 pub binary: Option<BinarySettings>,
121 pub initialization_options: Option<serde_json::Value>,
122 pub settings: Option<serde_json::Value>,
123}
124
125impl Settings for ProjectSettings {
126 const KEY: Option<&'static str> = None;
127
128 type FileContent = Self;
129
130 fn load(
131 sources: SettingsSources<Self::FileContent>,
132 _: &mut AppContext,
133 ) -> anyhow::Result<Self> {
134 sources.json_merge()
135 }
136}