use std::sync::Arc; use collections::HashMap; use derive_more::{Deref, DerefMut}; use gpui::Global; use gpui::{AppContext, ReadGlobal}; use parking_lot::RwLock; use crate::Tool; #[derive(Default, Deref, DerefMut)] struct GlobalToolRegistry(Arc); impl Global for GlobalToolRegistry {} #[derive(Default)] struct ToolRegistryState { tools: HashMap, Arc>, } #[derive(Default)] pub struct ToolRegistry { state: RwLock, } impl ToolRegistry { /// Returns the global [`ToolRegistry`]. pub fn global(cx: &AppContext) -> Arc { GlobalToolRegistry::global(cx).0.clone() } /// Returns the global [`ToolRegistry`]. /// /// Inserts a default [`ToolRegistry`] if one does not yet exist. pub fn default_global(cx: &mut AppContext) -> Arc { cx.default_global::().0.clone() } pub fn new() -> Arc { Arc::new(Self { state: RwLock::new(ToolRegistryState { tools: HashMap::default(), }), }) } /// Registers the provided [`Tool`]. pub fn register_tool(&self, tool: impl Tool) { let mut state = self.state.write(); let tool_name: Arc = tool.name().into(); state.tools.insert(tool_name, Arc::new(tool)); } /// Unregisters the provided [`Tool`]. pub fn unregister_tool(&self, tool: impl Tool) { self.unregister_tool_by_name(tool.name().as_str()) } /// Unregisters the tool with the given name. pub fn unregister_tool_by_name(&self, tool_name: &str) { let mut state = self.state.write(); state.tools.remove(tool_name); } /// Returns the list of tools in the registry. pub fn tools(&self) -> Vec> { self.state.read().tools.values().cloned().collect() } /// Returns the [`Tool`] with the given name. pub fn tool(&self, name: &str) -> Option> { self.state.read().tools.get(name).cloned() } }