1use std::sync::Arc;
2
3use anyhow::Result;
4use collections::HashMap;
5use extension::ContextServerConfiguration;
6use gpui::{App, AppContext as _, AsyncApp, Entity, Global, ReadGlobal, Task};
7use project::Project;
8
9use crate::ServerCommand;
10
11pub trait ContextServerDescriptor {
12 fn command(&self, project: Entity<Project>, cx: &AsyncApp) -> Task<Result<ServerCommand>>;
13 fn configuration(
14 &self,
15 project: Entity<Project>,
16 cx: &AsyncApp,
17 ) -> Task<Result<Option<ContextServerConfiguration>>>;
18}
19
20struct GlobalContextServerDescriptorRegistry(Entity<ContextServerDescriptorRegistry>);
21
22impl Global for GlobalContextServerDescriptorRegistry {}
23
24#[derive(Default)]
25pub struct ContextServerDescriptorRegistry {
26 context_servers: HashMap<Arc<str>, Arc<dyn ContextServerDescriptor>>,
27}
28
29impl ContextServerDescriptorRegistry {
30 /// Returns the global [`ContextServerDescriptorRegistry`].
31 pub fn global(cx: &App) -> Entity<Self> {
32 GlobalContextServerDescriptorRegistry::global(cx).0.clone()
33 }
34
35 /// Returns the global [`ContextServerDescriptorRegistry`].
36 ///
37 /// Inserts a default [`ContextServerDescriptorRegistry`] if one does not yet exist.
38 pub fn default_global(cx: &mut App) -> Entity<Self> {
39 if !cx.has_global::<GlobalContextServerDescriptorRegistry>() {
40 let registry = cx.new(|_| Self::new());
41 cx.set_global(GlobalContextServerDescriptorRegistry(registry));
42 }
43 cx.global::<GlobalContextServerDescriptorRegistry>()
44 .0
45 .clone()
46 }
47
48 pub fn new() -> Self {
49 Self {
50 context_servers: HashMap::default(),
51 }
52 }
53
54 pub fn context_server_descriptors(&self) -> Vec<(Arc<str>, Arc<dyn ContextServerDescriptor>)> {
55 self.context_servers
56 .iter()
57 .map(|(id, factory)| (id.clone(), factory.clone()))
58 .collect()
59 }
60
61 pub fn context_server_descriptor(&self, id: &str) -> Option<Arc<dyn ContextServerDescriptor>> {
62 self.context_servers.get(id).cloned()
63 }
64
65 /// Registers the provided [`ContextServerDescriptor`].
66 pub fn register_context_server_descriptor(
67 &mut self,
68 id: Arc<str>,
69 descriptor: Arc<dyn ContextServerDescriptor>,
70 ) {
71 self.context_servers.insert(id, descriptor);
72 }
73
74 /// Unregisters the [`ContextServerDescriptor`] for the server with the given ID.
75 pub fn unregister_context_server_descriptor_by_id(&mut self, server_id: &str) {
76 self.context_servers.remove(server_id);
77 }
78}