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 /// Settings for language server notifications
204 pub notifications: Option<LspNotificationSettingsContent>,
205 /// Rules for rendering LSP semantic tokens.
206 pub semantic_token_rules: Option<SemanticTokenRules>,
207}
208
209#[with_fallible_options]
210#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, MergeFrom)]
211pub struct LspNotificationSettingsContent {
212 /// Timeout in milliseconds for automatically dismissing language server notifications.
213 /// Set to 0 to disable auto-dismiss.
214 ///
215 /// Default: 5000
216 pub dismiss_timeout_ms: Option<u64>,
217}
218
219/// Custom rules for rendering LSP semantic tokens.
220#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, JsonSchema)]
221#[serde(transparent)]
222pub struct SemanticTokenRules {
223 pub rules: Vec<SemanticTokenRule>,
224}
225
226impl crate::merge_from::MergeFrom for SemanticTokenRules {
227 fn merge_from(&mut self, other: &Self) {
228 self.rules.splice(0..0, other.rules.iter().cloned());
229 }
230}
231
232#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, JsonSchema)]
233#[serde(rename_all = "snake_case")]
234pub struct SemanticTokenRule {
235 pub token_type: Option<String>,
236 #[serde(default)]
237 pub token_modifiers: Vec<String>,
238 #[serde(default)]
239 pub style: Vec<String>,
240 pub foreground_color: Option<Rgba>,
241 pub background_color: Option<Rgba>,
242 pub underline: Option<SemanticTokenColorOverride>,
243 pub strikethrough: Option<SemanticTokenColorOverride>,
244 pub font_weight: Option<SemanticTokenFontWeight>,
245 pub font_style: Option<SemanticTokenFontStyle>,
246}
247
248#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema, MergeFrom)]
249#[serde(untagged)]
250pub enum SemanticTokenColorOverride {
251 InheritForeground(bool),
252 Replace(Rgba),
253}
254
255#[derive(
256 Copy,
257 Clone,
258 Debug,
259 Default,
260 Serialize,
261 Deserialize,
262 PartialEq,
263 Eq,
264 JsonSchema,
265 MergeFrom,
266 strum::VariantArray,
267 strum::VariantNames,
268)]
269#[serde(rename_all = "snake_case")]
270pub enum SemanticTokenFontWeight {
271 #[default]
272 Normal,
273 Bold,
274}
275
276#[derive(
277 Copy,
278 Clone,
279 Debug,
280 Default,
281 Serialize,
282 Deserialize,
283 PartialEq,
284 Eq,
285 JsonSchema,
286 MergeFrom,
287 strum::VariantArray,
288 strum::VariantNames,
289)]
290#[serde(rename_all = "snake_case")]
291pub enum SemanticTokenFontStyle {
292 #[default]
293 Normal,
294 Italic,
295}
296
297#[with_fallible_options]
298#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema, MergeFrom)]
299#[serde(rename_all = "snake_case")]
300pub struct DapSettingsContent {
301 pub binary: Option<String>,
302 pub args: Option<Vec<String>>,
303 pub env: Option<HashMap<String, String>>,
304}
305
306#[with_fallible_options]
307#[derive(
308 Default, Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, JsonSchema, MergeFrom,
309)]
310pub struct SessionSettingsContent {
311 /// Whether or not to restore unsaved buffers on restart.
312 ///
313 /// If this is true, user won't be prompted whether to save/discard
314 /// dirty files when closing the application.
315 ///
316 /// Default: true
317 pub restore_unsaved_buffers: Option<bool>,
318 /// Whether or not to skip worktree trust checks.
319 /// When trusted, project settings are synchronized automatically,
320 /// language and MCP servers are downloaded and started automatically.
321 ///
322 /// Default: false
323 pub trust_all_worktrees: Option<bool>,
324}
325
326#[derive(Deserialize, Serialize, Clone, PartialEq, Eq, JsonSchema, MergeFrom, Debug)]
327#[serde(untagged, rename_all = "snake_case")]
328pub enum ContextServerSettingsContent {
329 Stdio {
330 /// Whether the context server is enabled.
331 #[serde(default = "default_true")]
332 enabled: bool,
333 /// Whether to run the context server on the remote server when using remote development.
334 ///
335 /// If this is false, the context server will always run on the local machine.
336 ///
337 /// Default: false
338 #[serde(default)]
339 remote: bool,
340 #[serde(flatten)]
341 command: ContextServerCommand,
342 },
343 Http {
344 /// Whether the context server is enabled.
345 #[serde(default = "default_true")]
346 enabled: bool,
347 /// The URL of the remote context server.
348 url: String,
349 /// Optional headers to send.
350 #[serde(skip_serializing_if = "HashMap::is_empty", default)]
351 headers: HashMap<String, String>,
352 /// Timeout for tool calls in seconds. Defaults to global context_server_timeout if not specified.
353 timeout: Option<u64>,
354 },
355 Extension {
356 /// Whether the context server is enabled.
357 #[serde(default = "default_true")]
358 enabled: bool,
359 /// Whether to run the context server on the remote server when using remote development.
360 ///
361 /// If this is false, the context server will always run on the local machine.
362 ///
363 /// Default: false
364 #[serde(default)]
365 remote: bool,
366 /// The settings for this context server specified by the extension.
367 ///
368 /// Consult the documentation for the context server to see what settings
369 /// are supported.
370 settings: serde_json::Value,
371 },
372}
373
374impl ContextServerSettingsContent {
375 pub fn set_enabled(&mut self, enabled: bool) {
376 match self {
377 ContextServerSettingsContent::Stdio {
378 enabled: custom_enabled,
379 ..
380 } => {
381 *custom_enabled = enabled;
382 }
383 ContextServerSettingsContent::Extension {
384 enabled: ext_enabled,
385 ..
386 } => *ext_enabled = enabled,
387 ContextServerSettingsContent::Http {
388 enabled: remote_enabled,
389 ..
390 } => *remote_enabled = enabled,
391 }
392 }
393}
394
395#[with_fallible_options]
396#[derive(Deserialize, Serialize, Clone, PartialEq, Eq, JsonSchema, MergeFrom)]
397pub struct ContextServerCommand {
398 #[serde(rename = "command")]
399 pub path: PathBuf,
400 pub args: Vec<String>,
401 pub env: Option<HashMap<String, String>>,
402 /// Timeout for tool calls in seconds. Defaults to 60 if not specified.
403 pub timeout: Option<u64>,
404}
405
406impl std::fmt::Debug for ContextServerCommand {
407 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
408 let filtered_env = self.env.as_ref().map(|env| {
409 env.iter()
410 .map(|(k, v)| {
411 (
412 k,
413 if util::redact::should_redact(k) {
414 "[REDACTED]"
415 } else {
416 v
417 },
418 )
419 })
420 .collect::<Vec<_>>()
421 });
422
423 f.debug_struct("ContextServerCommand")
424 .field("path", &self.path)
425 .field("args", &self.args)
426 .field("env", &filtered_env)
427 .finish()
428 }
429}
430
431#[with_fallible_options]
432#[derive(Copy, Clone, Debug, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
433pub struct GitSettings {
434 /// Whether or not to enable git integration.
435 ///
436 /// Default: true
437 #[serde(flatten)]
438 pub enabled: Option<GitEnabledSettings>,
439 /// Whether or not to show the git gutter.
440 ///
441 /// Default: tracked_files
442 pub git_gutter: Option<GitGutterSetting>,
443 /// Sets the debounce threshold (in milliseconds) after which changes are reflected in the git gutter.
444 ///
445 /// Default: 0
446 pub gutter_debounce: Option<u64>,
447 /// Whether or not to show git blame data inline in
448 /// the currently focused line.
449 ///
450 /// Default: on
451 pub inline_blame: Option<InlineBlameSettings>,
452 /// Git blame settings.
453 pub blame: Option<BlameSettings>,
454 /// Which information to show in the branch picker.
455 ///
456 /// Default: on
457 pub branch_picker: Option<BranchPickerSettingsContent>,
458 /// How hunks are displayed visually in the editor.
459 ///
460 /// Default: staged_hollow
461 pub hunk_style: Option<GitHunkStyleSetting>,
462 /// How file paths are displayed in the git gutter.
463 ///
464 /// Default: file_name_first
465 pub path_style: Option<GitPathStyle>,
466}
467
468#[with_fallible_options]
469#[derive(Clone, Copy, Debug, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
470#[serde(rename_all = "snake_case")]
471pub struct GitEnabledSettings {
472 pub disable_git: Option<bool>,
473 pub enable_status: Option<bool>,
474 pub enable_diff: Option<bool>,
475}
476
477impl GitEnabledSettings {
478 pub fn is_git_status_enabled(&self) -> bool {
479 !self.disable_git.unwrap_or(false) && self.enable_status.unwrap_or(true)
480 }
481
482 pub fn is_git_diff_enabled(&self) -> bool {
483 !self.disable_git.unwrap_or(false) && self.enable_diff.unwrap_or(true)
484 }
485}
486
487#[derive(
488 Clone,
489 Copy,
490 Debug,
491 PartialEq,
492 Default,
493 Serialize,
494 Deserialize,
495 JsonSchema,
496 MergeFrom,
497 strum::VariantArray,
498 strum::VariantNames,
499)]
500#[serde(rename_all = "snake_case")]
501pub enum GitGutterSetting {
502 /// Show git gutter in tracked files.
503 #[default]
504 TrackedFiles,
505 /// Hide git gutter
506 Hide,
507}
508
509#[with_fallible_options]
510#[derive(Clone, Copy, Debug, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
511#[serde(rename_all = "snake_case")]
512pub struct InlineBlameSettings {
513 /// Whether or not to show git blame data inline in
514 /// the currently focused line.
515 ///
516 /// Default: true
517 pub enabled: Option<bool>,
518 /// Whether to only show the inline blame information
519 /// after a delay once the cursor stops moving.
520 ///
521 /// Default: 0
522 pub delay_ms: Option<DelayMs>,
523 /// The amount of padding between the end of the source line and the start
524 /// of the inline blame in units of columns.
525 ///
526 /// Default: 7
527 pub padding: Option<u32>,
528 /// The minimum column number to show the inline blame information at
529 ///
530 /// Default: 0
531 pub min_column: Option<u32>,
532 /// Whether to show commit summary as part of the inline blame.
533 ///
534 /// Default: false
535 pub show_commit_summary: Option<bool>,
536}
537
538#[with_fallible_options]
539#[derive(Clone, Copy, Debug, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
540#[serde(rename_all = "snake_case")]
541pub struct BlameSettings {
542 /// Whether to show the avatar of the author of the commit.
543 ///
544 /// Default: true
545 pub show_avatar: Option<bool>,
546}
547
548#[with_fallible_options]
549#[derive(Clone, Copy, PartialEq, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
550#[serde(rename_all = "snake_case")]
551pub struct BranchPickerSettingsContent {
552 /// Whether to show author name as part of the commit information.
553 ///
554 /// Default: false
555 pub show_author_name: Option<bool>,
556}
557
558#[derive(
559 Clone,
560 Copy,
561 PartialEq,
562 Debug,
563 Default,
564 Serialize,
565 Deserialize,
566 JsonSchema,
567 MergeFrom,
568 strum::VariantArray,
569 strum::VariantNames,
570)]
571#[serde(rename_all = "snake_case")]
572pub enum GitHunkStyleSetting {
573 /// Show unstaged hunks with a filled background and staged hunks hollow.
574 #[default]
575 StagedHollow,
576 /// Show unstaged hunks hollow and staged hunks with a filled background.
577 UnstagedHollow,
578}
579
580#[with_fallible_options]
581#[derive(
582 Copy,
583 Clone,
584 Debug,
585 PartialEq,
586 Default,
587 Serialize,
588 Deserialize,
589 JsonSchema,
590 MergeFrom,
591 strum::VariantArray,
592 strum::VariantNames,
593)]
594#[serde(rename_all = "snake_case")]
595pub enum GitPathStyle {
596 /// Show file name first, then path
597 #[default]
598 FileNameFirst,
599 /// Show full path first
600 FilePathFirst,
601}
602
603#[with_fallible_options]
604#[derive(Clone, Debug, PartialEq, Eq, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
605pub struct DiagnosticsSettingsContent {
606 /// Whether to show the project diagnostics button in the status bar.
607 pub button: Option<bool>,
608
609 /// Whether or not to include warning diagnostics.
610 ///
611 /// Default: true
612 pub include_warnings: Option<bool>,
613
614 /// Settings for using LSP pull diagnostics mechanism in Zed.
615 pub lsp_pull_diagnostics: Option<LspPullDiagnosticsSettingsContent>,
616
617 /// Settings for showing inline diagnostics.
618 pub inline: Option<InlineDiagnosticsSettingsContent>,
619}
620
621#[with_fallible_options]
622#[derive(
623 Clone, Copy, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq,
624)]
625pub struct LspPullDiagnosticsSettingsContent {
626 /// Whether to pull for diagnostics or not.
627 ///
628 /// Default: true
629 pub enabled: Option<bool>,
630 /// Minimum time to wait before pulling diagnostics from the language server(s).
631 /// 0 turns the debounce off.
632 ///
633 /// Default: 50
634 pub debounce_ms: Option<DelayMs>,
635}
636
637#[with_fallible_options]
638#[derive(
639 Clone, Copy, Debug, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Eq,
640)]
641pub struct InlineDiagnosticsSettingsContent {
642 /// Whether or not to show inline diagnostics
643 ///
644 /// Default: false
645 pub enabled: Option<bool>,
646 /// Whether to only show the inline diagnostics after a delay after the
647 /// last editor event.
648 ///
649 /// Default: 150
650 pub update_debounce_ms: Option<DelayMs>,
651 /// The amount of padding between the end of the source line and the start
652 /// of the inline diagnostic in units of columns.
653 ///
654 /// Default: 4
655 pub padding: Option<u32>,
656 /// The minimum column to display inline diagnostics. This setting can be
657 /// used to horizontally align inline diagnostics at some position. Lines
658 /// longer than this value will still push diagnostics further to the right.
659 ///
660 /// Default: 0
661 pub min_column: Option<u32>,
662
663 pub max_severity: Option<DiagnosticSeverityContent>,
664}
665
666#[with_fallible_options]
667#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema, MergeFrom)]
668pub struct NodeBinarySettings {
669 /// The path to the Node binary.
670 pub path: Option<String>,
671 /// The path to the npm binary Zed should use (defaults to `.path/../npm`).
672 pub npm_path: Option<String>,
673 /// If enabled, Zed will download its own copy of Node.
674 pub ignore_system_version: Option<bool>,
675}
676
677#[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
678#[serde(rename_all = "snake_case")]
679pub enum DirenvSettings {
680 /// Load direnv configuration through a shell hook
681 ShellHook,
682 /// Load direnv configuration directly using `direnv export json`
683 #[default]
684 Direct,
685 /// Do not load direnv configuration
686 Disabled,
687}
688
689#[derive(
690 Clone,
691 Copy,
692 Debug,
693 Eq,
694 PartialEq,
695 Ord,
696 PartialOrd,
697 Serialize,
698 Deserialize,
699 JsonSchema,
700 MergeFrom,
701 strum::VariantArray,
702 strum::VariantNames,
703)]
704#[serde(rename_all = "snake_case")]
705pub enum DiagnosticSeverityContent {
706 // No diagnostics are shown.
707 Off,
708 Error,
709 Warning,
710 Info,
711 Hint,
712 All,
713}
714
715/// A custom Git hosting provider.
716#[with_fallible_options]
717#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, JsonSchema, MergeFrom)]
718pub struct GitHostingProviderConfig {
719 /// The type of the provider.
720 ///
721 /// Must be one of `github`, `gitlab`, `bitbucket`, `gitea`, `forgejo`, or `source_hut`.
722 pub provider: GitHostingProviderKind,
723
724 /// The base URL for the provider (e.g., "https://code.corp.big.com").
725 pub base_url: String,
726
727 /// The display name for the provider (e.g., "BigCorp GitHub").
728 pub name: String,
729}
730
731#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)]
732#[serde(rename_all = "snake_case")]
733pub enum GitHostingProviderKind {
734 Github,
735 Gitlab,
736 Bitbucket,
737 Gitea,
738 Forgejo,
739 SourceHut,
740}