slash_command_registry.rs

 1use std::sync::Arc;
 2
 3use collections::HashMap;
 4use derive_more::{Deref, DerefMut};
 5use gpui::Global;
 6use gpui::{AppContext, ReadGlobal};
 7use parking_lot::RwLock;
 8
 9use crate::SlashCommand;
10
11#[derive(Default, Deref, DerefMut)]
12struct GlobalSlashCommandRegistry(Arc<SlashCommandRegistry>);
13
14impl Global for GlobalSlashCommandRegistry {}
15
16#[derive(Default)]
17struct SlashCommandRegistryState {
18    commands: HashMap<Arc<str>, Arc<dyn SlashCommand>>,
19}
20
21#[derive(Default)]
22pub struct SlashCommandRegistry {
23    state: RwLock<SlashCommandRegistryState>,
24}
25
26impl SlashCommandRegistry {
27    /// Returns the global [`SlashCommandRegistry`].
28    pub fn global(cx: &AppContext) -> Arc<Self> {
29        GlobalSlashCommandRegistry::global(cx).0.clone()
30    }
31
32    /// Returns the global [`SlashCommandRegistry`].
33    ///
34    /// Inserts a default [`SlashCommandRegistry`] if one does not yet exist.
35    pub fn default_global(cx: &mut AppContext) -> Arc<Self> {
36        cx.default_global::<GlobalSlashCommandRegistry>().0.clone()
37    }
38
39    pub fn new() -> Arc<Self> {
40        Arc::new(Self {
41            state: RwLock::new(SlashCommandRegistryState {
42                commands: HashMap::default(),
43            }),
44        })
45    }
46
47    /// Registers the provided [`SlashCommand`].
48    pub fn register_command(&self, command: impl SlashCommand) {
49        self.state
50            .write()
51            .commands
52            .insert(command.name().into(), Arc::new(command));
53    }
54
55    /// Returns the names of registered [`SlashCommand`]s.
56    pub fn command_names(&self) -> Vec<Arc<str>> {
57        self.state.read().commands.keys().cloned().collect()
58    }
59
60    /// Returns the [`SlashCommand`] with the given name.
61    pub fn command(&self, name: &str) -> Option<Arc<dyn SlashCommand>> {
62        self.state.read().commands.get(name).cloned()
63    }
64}