1use std::num::NonZeroUsize;
2
3use anyhow::Result;
4use collections::HashMap;
5use gpui::AppContext;
6use schemars::JsonSchema;
7use serde::{Deserialize, Serialize};
8use settings::{Settings, SettingsSources};
9
10#[derive(Deserialize)]
11pub struct WorkspaceSettings {
12 pub active_pane_modifiers: ActivePanelModifiers,
13 pub pane_split_direction_horizontal: PaneSplitDirectionHorizontal,
14 pub pane_split_direction_vertical: PaneSplitDirectionVertical,
15 pub centered_layout: CenteredLayoutSettings,
16 pub confirm_quit: bool,
17 pub show_call_status_icon: bool,
18 pub autosave: AutosaveSetting,
19 pub restore_on_startup: RestoreOnStartupBehavior,
20 pub drop_target_size: f32,
21 pub when_closing_with_no_tabs: CloseWindowWhenNoItems,
22 pub use_system_path_prompts: bool,
23 pub command_aliases: HashMap<String, String>,
24 pub show_user_picture: bool,
25 pub max_tabs: Option<NonZeroUsize>,
26}
27
28#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema)]
29#[serde(rename_all = "snake_case")]
30pub struct ActivePanelModifiers {
31 /// Scale by which to zoom the active pane.
32 /// When set to 1.0, the active pane has the same size as others,
33 /// but when set to a larger value, the active pane takes up more space.
34 ///
35 /// Default: `1.0`
36 pub magnification: Option<f32>,
37 /// Size of the border surrounding the active pane.
38 /// When set to 0, the active pane doesn't have any border.
39 /// The border is drawn inset.
40 ///
41 /// Default: `0.0`
42 pub border_size: Option<f32>,
43 /// Opacity of inactive panels.
44 /// When set to 1.0, the inactive panes have the same opacity as the active one.
45 /// If set to 0, the inactive panes content will not be visible at all.
46 /// Values are clamped to the [0.0, 1.0] range.
47 ///
48 /// Default: `1.0`
49 pub inactive_opacity: Option<f32>,
50}
51
52#[derive(Copy, Clone, Default, Serialize, Deserialize, JsonSchema)]
53#[serde(rename_all = "snake_case")]
54pub enum CloseWindowWhenNoItems {
55 /// Match platform conventions by default, so "on" on macOS and "off" everywhere else
56 #[default]
57 PlatformDefault,
58 /// Close the window when there are no tabs
59 CloseWindow,
60 /// Leave the window open when there are no tabs
61 KeepWindowOpen,
62}
63
64impl CloseWindowWhenNoItems {
65 pub fn should_close(&self) -> bool {
66 match self {
67 CloseWindowWhenNoItems::PlatformDefault => cfg!(target_os = "macos"),
68 CloseWindowWhenNoItems::CloseWindow => true,
69 CloseWindowWhenNoItems::KeepWindowOpen => false,
70 }
71 }
72}
73
74#[derive(Copy, Clone, Default, Serialize, Deserialize, JsonSchema)]
75#[serde(rename_all = "snake_case")]
76pub enum RestoreOnStartupBehavior {
77 /// Always start with an empty editor
78 None,
79 /// Restore the workspace that was closed last.
80 LastWorkspace,
81 /// Restore all workspaces that were open when quitting Zed.
82 #[default]
83 LastSession,
84}
85
86#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
87pub struct WorkspaceSettingsContent {
88 /// Active pane styling settings.
89 pub active_pane_modifiers: Option<ActivePanelModifiers>,
90 /// Direction to split horizontally.
91 ///
92 /// Default: "up"
93 pub pane_split_direction_horizontal: Option<PaneSplitDirectionHorizontal>,
94 /// Direction to split vertically.
95 ///
96 /// Default: "left"
97 pub pane_split_direction_vertical: Option<PaneSplitDirectionVertical>,
98 /// Centered layout related settings.
99 pub centered_layout: Option<CenteredLayoutSettings>,
100 /// Whether or not to prompt the user to confirm before closing the application.
101 ///
102 /// Default: false
103 pub confirm_quit: Option<bool>,
104 /// Whether or not to show the call status icon in the status bar.
105 ///
106 /// Default: true
107 pub show_call_status_icon: Option<bool>,
108 /// When to automatically save edited buffers.
109 ///
110 /// Default: off
111 pub autosave: Option<AutosaveSetting>,
112 /// Controls previous session restoration in freshly launched Zed instance.
113 /// Values: none, last_workspace, last_session
114 /// Default: last_session
115 pub restore_on_startup: Option<RestoreOnStartupBehavior>,
116 /// The size of the workspace split drop targets on the outer edges.
117 /// Given as a fraction that will be multiplied by the smaller dimension of the workspace.
118 ///
119 /// Default: `0.2` (20% of the smaller dimension of the workspace)
120 pub drop_target_size: Option<f32>,
121 /// Whether to close the window when using 'close active item' on a workspace with no tabs
122 ///
123 /// Default: auto ("on" on macOS, "off" otherwise)
124 pub when_closing_with_no_tabs: Option<CloseWindowWhenNoItems>,
125 /// Whether to use the system provided dialogs for Open and Save As.
126 /// When set to false, Zed will use the built-in keyboard-first pickers.
127 ///
128 /// Default: true
129 pub use_system_path_prompts: Option<bool>,
130 /// Aliases for the command palette. When you type a key in this map,
131 /// it will be assumed to equal the value.
132 ///
133 /// Default: true
134 pub command_aliases: Option<HashMap<String, String>>,
135 /// Whether to show user avatar in the title bar.
136 ///
137 /// Default: true
138 pub show_user_picture: Option<bool>,
139 // Maximum open tabs in a pane. Will not close an unsaved
140 // tab. Set to `None` for unlimited tabs.
141 //
142 // Default: none
143 pub max_tabs: Option<NonZeroUsize>,
144}
145
146#[derive(Deserialize)]
147pub struct TabBarSettings {
148 pub show: bool,
149 pub show_nav_history_buttons: bool,
150}
151
152#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
153pub struct TabBarSettingsContent {
154 /// Whether or not to show the tab bar in the editor.
155 ///
156 /// Default: true
157 pub show: Option<bool>,
158 /// Whether or not to show the navigation history buttons in the tab bar.
159 ///
160 /// Default: true
161 pub show_nav_history_buttons: Option<bool>,
162}
163
164#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
165#[serde(rename_all = "snake_case")]
166pub enum AutosaveSetting {
167 /// Disable autosave.
168 Off,
169 /// Save after inactivity period of `milliseconds`.
170 AfterDelay { milliseconds: u64 },
171 /// Autosave when focus changes.
172 OnFocusChange,
173 /// Autosave when the active window changes.
174 OnWindowChange,
175}
176
177#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
178#[serde(rename_all = "snake_case")]
179pub enum PaneSplitDirectionHorizontal {
180 Up,
181 Down,
182}
183
184#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
185#[serde(rename_all = "snake_case")]
186pub enum PaneSplitDirectionVertical {
187 Left,
188 Right,
189}
190
191#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema)]
192#[serde(rename_all = "snake_case")]
193pub struct CenteredLayoutSettings {
194 /// The relative width of the left padding of the central pane from the
195 /// workspace when the centered layout is used.
196 ///
197 /// Default: 0.2
198 pub left_padding: Option<f32>,
199 // The relative width of the right padding of the central pane from the
200 // workspace when the centered layout is used.
201 ///
202 /// Default: 0.2
203 pub right_padding: Option<f32>,
204}
205
206impl Settings for WorkspaceSettings {
207 const KEY: Option<&'static str> = None;
208
209 type FileContent = WorkspaceSettingsContent;
210
211 fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
212 sources.json_merge()
213 }
214}
215
216impl Settings for TabBarSettings {
217 const KEY: Option<&'static str> = Some("tab_bar");
218
219 type FileContent = TabBarSettingsContent;
220
221 fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
222 sources.json_merge()
223 }
224}