1use std::sync::Arc;
2
3use collections::HashMap;
4use derive_more::{Deref, DerefMut};
5use gpui::Global;
6use gpui::{App, ReadGlobal};
7use parking_lot::RwLock;
8
9use crate::Tool;
10
11#[derive(Default, Deref, DerefMut)]
12struct GlobalToolRegistry(Arc<ToolRegistry>);
13
14impl Global for GlobalToolRegistry {}
15
16#[derive(Default)]
17struct ToolRegistryState {
18 tools: HashMap<Arc<str>, Arc<dyn Tool>>,
19}
20
21#[derive(Default)]
22pub struct ToolRegistry {
23 state: RwLock<ToolRegistryState>,
24}
25
26impl ToolRegistry {
27 /// Returns the global [`ToolRegistry`].
28 pub fn global(cx: &App) -> Arc<Self> {
29 GlobalToolRegistry::global(cx).0.clone()
30 }
31
32 /// Returns the global [`ToolRegistry`].
33 ///
34 /// Inserts a default [`ToolRegistry`] if one does not yet exist.
35 pub fn default_global(cx: &mut App) -> Arc<Self> {
36 cx.default_global::<GlobalToolRegistry>().0.clone()
37 }
38
39 pub fn new() -> Arc<Self> {
40 Arc::new(Self {
41 state: RwLock::new(ToolRegistryState {
42 tools: HashMap::default(),
43 }),
44 })
45 }
46
47 /// Registers the provided [`Tool`].
48 pub fn register_tool(&self, tool: impl Tool) {
49 let mut state = self.state.write();
50 let tool_name: Arc<str> = tool.name().into();
51 state.tools.insert(tool_name, Arc::new(tool));
52 }
53
54 /// Unregisters the provided [`Tool`].
55 pub fn unregister_tool(&self, tool: impl Tool) {
56 self.unregister_tool_by_name(tool.name().as_str())
57 }
58
59 /// Unregisters the tool with the given name.
60 pub fn unregister_tool_by_name(&self, tool_name: &str) {
61 let mut state = self.state.write();
62 state.tools.remove(tool_name);
63 }
64
65 /// Returns the list of tools in the registry.
66 pub fn tools(&self) -> Vec<Arc<dyn Tool>> {
67 self.state.read().tools.values().cloned().collect()
68 }
69
70 /// Returns the [`Tool`] with the given name.
71 pub fn tool(&self, name: &str) -> Option<Arc<dyn Tool>> {
72 self.state.read().tools.get(name).cloned()
73 }
74}