1use anyhow::{Result, anyhow};
2use assistant_slash_command::{
3 ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
4 SlashCommandResult,
5};
6use gpui::{Task, WeakEntity};
7use language::{BufferSnapshot, LspAdapterDelegate};
8use prompt_store::PromptStore;
9use std::{
10 fmt::Write,
11 sync::{Arc, atomic::AtomicBool},
12};
13use ui::prelude::*;
14use workspace::Workspace;
15
16pub struct DefaultSlashCommand;
17
18impl SlashCommand for DefaultSlashCommand {
19 fn name(&self) -> String {
20 "default".into()
21 }
22
23 fn description(&self) -> String {
24 "Insert default prompt".into()
25 }
26
27 fn menu_text(&self) -> String {
28 self.description()
29 }
30
31 fn requires_argument(&self) -> bool {
32 false
33 }
34
35 fn complete_argument(
36 self: Arc<Self>,
37 _arguments: &[String],
38 _cancellation_flag: Arc<AtomicBool>,
39 _workspace: Option<WeakEntity<Workspace>>,
40 _window: &mut Window,
41 _cx: &mut App,
42 ) -> Task<Result<Vec<ArgumentCompletion>>> {
43 Task::ready(Err(anyhow!("this command does not require argument")))
44 }
45
46 fn run(
47 self: Arc<Self>,
48 _arguments: &[String],
49 _context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
50 _context_buffer: BufferSnapshot,
51 _workspace: WeakEntity<Workspace>,
52 _delegate: Option<Arc<dyn LspAdapterDelegate>>,
53 _window: &mut Window,
54 cx: &mut App,
55 ) -> Task<SlashCommandResult> {
56 let store = PromptStore::global(cx);
57 cx.spawn(async move |cx| {
58 let store = store.await?;
59 let prompts = store.read_with(cx, |store, _cx| store.default_prompt_metadata())?;
60
61 let mut text = String::new();
62 text.push('\n');
63 for prompt in prompts {
64 if let Some(title) = prompt.title {
65 writeln!(text, "/prompt {}", title).unwrap();
66 }
67 }
68 text.pop();
69
70 if text.is_empty() {
71 text.push('\n');
72 }
73
74 if !text.ends_with('\n') {
75 text.push('\n');
76 }
77
78 Ok(SlashCommandOutput {
79 sections: vec![SlashCommandOutputSection {
80 range: 0..text.len(),
81 icon: IconName::Library,
82 label: "Default".into(),
83 metadata: None,
84 }],
85 text,
86 run_commands_in_text: true,
87 }
88 .into_event_stream())
89 })
90 }
91}