1use crate::prompt_library::PromptStore;
2use anyhow::{anyhow, Result};
3use assistant_slash_command::{
4 ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
5 SlashCommandResult,
6};
7use gpui::{Task, WeakView};
8use language::{BufferSnapshot, LspAdapterDelegate};
9use std::{
10 fmt::Write,
11 sync::{atomic::AtomicBool, Arc},
12};
13use ui::prelude::*;
14use workspace::Workspace;
15
16pub(crate) 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 "Insert Default Prompt".into()
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<WeakView<Workspace>>,
40 _cx: &mut WindowContext,
41 ) -> Task<Result<Vec<ArgumentCompletion>>> {
42 Task::ready(Err(anyhow!("this command does not require argument")))
43 }
44
45 fn run(
46 self: Arc<Self>,
47 _arguments: &[String],
48 _context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
49 _context_buffer: BufferSnapshot,
50 _workspace: WeakView<Workspace>,
51 _delegate: Option<Arc<dyn LspAdapterDelegate>>,
52 cx: &mut WindowContext,
53 ) -> Task<SlashCommandResult> {
54 let store = PromptStore::global(cx);
55 cx.background_executor().spawn(async move {
56 let store = store.await?;
57 let prompts = store.default_prompt_metadata();
58
59 let mut text = String::new();
60 text.push('\n');
61 for prompt in prompts {
62 if let Some(title) = prompt.title {
63 writeln!(text, "/prompt {}", title).unwrap();
64 }
65 }
66 text.pop();
67
68 if text.is_empty() {
69 text.push('\n');
70 }
71
72 if !text.ends_with('\n') {
73 text.push('\n');
74 }
75
76 Ok(SlashCommandOutput {
77 sections: vec![SlashCommandOutputSection {
78 range: 0..text.len(),
79 icon: IconName::Library,
80 label: "Default".into(),
81 metadata: None,
82 }],
83 text,
84 run_commands_in_text: true,
85 }
86 .to_event_stream())
87 })
88 }
89}