Extract ExtensionSlashCommand to assistant_slash_command crate (#20617)

This PR extracts the `ExtensionSlashCommand` implementation to the
`assistant_slash_command` crate.

The slash command related methods have been added to the `Extension`
trait. We also create separate data types for the slash command data
within the `extension` crate so that we can talk about them without
depending on the `extension_host` or `assistant_slash_command`.

Release Notes:

- N/A
This commit is contained in:
Marshall Bowers 2024-11-13 14:34:58 -05:00 committed by GitHub
parent b913cf2e02
commit 254ce74036
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 309 additions and 161 deletions

View file

@ -1,7 +1,7 @@
use std::{path::PathBuf, sync::Arc};
use anyhow::Result;
use assistant_slash_command::SlashCommandRegistry;
use assistant_slash_command::{ExtensionSlashCommand, SlashCommandRegistry};
use context_servers::ContextServerFactoryRegistry;
use extension::Extension;
use extension_host::{extension_lsp_adapter::ExtensionLspAdapter, wasm_host};
@ -14,7 +14,6 @@ use theme::{ThemeRegistry, ThemeSettings};
use ui::SharedString;
use crate::extension_context_server::ExtensionContextServer;
use crate::extension_slash_command::ExtensionSlashCommand;
pub struct ConcreteExtensionRegistrationHooks {
slash_command_registry: Arc<SlashCommandRegistry>,
@ -61,18 +60,11 @@ impl extension_host::ExtensionRegistrationHooks for ConcreteExtensionRegistratio
fn register_slash_command(
&self,
command: wasm_host::SlashCommand,
extension: wasm_host::WasmExtension,
host: Arc<wasm_host::WasmHost>,
extension: Arc<dyn Extension>,
command: extension::SlashCommand,
) {
self.slash_command_registry.register_command(
ExtensionSlashCommand {
command,
extension,
host,
},
false,
)
self.slash_command_registry
.register_command(ExtensionSlashCommand::new(extension, command), false)
}
fn register_context_server(

View file

@ -1,138 +0,0 @@
use std::sync::{atomic::AtomicBool, Arc};
use anyhow::{anyhow, Result};
use assistant_slash_command::{
ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
SlashCommandResult,
};
use extension_host::extension_lsp_adapter::WorktreeDelegateAdapter;
use futures::FutureExt as _;
use gpui::{Task, WeakView, WindowContext};
use language::{BufferSnapshot, LspAdapterDelegate};
use ui::prelude::*;
use wasmtime_wasi::WasiView;
use workspace::Workspace;
use extension_host::wasm_host::{WasmExtension, WasmHost};
pub struct ExtensionSlashCommand {
pub(crate) extension: WasmExtension,
#[allow(unused)]
pub(crate) host: Arc<WasmHost>,
pub(crate) command: extension_host::wasm_host::SlashCommand,
}
impl SlashCommand for ExtensionSlashCommand {
fn name(&self) -> String {
self.command.name.clone()
}
fn description(&self) -> String {
self.command.description.clone()
}
fn menu_text(&self) -> String {
self.command.tooltip_text.clone()
}
fn requires_argument(&self) -> bool {
self.command.requires_argument
}
fn complete_argument(
self: Arc<Self>,
arguments: &[String],
_cancel: Arc<AtomicBool>,
_workspace: Option<WeakView<Workspace>>,
cx: &mut WindowContext,
) -> Task<Result<Vec<ArgumentCompletion>>> {
let arguments = arguments.to_owned();
cx.background_executor().spawn(async move {
self.extension
.call({
let this = self.clone();
move |extension, store| {
async move {
let completions = extension
.call_complete_slash_command_argument(
store,
&this.command,
&arguments,
)
.await?
.map_err(|e| anyhow!("{}", e))?;
anyhow::Ok(
completions
.into_iter()
.map(|completion| ArgumentCompletion {
label: completion.label.into(),
new_text: completion.new_text,
replace_previous_arguments: false,
after_completion: completion.run_command.into(),
})
.collect(),
)
}
.boxed()
}
})
.await
})
}
fn run(
self: Arc<Self>,
arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
_workspace: WeakView<Workspace>,
delegate: Option<Arc<dyn LspAdapterDelegate>>,
cx: &mut WindowContext,
) -> Task<SlashCommandResult> {
let arguments = arguments.to_owned();
let output = cx.background_executor().spawn(async move {
self.extension
.call({
let this = self.clone();
move |extension, store| {
async move {
let resource = if let Some(delegate) = delegate {
let delegate =
Arc::new(WorktreeDelegateAdapter(delegate.clone())) as _;
Some(store.data_mut().table().push(delegate)?)
} else {
None
};
let output = extension
.call_run_slash_command(store, &this.command, &arguments, resource)
.await?
.map_err(|e| anyhow!("{}", e))?;
anyhow::Ok(output)
}
.boxed()
}
})
.await
});
cx.foreground_executor().spawn(async move {
let output = output.await?;
Ok(SlashCommandOutput {
text: output.text,
sections: output
.sections
.into_iter()
.map(|section| SlashCommandOutputSection {
range: section.range.into(),
icon: IconName::Code,
label: section.label.into(),
metadata: None,
})
.collect(),
run_commands_in_text: false,
}
.to_event_stream())
})
}
}

View file

@ -1,7 +1,6 @@
mod components;
mod extension_context_server;
mod extension_registration_hooks;
mod extension_slash_command;
mod extension_suggest;
mod extension_version_selector;