slash_command_working_set.rs

 1use assistant_slash_command::{SlashCommand, SlashCommandRegistry};
 2use collections::HashMap;
 3use gpui::AppContext;
 4use parking_lot::Mutex;
 5use std::sync::Arc;
 6
 7#[derive(Copy, Clone, PartialEq, Eq, Hash, Default)]
 8pub struct SlashCommandId(usize);
 9
10/// A working set of slash commands for use in one instance of the Assistant Panel.
11#[derive(Default)]
12pub struct SlashCommandWorkingSet {
13    state: Mutex<WorkingSetState>,
14}
15
16#[derive(Default)]
17struct WorkingSetState {
18    context_server_commands_by_id: HashMap<SlashCommandId, Arc<dyn SlashCommand>>,
19    context_server_commands_by_name: HashMap<String, Arc<dyn SlashCommand>>,
20    next_command_id: SlashCommandId,
21}
22
23impl SlashCommandWorkingSet {
24    pub fn command(&self, name: &str, cx: &AppContext) -> Option<Arc<dyn SlashCommand>> {
25        self.state
26            .lock()
27            .context_server_commands_by_name
28            .get(name)
29            .cloned()
30            .or_else(|| SlashCommandRegistry::global(cx).command(name))
31    }
32
33    pub fn featured_command_names(&self, cx: &AppContext) -> Vec<Arc<str>> {
34        SlashCommandRegistry::global(cx).featured_command_names()
35    }
36
37    pub fn insert(&self, command: Arc<dyn SlashCommand>) -> SlashCommandId {
38        let mut state = self.state.lock();
39        let command_id = state.next_command_id;
40        state.next_command_id.0 += 1;
41        state
42            .context_server_commands_by_id
43            .insert(command_id, command.clone());
44        state.slash_commands_changed();
45        command_id
46    }
47
48    pub fn remove(&self, command_ids_to_remove: &[SlashCommandId]) {
49        let mut state = self.state.lock();
50        state
51            .context_server_commands_by_id
52            .retain(|id, _| !command_ids_to_remove.contains(id));
53        state.slash_commands_changed();
54    }
55}
56
57impl WorkingSetState {
58    fn slash_commands_changed(&mut self) {
59        self.context_server_commands_by_name.clear();
60        self.context_server_commands_by_name.extend(
61            self.context_server_commands_by_id
62                .values()
63                .map(|command| (command.name(), command.clone())),
64        );
65    }
66}