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}