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