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

@ -24,6 +24,7 @@ pub use wit::{
npm_package_latest_version,
},
zed::extension::platform::{current_platform, Architecture, Os},
zed::extension::slash_command::SlashCommand,
CodeLabel, CodeLabelSpan, CodeLabelSpanLiteral, Command, DownloadedFileType, EnvVars,
LanguageServerInstallationStatus, Range, Worktree,
};
@ -104,6 +105,16 @@ pub trait Extension: Send + Sync {
) -> Option<CodeLabel> {
None
}
/// Runs the given slash command.
fn run_slash_command(
&self,
_command: SlashCommand,
_argument: Option<String>,
_worktree: &Worktree,
) -> Result<Option<String>, String> {
Ok(None)
}
}
/// Registers the provided type as a Zed extension.
@ -139,6 +150,8 @@ static mut EXTENSION: Option<Box<dyn Extension>> = None;
pub static ZED_API_VERSION: [u8; 6] = *include_bytes!(concat!(env!("OUT_DIR"), "/version_bytes"));
mod wit {
#![allow(clippy::too_many_arguments)]
wit_bindgen::generate!({
skip: ["init-extension"],
path: "./wit/since_v0.0.7",
@ -209,6 +222,14 @@ impl wit::Guest for Component {
}
Ok(labels)
}
fn run_slash_command(
command: SlashCommand,
argument: Option<String>,
worktree: &Worktree,
) -> Result<Option<String>, String> {
extension().run_slash_command(command, argument, worktree)
}
}
/// The ID of a language server.

View file

@ -6,6 +6,7 @@ world extension {
import nodejs;
use lsp.{completion, symbol};
use slash-command.{slash-command};
/// Initializes the extension.
export init-extension: func();
@ -127,4 +128,7 @@ world extension {
export labels-for-completions: func(language-server-id: string, completions: list<completion>) -> result<list<option<code-label>>, string>;
export labels-for-symbols: func(language-server-id: string, symbols: list<symbol>) -> result<list<option<code-label>>, string>;
/// Runs the provided slash command.
export run-slash-command: func(command: slash-command, argument: option<string>, worktree: borrow<worktree>) -> result<option<string>, string>;
}

View file

@ -0,0 +1,11 @@
interface slash-command {
/// A slash command for use in the Assistant.
record slash-command {
/// The name of the slash command.
name: string,
/// The description of the slash command.
description: string,
/// Whether this slash command requires an argument.
requires-argument: bool,
}
}