1use std::{path::PathBuf, sync::Arc};
2
3use collections::{BTreeMap, HashMap};
4use gpui::Rgba;
5use schemars::JsonSchema;
6use serde::{Deserialize, Serialize};
7use settings_json::parse_json_with_comments;
8use settings_macros::{MergeFrom, with_fallible_options};
9use util::serde::default_true;
10
11use crate::{
12 AllLanguageSettingsContent, DelayMs, ExtendingVec, ParseStatus, ProjectTerminalSettingsContent,
13 RootUserSettings, SlashCommandSettings, fallible_options,
14};
15
16#[with_fallible_options]
17#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)]
18pub struct LspSettingsMap(pub HashMap<Arc<str>, LspSettings>);
19
20impl IntoIterator for LspSettingsMap {
21 type Item = (Arc<str>, LspSettings);
22 type IntoIter = std::collections::hash_map::IntoIter<Arc<str>, LspSettings>;
23
24 fn into_iter(self) -> Self::IntoIter {
25 self.0.into_iter()
26 }
27}
28
29impl RootUserSettings for ProjectSettingsContent {
30 fn parse_json(json: &str) -> (Option<Self>, ParseStatus) {
31 fallible_options::parse_json(json)
32 }
33 fn parse_json_with_comments(json: &str) -> anyhow::Result<Self> {
34 parse_json_with_comments(json)
35 }
36}
37
38#[with_fallible_options]
39#[derive(Debug, PartialEq, Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
40pub struct ProjectSettingsContent {
41 #[serde(flatten)]
42 pub all_languages: AllLanguageSettingsContent,
43
44 #[serde(flatten)]
45 pub worktree: WorktreeSettingsContent,
46
47 /// Configuration for language servers.
48 ///
49 /// The following settings can be overridden for specific language servers:
50 /// - initialization_options
51 ///
52 /// To override settings for a language, add an entry for that language server's
53 /// name to the lsp value.
54 /// Default: null
55 #[serde(default)]
56 pub lsp: LspSettingsMap,
57
58 pub terminal: Option<ProjectTerminalSettingsContent>,
59
60 /// Configuration for Debugger-related features
61 #[serde(default)]
62 pub dap: HashMap<Arc<str>, DapSettingsContent>,
63
64 /// Settings for context servers used for AI-related features.
65 #[serde(default)]
66 pub context_servers: HashMap<Arc<str>, ContextServerSettingsContent>,
67
68 /// Default timeout in seconds for context server tool calls.
69 /// Can be overridden per-server in context_servers configuration.
70 ///
71 /// Default: 60
72 pub context_server_timeout: Option<u64>,
73
74 /// Configuration for how direnv configuration should be loaded
75 pub load_direnv: Option<DirenvSettings>,
76
77 /// Settings for slash commands.
78 pub slash_commands: Option<SlashCommandSettings>,
79
80 /// The list of custom Git hosting providers.
81 pub git_hosting_providers: Option<ExtendingVec<GitHostingProviderConfig>>,
82}
83
84#[with_fallible_options]
85#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)]
86pub struct WorktreeSettingsContent {
87 /// The displayed name of this project. If not set or null, the root directory name
88 /// will be displayed.
89 ///
90 /// Default: null
91 pub project_name: Option<String>,
92
93 /// Whether to prevent this project from being shared in public channels.
94 ///
95 /// Default: false
96 #[serde(default)]
97 pub prevent_sharing_in_public_channels: bool,
98
99 /// Completely ignore files matching globs from `file_scan_exclusions`. Overrides
100 /// `file_scan_inclusions`.
101 ///
102 /// Default: [
103 /// "**/.git",
104 /// "**/.svn",
105 /// "**/.hg",
106 /// "**/.jj",
107 /// "**/CVS",
108 /// "**/.DS_Store",
109 /// "**/Thumbs.db",
110 /// "**/.classpath",
111 /// "**/.settings"
112 /// ]
113 pub file_scan_exclusions: Option<Vec<String>>,
114
115 /// Always include files that match these globs when scanning for files, even if they're
116 /// ignored by git. This setting is overridden by `file_scan_exclusions`.
117 /// Default: [
118 /// ".env*",
119 /// "docker-compose.*.yml",
120 /// ]
121 pub file_scan_inclusions: Option<Vec<String>>,
122
123 /// Treat the files matching these globs as `.env` files.
124 /// Default: ["**/.env*", "**/*.pem", "**/*.key", "**/*.cert", "**/*.crt", "**/secrets.yml"]
125 pub private_files: Option<ExtendingVec<String>>,
126
127 /// Treat the files matching these globs as hidden files. You can hide hidden files in the project panel.
128 /// Default: ["**/.*"]
129 pub hidden_files: Option<Vec<String>>,
130
131 /// Treat the files matching these globs as read-only. These files can be opened and viewed,
132 /// but cannot be edited. This is useful for generated files, build outputs, or files from
133 /// external dependencies that should not be modified directly.
134 /// Default: []
135 pub read_only_files: Option<Vec<String>>,
136}
137
138#[with_fallible_options]
139#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom, Hash)]
140#[serde(rename_all = "snake_case")]
141pub struct LspSettings {
142 pub binary: Option<BinarySettings>,
143 /// Options passed to the language server at startup.
144 ///
145 /// Ref: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#initialize
146 ///
147 /// Consult the documentation for the specific language server to see which settings are supported.
148 pub initialization_options: Option<serde_json::Value>,
149 /// Language server settings.
150 ///
151 /// Ref: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_configuration
152 ///
153 /// Consult the documentation for the specific language server to see which settings are supported.
154 pub settings: Option<serde_json::Value>,
155 /// If the server supports sending tasks over LSP extensions,
156 /// this setting can be used to enable or disable them in Zed.
157 /// Default: true
158 #[serde(default = "default_true")]
159 pub enable_lsp_tasks: bool,
160 pub fetch: Option<FetchSettings>,
161}
162
163impl Default for LspSettings {
164 fn default() -> Self {
165 Self {
166 binary: None,
167 initialization_options: None,
168 settings: None,
169 enable_lsp_tasks: true,
170 fetch: None,
171 }
172 }
173}
174
175#[with_fallible_options]
176#[derive(
177 Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom, Hash,
178)]
179pub struct BinarySettings {
180 pub path: Option<String>,
181 pub arguments: Option<Vec<String>>,
182 pub env: Option<BTreeMap<String, String>>,
183 pub ignore_system_version: Option<bool>,
184}
185
186#[with_fallible_options]
187#[derive(
188 Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom, Hash,
189)]
190pub struct FetchSettings {
191 // Whether to consider pre-releases for fetching
192 pub pre_release: Option<bool>,
193}
194
195/// Common language server settings.
196#[with_fallible_options]
197#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)]
198pub struct GlobalLspSettingsContent {
199 /// Whether to show the LSP servers button in the status bar.
200 ///
201 /// Default: `true`
202 pub button: Option<bool>,
203 /// The maximum amount of time to wait for responses from language servers, in seconds.
204 /// A value of `0` will result in no timeout being applied (causing all LSP responses to wait indefinitely until completed).
205 ///
206 /// Default: `120`
207 pub request_timeout: Option<u64>,
208 /// Settings for language server notifications
209 pub notifications: Option<LspNotificationSettingsContent>,
210 /// Rules for rendering LSP semantic tokens.
211 pub semantic_token_rules: Option<SemanticTokenRules>,
212}
213
214#[with_fallible_options]
215#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, MergeFrom)]
216pub struct LspNotificationSettingsContent {
217 /// Timeout in milliseconds for automatically dismissing language server notifications.
218 /// Set to 0 to disable auto-dismiss.
219 ///
220 /// Default: 5000
221 pub dismiss_timeout_ms: Option<u64>,
222}
223
224/// Custom rules for rendering LSP semantic tokens.
225#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, JsonSchema)]
226#[serde(transparent)]
227pub struct SemanticTokenRules {
228 pub rules: Vec<SemanticTokenRule>,
229}
230
231impl crate::merge_from::MergeFrom for SemanticTokenRules {
232 fn merge_from(&mut self, other: &Self) {
233 self.rules.splice(0..0, other.rules.iter().cloned());
234 }
235}
236
237#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, JsonSchema)]
238#[serde(rename_all = "snake_case")]
239pub struct SemanticTokenRule {
240 pub token_type: Option<String>,
241 #[serde(default)]
242 pub token_modifiers: Vec<String>,
243 #[serde(default)]
244 pub style: Vec<String>,
245 pub foreground_color: Option<Rgba>,
246 pub background_color: Option<Rgba>,
247 pub underline: Option<SemanticTokenColorOverride>,
248 pub strikethrough: Option<SemanticTokenColorOverride>,
249 pub font_weight: Option<SemanticTokenFontWeight>,
250 pub font_style: Option<SemanticTokenFontStyle>,
251}
252
253#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema, MergeFrom)]
254#[serde(untagged)]
255pub enum SemanticTokenColorOverride {
256 InheritForeground(bool),
257 Replace(Rgba),
258}
259
260#[derive(
261 Copy,
262 Clone,
263 Debug,
264 Default,
265 Serialize,
266 Deserialize,
267 PartialEq,
268 Eq,
269 JsonSchema,
270 MergeFrom,
271 strum::VariantArray,
272 strum::VariantNames,
273)]
274#[serde(rename_all = "snake_case")]
275pub enum SemanticTokenFontWeight {
276 #[default]
277 Normal,
278 Bold,
279}
280
281#[derive(
282 Copy,
283 Clone,
284 Debug,
285 Default,
286 Serialize,
287 Deserialize,
288 PartialEq,
289 Eq,
290 JsonSchema,
291 MergeFrom,
292 strum::VariantArray,
293 strum::VariantNames,
294)]
295#[serde(rename_all = "snake_case")]
296pub enum SemanticTokenFontStyle {
297 #[default]
298 Normal,
299 Italic,
300}
301
302#[with_fallible_options]
303#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema, MergeFrom)]
304#[serde(rename_all = "snake_case")]
305pub struct DapSettingsContent {
306 pub binary: Option<String>,
307 pub args: Option<Vec<String>>,
308 pub env: Option<HashMap<String, String>>,
309}
310
311#[with_fallible_options]
312#[derive(
313 Default, Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, JsonSchema, MergeFrom,
314)]
315pub struct SessionSettingsContent {
316 /// Whether or not to restore unsaved buffers on restart.
317 ///
318 /// If this is true, user won't be prompted whether to save/discard
319 /// dirty files when closing the application.
320 ///
321 /// Default: true
322 pub restore_unsaved_buffers: Option<bool>,
323 /// Whether or not to skip worktree trust checks.
324 /// When trusted, project settings are synchronized automatically,
325 /// language and MCP servers are downloaded and started automatically.
326 ///
327 /// Default: false
328 pub trust_all_worktrees: Option<bool>,
329}
330
331#[derive(Deserialize, Serialize, Clone, PartialEq, Eq, JsonSchema, MergeFrom, Debug)]
332#[serde(untagged, rename_all = "snake_case")]
333pub enum ContextServerSettingsContent {
334 Stdio {
335 /// Whether the context server is enabled.
336 #[serde(default = "default_true")]
337 enabled: bool,
338 /// Whether to run the context server on the remote server when using remote development.
339 ///
340 /// If this is false, the context server will always run on the local machine.
341 ///
342 /// Default: false
343 #[serde(default)]
344 remote: bool,
345 #[serde(flatten)]
346 command: ContextServerCommand,
347 },
348 Http {
349 /// Whether the context server is enabled.
350 #[serde(default = "default_true")]
351 enabled: bool,
352 /// The URL of the remote context server.
353 url: String,
354 /// Optional headers to send.
355 #[serde(skip_serializing_if = "HashMap::is_empty", default)]
356 headers: HashMap<String, String>,
357 /// Timeout for tool calls in seconds. Defaults to global context_server_timeout if not specified.
358 timeout: Option<u64>,
359 },
360 Extension {
361 /// Whether the context server is enabled.
362 #[serde(default = "default_true")]
363 enabled: bool,
364 /// Whether to run the context server on the remote server when using remote development.
365 ///
366 /// If this is false, the context server will always run on the local machine.
367 ///
368 /// Default: false
369 #[serde(default)]
370 remote: bool,
371 /// The settings for this context server specified by the extension.
372 ///
373 /// Consult the documentation for the context server to see what settings
374 /// are supported.
375 settings: serde_json::Value,
376 },
377}
378
379impl ContextServerSettingsContent {
380 pub fn set_enabled(&mut self, enabled: bool) {
381 match self {
382 ContextServerSettingsContent::Stdio {
383 enabled: custom_enabled,
384 ..
385 } => {
386 *custom_enabled = enabled;
387 }
388 ContextServerSettingsContent::Extension {
389 enabled: ext_enabled,
390 ..
391 } => *ext_enabled = enabled,
392 ContextServerSettingsContent::Http {
393 enabled: remote_enabled,
394 ..
395 } => *remote_enabled = enabled,
396 }
397 }
398}
399
400#[with_fallible_options]
401#[derive(Deserialize, Serialize, Clone, PartialEq, Eq, JsonSchema, MergeFrom)]
402pub struct ContextServerCommand {
403 #[serde(rename = "command")]
404 pub path: PathBuf,
405 pub args: Vec<String>,
406 pub env: Option<HashMap<String, String>>,
407 /// Timeout for tool calls in seconds. Defaults to 60 if not specified.
408 pub timeout: Option<u64>,
409}
410
411impl std::fmt::Debug for ContextServerCommand {
412 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
413 let filtered_env = self.env.as_ref().map(|env| {
414 env.iter()
415 .map(|(k, v)| {
416 (
417 k,
418 if util::redact::should_redact(k) {
419 "[REDACTED]"
420 } else {
421 v
422 },
423 )
424 })
425 .collect::<Vec<_>>()
426 });
427
428 f.debug_struct("ContextServerCommand")
429 .field("path", &self.path)
430 .field("args", &self.args)
431 .field("env", &filtered_env)
432 .finish()
433 }
434}
435
436#[with_fallible_options]
437#[derive(Copy, Clone, Debug, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
438pub struct GitSettings {
439 /// Whether or not to enable git integration.
440 ///
441 /// Default: true
442 #[serde(flatten)]
443 pub enabled: Option<GitEnabledSettings>,
444 /// Whether or not to show the git gutter.
445 ///
446 /// Default: tracked_files
447 pub git_gutter: Option<GitGutterSetting>,
448 /// Sets the debounce threshold (in milliseconds) after which changes are reflected in the git gutter.
449 ///
450 /// Default: 0
451 pub gutter_debounce: Option<u64>,
452 /// Whether or not to show git blame data inline in
453 /// the currently focused line.
454 ///
455 /// Default: on
456 pub inline_blame: Option<InlineBlameSettings>,
457 /// Git blame settings.
458 pub blame: Option<BlameSettings>,
459 /// Which information to show in the branch picker.
460 ///
461 /// Default: on
462 pub branch_picker: Option<BranchPickerSettingsContent>,
463 /// How hunks are displayed visually in the editor.
464 ///
465 /// Default: staged_hollow
466 pub hunk_style: Option<GitHunkStyleSetting>,
467 /// How file paths are displayed in the git gutter.
468 ///
469 /// Default: file_name_first
470 pub path_style: Option<GitPathStyle>,
471}
472
473#[with_fallible_options]
474#[derive(Clone, Copy, Debug, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
475#[serde(rename_all = "snake_case")]
476pub struct GitEnabledSettings {
477 pub disable_git: Option<bool>,
478 pub enable_status: Option<bool>,
479 pub enable_diff: Option<bool>,
480}
481
482impl GitEnabledSettings {
483 pub fn is_git_status_enabled(&self) -> bool {
484 !self.disable_git.unwrap_or(false) && self.enable_status.unwrap_or(true)
485 }
486
487 pub fn is_git_diff_enabled(&self) -> bool {
488 !self.disable_git.unwrap_or(false) && self.enable_diff.unwrap_or(true)
489 }
490}
491
492#[derive(
493 Clone,
494 Copy,
495 Debug,
496 PartialEq,
497 Default,
498 Serialize,
499 Deserialize,
500 JsonSchema,
501 MergeFrom,
502 strum::VariantArray,
503 strum::VariantNames,
504)]
505#[serde(rename_all = "snake_case")]
506pub enum GitGutterSetting {
507 /// Show git gutter in tracked files.
508 #[default]
509 TrackedFiles,
510 /// Hide git gutter
511 Hide,
512}
513
514#[with_fallible_options]
515#[derive(Clone, Copy, Debug, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
516#[serde(rename_all = "snake_case")]
517pub struct InlineBlameSettings {
518 /// Whether or not to show git blame data inline in
519 /// the currently focused line.
520 ///
521 /// Default: true
522 pub enabled: Option<bool>,
523 /// Whether to only show the inline blame information
524 /// after a delay once the cursor stops moving.
525 ///
526 /// Default: 0
527 pub delay_ms: Option<DelayMs>,
528 /// The amount of padding between the end of the source line and the start
529 /// of the inline blame in units of columns.
530 ///
531 /// Default: 7
532 pub padding: Option<u32>,
533 /// The minimum column number to show the inline blame information at
534 ///
535 /// Default: 0
536 pub min_column: Option<u32>,
537 /// Whether to show commit summary as part of the inline blame.
538 ///
539 /// Default: false
540 pub show_commit_summary: Option<bool>,
541}
542
543#[with_fallible_options]
544#[derive(Clone, Copy, Debug, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
545#[serde(rename_all = "snake_case")]
546pub struct BlameSettings {
547 /// Whether to show the avatar of the author of the commit.
548 ///
549 /// Default: true
550 pub show_avatar: Option<bool>,
551}
552
553#[with_fallible_options]
554#[derive(Clone, Copy, PartialEq, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
555#[serde(rename_all = "snake_case")]
556pub struct BranchPickerSettingsContent {
557 /// Whether to show author name as part of the commit information.
558 ///
559 /// Default: false
560 pub show_author_name: Option<bool>,
561}
562
563#[derive(
564 Clone,
565 Copy,
566 PartialEq,
567 Debug,
568 Default,
569 Serialize,
570 Deserialize,
571 JsonSchema,
572 MergeFrom,
573 strum::VariantArray,
574 strum::VariantNames,
575)]
576#[serde(rename_all = "snake_case")]
577pub enum GitHunkStyleSetting {
578 /// Show unstaged hunks with a filled background and staged hunks hollow.
579 #[default]
580 StagedHollow,
581 /// Show unstaged hunks hollow and staged hunks with a filled background.
582 UnstagedHollow,
583}
584
585#[with_fallible_options]
586#[derive(
587 Copy,
588 Clone,
589 Debug,
590 PartialEq,
591 Default,
592 Serialize,
593 Deserialize,
594 JsonSchema,
595 MergeFrom,
596 strum::VariantArray,
597 strum::VariantNames,
598)]
599#[serde(rename_all = "snake_case")]
600pub enum GitPathStyle {
601 /// Show file name first, then path
602 #[default]
603 FileNameFirst,
604 /// Show full path first
605 FilePathFirst,
606}
607
608#[with_fallible_options]
609#[derive(Clone, Debug, PartialEq, Eq, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
610pub struct DiagnosticsSettingsContent {
611 /// Whether to show the project diagnostics button in the status bar.
612 pub button: Option<bool>,
613
614 /// Whether or not to include warning diagnostics.
615 ///
616 /// Default: true
617 pub include_warnings: Option<bool>,
618
619 /// Settings for using LSP pull diagnostics mechanism in Zed.
620 pub lsp_pull_diagnostics: Option<LspPullDiagnosticsSettingsContent>,
621
622 /// Settings for showing inline diagnostics.
623 pub inline: Option<InlineDiagnosticsSettingsContent>,
624}
625
626#[with_fallible_options]
627#[derive(
628 Clone, Copy, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq,
629)]
630pub struct LspPullDiagnosticsSettingsContent {
631 /// Whether to pull for diagnostics or not.
632 ///
633 /// Default: true
634 pub enabled: Option<bool>,
635 /// Minimum time to wait before pulling diagnostics from the language server(s).
636 /// 0 turns the debounce off.
637 ///
638 /// Default: 50
639 pub debounce_ms: Option<DelayMs>,
640}
641
642#[with_fallible_options]
643#[derive(
644 Clone, Copy, Debug, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Eq,
645)]
646pub struct InlineDiagnosticsSettingsContent {
647 /// Whether or not to show inline diagnostics
648 ///
649 /// Default: false
650 pub enabled: Option<bool>,
651 /// Whether to only show the inline diagnostics after a delay after the
652 /// last editor event.
653 ///
654 /// Default: 150
655 pub update_debounce_ms: Option<DelayMs>,
656 /// The amount of padding between the end of the source line and the start
657 /// of the inline diagnostic in units of columns.
658 ///
659 /// Default: 4
660 pub padding: Option<u32>,
661 /// The minimum column to display inline diagnostics. This setting can be
662 /// used to horizontally align inline diagnostics at some position. Lines
663 /// longer than this value will still push diagnostics further to the right.
664 ///
665 /// Default: 0
666 pub min_column: Option<u32>,
667
668 pub max_severity: Option<DiagnosticSeverityContent>,
669}
670
671#[with_fallible_options]
672#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema, MergeFrom)]
673pub struct NodeBinarySettings {
674 /// The path to the Node binary.
675 pub path: Option<String>,
676 /// The path to the npm binary Zed should use (defaults to `.path/../npm`).
677 pub npm_path: Option<String>,
678 /// If enabled, Zed will download its own copy of Node.
679 pub ignore_system_version: Option<bool>,
680}
681
682#[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
683#[serde(rename_all = "snake_case")]
684pub enum DirenvSettings {
685 /// Load direnv configuration through a shell hook
686 ShellHook,
687 /// Load direnv configuration directly using `direnv export json`
688 #[default]
689 Direct,
690 /// Do not load direnv configuration
691 Disabled,
692}
693
694#[derive(
695 Clone,
696 Copy,
697 Debug,
698 Eq,
699 PartialEq,
700 Ord,
701 PartialOrd,
702 Serialize,
703 Deserialize,
704 JsonSchema,
705 MergeFrom,
706 strum::VariantArray,
707 strum::VariantNames,
708)]
709#[serde(rename_all = "snake_case")]
710pub enum DiagnosticSeverityContent {
711 // No diagnostics are shown.
712 Off,
713 Error,
714 Warning,
715 Info,
716 Hint,
717 All,
718}
719
720/// A custom Git hosting provider.
721#[with_fallible_options]
722#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, JsonSchema, MergeFrom)]
723pub struct GitHostingProviderConfig {
724 /// The type of the provider.
725 ///
726 /// Must be one of `github`, `gitlab`, `bitbucket`, `gitea`, `forgejo`, or `source_hut`.
727 pub provider: GitHostingProviderKind,
728
729 /// The base URL for the provider (e.g., "https://code.corp.big.com").
730 pub base_url: String,
731
732 /// The display name for the provider (e.g., "BigCorp GitHub").
733 pub name: String,
734}
735
736#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)]
737#[serde(rename_all = "snake_case")]
738pub enum GitHostingProviderKind {
739 Github,
740 Gitlab,
741 Bitbucket,
742 Gitea,
743 Forgejo,
744 SourceHut,
745}