Allow defining slash commands in extensions (#12255)

This PR adds initial support for defining slash commands for the
Assistant from extensions.

Slash commands are defined in an extension's `extension.toml`:

```toml
[slash_commands.gleam-project]
description = "Returns information about the current Gleam project."
requires_argument = false
```

and then executed via the `run_slash_command` method on the `Extension`
trait:

```rs
impl Extension for GleamExtension {
    // ...

    fn run_slash_command(
        &self,
        command: SlashCommand,
        _argument: Option<String>,
        worktree: &zed::Worktree,
    ) -> Result<Option<String>, String> {
        match command.name.as_str() {
            "gleam-project" => Ok(Some("Yayyy".to_string())),
            command => Err(format!("unknown slash command: \"{command}\"")),
        }
    }
}
```

Release Notes:

- N/A
This commit is contained in:
Marshall Bowers 2024-05-24 15:44:32 -04:00 committed by GitHub
parent 055a13a9b6
commit 82f5f36422
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 310 additions and 14 deletions

View file

@ -5,6 +5,7 @@ use crate::{
ExtensionIndexThemeEntry, ExtensionManifest, ExtensionStore, GrammarManifestEntry,
RELOAD_DEBOUNCE_DURATION,
};
use assistant_slash_command::SlashCommandRegistry;
use async_compression::futures::bufread::GzipEncoder;
use collections::BTreeMap;
use fs::{FakeFs, Fs, RealFs};
@ -156,6 +157,7 @@ async fn test_extension_store(cx: &mut TestAppContext) {
.into_iter()
.collect(),
language_servers: BTreeMap::default(),
slash_commands: BTreeMap::default(),
}),
dev: false,
},
@ -179,6 +181,7 @@ async fn test_extension_store(cx: &mut TestAppContext) {
languages: Default::default(),
grammars: BTreeMap::default(),
language_servers: BTreeMap::default(),
slash_commands: BTreeMap::default(),
}),
dev: false,
},
@ -250,6 +253,7 @@ async fn test_extension_store(cx: &mut TestAppContext) {
let language_registry = Arc::new(LanguageRegistry::test(cx.executor()));
let theme_registry = Arc::new(ThemeRegistry::new(Box::new(())));
let slash_command_registry = SlashCommandRegistry::new();
let node_runtime = FakeNodeRuntime::new();
let store = cx.new_model(|cx| {
@ -262,6 +266,7 @@ async fn test_extension_store(cx: &mut TestAppContext) {
node_runtime.clone(),
language_registry.clone(),
theme_registry.clone(),
slash_command_registry.clone(),
cx,
)
});
@ -333,6 +338,7 @@ async fn test_extension_store(cx: &mut TestAppContext) {
languages: Default::default(),
grammars: BTreeMap::default(),
language_servers: BTreeMap::default(),
slash_commands: BTreeMap::default(),
}),
dev: false,
},
@ -382,6 +388,7 @@ async fn test_extension_store(cx: &mut TestAppContext) {
node_runtime.clone(),
language_registry.clone(),
theme_registry.clone(),
slash_command_registry,
cx,
)
});
@ -460,6 +467,7 @@ async fn test_extension_store_with_gleam_extension(cx: &mut TestAppContext) {
let language_registry = project.read_with(cx, |project, _cx| project.languages().clone());
let theme_registry = Arc::new(ThemeRegistry::new(Box::new(())));
let slash_command_registry = SlashCommandRegistry::new();
let node_runtime = FakeNodeRuntime::new();
let mut status_updates = language_registry.language_server_binary_statuses();
@ -541,6 +549,7 @@ async fn test_extension_store_with_gleam_extension(cx: &mut TestAppContext) {
node_runtime,
language_registry.clone(),
theme_registry.clone(),
slash_command_registry,
cx,
)
});