1use assistant_slash_command::{SlashCommand, SlashCommandRegistry};
2use collections::HashMap;
3use gpui::AppContext;
4use parking_lot::Mutex;
5use std::sync::Arc;
6
7#[derive(Debug, 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<Arc<str>, 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 command_names(&self, cx: &AppContext) -> Vec<Arc<str>> {
34 let mut command_names = SlashCommandRegistry::global(cx).command_names();
35 command_names.extend(
36 self.state
37 .lock()
38 .context_server_commands_by_name
39 .keys()
40 .cloned(),
41 );
42
43 command_names
44 }
45
46 pub fn featured_command_names(&self, cx: &AppContext) -> Vec<Arc<str>> {
47 SlashCommandRegistry::global(cx).featured_command_names()
48 }
49
50 pub fn insert(&self, command: Arc<dyn SlashCommand>) -> SlashCommandId {
51 let mut state = self.state.lock();
52 let command_id = state.next_command_id;
53 state.next_command_id.0 += 1;
54 state
55 .context_server_commands_by_id
56 .insert(command_id, command.clone());
57 state.slash_commands_changed();
58 command_id
59 }
60
61 pub fn remove(&self, command_ids_to_remove: &[SlashCommandId]) {
62 let mut state = self.state.lock();
63 state
64 .context_server_commands_by_id
65 .retain(|id, _| !command_ids_to_remove.contains(id));
66 state.slash_commands_changed();
67 }
68}
69
70impl WorkingSetState {
71 fn slash_commands_changed(&mut self) {
72 self.context_server_commands_by_name.clear();
73 self.context_server_commands_by_name.extend(
74 self.context_server_commands_by_id
75 .values()
76 .map(|command| (command.name().into(), command.clone())),
77 );
78 }
79}