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