1use std::sync::Arc;
2
3use anyhow::Result;
4use collections::HashMap;
5use gpui::{App, AppContext as _, AsyncApp, Entity, Global, ReadGlobal, Task};
6use project::Project;
7
8use crate::ServerCommand;
9
10pub type ContextServerFactory =
11 Arc<dyn Fn(Entity<Project>, &AsyncApp) -> Task<Result<ServerCommand>> + Send + Sync + 'static>;
12
13struct GlobalContextServerFactoryRegistry(Entity<ContextServerFactoryRegistry>);
14
15impl Global for GlobalContextServerFactoryRegistry {}
16
17#[derive(Default)]
18pub struct ContextServerFactoryRegistry {
19 context_servers: HashMap<Arc<str>, ContextServerFactory>,
20}
21
22impl ContextServerFactoryRegistry {
23 /// Returns the global [`ContextServerFactoryRegistry`].
24 pub fn global(cx: &App) -> Entity<Self> {
25 GlobalContextServerFactoryRegistry::global(cx).0.clone()
26 }
27
28 /// Returns the global [`ContextServerFactoryRegistry`].
29 ///
30 /// Inserts a default [`ContextServerFactoryRegistry`] if one does not yet exist.
31 pub fn default_global(cx: &mut App) -> Entity<Self> {
32 if !cx.has_global::<GlobalContextServerFactoryRegistry>() {
33 let registry = cx.new(|_| Self::new());
34 cx.set_global(GlobalContextServerFactoryRegistry(registry));
35 }
36 cx.global::<GlobalContextServerFactoryRegistry>().0.clone()
37 }
38
39 pub fn new() -> Self {
40 Self {
41 context_servers: HashMap::default(),
42 }
43 }
44
45 pub fn context_server_factories(&self) -> Vec<(Arc<str>, ContextServerFactory)> {
46 self.context_servers
47 .iter()
48 .map(|(id, factory)| (id.clone(), factory.clone()))
49 .collect()
50 }
51
52 /// Registers the provided [`ContextServerFactory`].
53 pub fn register_server_factory(&mut self, id: Arc<str>, factory: ContextServerFactory) {
54 self.context_servers.insert(id, factory);
55 }
56
57 /// Unregisters the [`ContextServerFactory`] for the server with the given ID.
58 pub fn unregister_server_factory_by_id(&mut self, server_id: &str) {
59 self.context_servers.remove(server_id);
60 }
61}