1use crate::wasm_host::{WasmExtension, WasmHost};
2use anyhow::{anyhow, Result};
3use assistant_slash_command::{SlashCommand, SlashCommandOutput};
4use futures::FutureExt;
5use gpui::{AppContext, IntoElement, Task, WeakView, WindowContext};
6use language::LspAdapterDelegate;
7use std::sync::{atomic::AtomicBool, Arc};
8use wasmtime_wasi::WasiView;
9use workspace::Workspace;
10
11pub struct ExtensionSlashCommand {
12 pub(crate) extension: WasmExtension,
13 #[allow(unused)]
14 pub(crate) host: Arc<WasmHost>,
15 pub(crate) command: crate::wit::SlashCommand,
16}
17
18impl SlashCommand for ExtensionSlashCommand {
19 fn name(&self) -> String {
20 self.command.name.clone()
21 }
22
23 fn description(&self) -> String {
24 self.command.description.clone()
25 }
26
27 fn tooltip_text(&self) -> String {
28 self.command.tooltip_text.clone()
29 }
30
31 fn requires_argument(&self) -> bool {
32 self.command.requires_argument
33 }
34
35 fn complete_argument(
36 &self,
37 _query: String,
38 _cancel: Arc<AtomicBool>,
39 _cx: &mut AppContext,
40 ) -> Task<Result<Vec<String>>> {
41 Task::ready(Ok(Vec::new()))
42 }
43
44 fn run(
45 self: Arc<Self>,
46 argument: Option<&str>,
47 _workspace: WeakView<Workspace>,
48 delegate: Arc<dyn LspAdapterDelegate>,
49 cx: &mut WindowContext,
50 ) -> Task<Result<SlashCommandOutput>> {
51 let argument = argument.map(|arg| arg.to_string());
52 let output = cx.background_executor().spawn(async move {
53 let output = self
54 .extension
55 .call({
56 let this = self.clone();
57 move |extension, store| {
58 async move {
59 let resource = store.data_mut().table().push(delegate)?;
60 let output = extension
61 .call_run_slash_command(
62 store,
63 &this.command,
64 argument.as_deref(),
65 resource,
66 )
67 .await?
68 .map_err(|e| anyhow!("{}", e))?;
69
70 anyhow::Ok(output)
71 }
72 .boxed()
73 }
74 })
75 .await?;
76 output.ok_or_else(|| anyhow!("no output from command: {}", self.command.name))
77 });
78 cx.foreground_executor().spawn(async move {
79 let output = output.await?;
80 Ok(SlashCommandOutput {
81 text: output,
82 render_placeholder: Arc::new(|_, _, _| {
83 "TODO: Extension command output".into_any_element()
84 }),
85 })
86 })
87 }
88}