Allow completing slash command arguments from extensions (#13240)

This PR extends the extension API with support for completing slash
command arguments for slash commands defined in extensions.

Release Notes:

- N/A
This commit is contained in:
Marshall Bowers 2024-06-18 17:58:57 -04:00 committed by GitHub
parent ad4e52842c
commit db0d843fb1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 90 additions and 19 deletions

View File

@ -6,6 +6,7 @@ use anyhow::{anyhow, Result};
use editor::Editor; use editor::Editor;
use gpui::{AppContext, Task, WeakView}; use gpui::{AppContext, Task, WeakView};
use language::LspAdapterDelegate; use language::LspAdapterDelegate;
use std::sync::atomic::AtomicBool;
use std::sync::Arc; use std::sync::Arc;
use ui::WindowContext; use ui::WindowContext;
use workspace::Workspace; use workspace::Workspace;
@ -26,9 +27,9 @@ impl SlashCommand for ActiveSlashCommand {
} }
fn complete_argument( fn complete_argument(
&self, self: Arc<Self>,
_query: String, _query: String,
_cancel: std::sync::Arc<std::sync::atomic::AtomicBool>, _cancel: Arc<AtomicBool>,
_workspace: Option<WeakView<Workspace>>, _workspace: Option<WeakView<Workspace>>,
_cx: &mut AppContext, _cx: &mut AppContext,
) -> Task<Result<Vec<String>>> { ) -> Task<Result<Vec<String>>> {

View File

@ -31,7 +31,7 @@ impl SlashCommand for DefaultSlashCommand {
} }
fn complete_argument( fn complete_argument(
&self, self: Arc<Self>,
_query: String, _query: String,
_cancellation_flag: Arc<AtomicBool>, _cancellation_flag: Arc<AtomicBool>,
_workspace: Option<WeakView<Workspace>>, _workspace: Option<WeakView<Workspace>>,

View File

@ -98,7 +98,7 @@ impl SlashCommand for DiagnosticsCommand {
} }
fn complete_argument( fn complete_argument(
&self, self: Arc<Self>,
query: String, query: String,
cancellation_flag: Arc<AtomicBool>, cancellation_flag: Arc<AtomicBool>,
workspace: Option<WeakView<Workspace>>, workspace: Option<WeakView<Workspace>>,

View File

@ -113,7 +113,7 @@ impl SlashCommand for FetchSlashCommand {
} }
fn complete_argument( fn complete_argument(
&self, self: Arc<Self>,
_query: String, _query: String,
_cancel: Arc<AtomicBool>, _cancel: Arc<AtomicBool>,
_workspace: Option<WeakView<Workspace>>, _workspace: Option<WeakView<Workspace>>,

View File

@ -101,7 +101,7 @@ impl SlashCommand for FileSlashCommand {
} }
fn complete_argument( fn complete_argument(
&self, self: Arc<Self>,
query: String, query: String,
cancellation_flag: Arc<AtomicBool>, cancellation_flag: Arc<AtomicBool>,
workspace: Option<WeakView<Workspace>>, workspace: Option<WeakView<Workspace>>,

View File

@ -29,7 +29,7 @@ impl SlashCommand for NowSlashCommand {
} }
fn complete_argument( fn complete_argument(
&self, self: Arc<Self>,
_query: String, _query: String,
_cancel: Arc<AtomicBool>, _cancel: Arc<AtomicBool>,
_workspace: Option<WeakView<Workspace>>, _workspace: Option<WeakView<Workspace>>,

View File

@ -102,7 +102,7 @@ impl SlashCommand for ProjectSlashCommand {
} }
fn complete_argument( fn complete_argument(
&self, self: Arc<Self>,
_query: String, _query: String,
_cancel: Arc<AtomicBool>, _cancel: Arc<AtomicBool>,
_workspace: Option<WeakView<Workspace>>, _workspace: Option<WeakView<Workspace>>,

View File

@ -28,7 +28,7 @@ impl SlashCommand for PromptSlashCommand {
} }
fn complete_argument( fn complete_argument(
&self, self: Arc<Self>,
query: String, query: String,
_cancellation_flag: Arc<AtomicBool>, _cancellation_flag: Arc<AtomicBool>,
_workspace: Option<WeakView<Workspace>>, _workspace: Option<WeakView<Workspace>>,

View File

@ -107,7 +107,7 @@ impl SlashCommand for RustdocSlashCommand {
} }
fn complete_argument( fn complete_argument(
&self, self: Arc<Self>,
query: String, query: String,
_cancel: Arc<AtomicBool>, _cancel: Arc<AtomicBool>,
workspace: Option<WeakView<Workspace>>, workspace: Option<WeakView<Workspace>>,

View File

@ -47,7 +47,7 @@ impl SlashCommand for SearchSlashCommand {
} }
fn complete_argument( fn complete_argument(
&self, self: Arc<Self>,
_query: String, _query: String,
_cancel: Arc<AtomicBool>, _cancel: Arc<AtomicBool>,
_workspace: Option<WeakView<Workspace>>, _workspace: Option<WeakView<Workspace>>,

View File

@ -31,7 +31,7 @@ impl SlashCommand for TabsSlashCommand {
} }
fn complete_argument( fn complete_argument(
&self, self: Arc<Self>,
_query: String, _query: String,
_cancel: Arc<std::sync::atomic::AtomicBool>, _cancel: Arc<std::sync::atomic::AtomicBool>,
_workspace: Option<WeakView<Workspace>>, _workspace: Option<WeakView<Workspace>>,

View File

@ -23,7 +23,7 @@ pub trait SlashCommand: 'static + Send + Sync {
fn description(&self) -> String; fn description(&self) -> String;
fn menu_text(&self) -> String; fn menu_text(&self) -> String;
fn complete_argument( fn complete_argument(
&self, self: Arc<Self>,
query: String, query: String,
cancel: Arc<AtomicBool>, cancel: Arc<AtomicBool>,
workspace: Option<WeakView<Workspace>>, workspace: Option<WeakView<Workspace>>,

View File

@ -36,13 +36,34 @@ impl SlashCommand for ExtensionSlashCommand {
} }
fn complete_argument( fn complete_argument(
&self, self: Arc<Self>,
_query: String, query: String,
_cancel: Arc<AtomicBool>, _cancel: Arc<AtomicBool>,
_workspace: Option<WeakView<Workspace>>, _workspace: Option<WeakView<Workspace>>,
_cx: &mut AppContext, cx: &mut AppContext,
) -> Task<Result<Vec<String>>> { ) -> Task<Result<Vec<String>>> {
Task::ready(Ok(Vec::new())) 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,
query.as_ref(),
)
.await?
.map_err(|e| anyhow!("{}", e))?;
anyhow::Ok(completions)
}
.boxed()
}
})
.await
})
} }
fn run( fn run(

View File

@ -257,6 +257,21 @@ impl Extension {
} }
} }
pub async fn call_complete_slash_command_argument(
&self,
store: &mut Store<WasmState>,
command: &SlashCommand,
query: &str,
) -> Result<Result<Vec<String>, String>> {
match self {
Extension::V007(ext) => {
ext.call_complete_slash_command_argument(store, command, query)
.await
}
Extension::V001(_) | Extension::V004(_) | Extension::V006(_) => Ok(Ok(Vec::new())),
}
}
pub async fn call_run_slash_command( pub async fn call_run_slash_command(
&self, &self,
store: &mut Store<WasmState>, store: &mut Store<WasmState>,

View File

@ -108,7 +108,16 @@ pub trait Extension: Send + Sync {
None None
} }
/// Runs the given slash command. /// Returns the completions that should be shown when completing the provided slash command with the given query.
fn complete_slash_command_argument(
&self,
_command: SlashCommand,
_query: String,
) -> Result<Vec<String>, String> {
Ok(Vec::new())
}
/// Returns the output from running the provided slash command.
fn run_slash_command( fn run_slash_command(
&self, &self,
_command: SlashCommand, _command: SlashCommand,
@ -225,6 +234,13 @@ impl wit::Guest for Component {
Ok(labels) Ok(labels)
} }
fn complete_slash_command_argument(
command: SlashCommand,
query: String,
) -> Result<Vec<String>, String> {
extension().complete_slash_command_argument(command, query)
}
fn run_slash_command( fn run_slash_command(
command: SlashCommand, command: SlashCommand,
argument: Option<String>, argument: Option<String>,

View File

@ -122,6 +122,9 @@ world extension {
export labels-for-completions: func(language-server-id: string, completions: list<completion>) -> result<list<option<code-label>>, string>; 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>; export labels-for-symbols: func(language-server-id: string, symbols: list<symbol>) -> result<list<option<code-label>>, string>;
/// Runs the provided slash command. /// Returns the completions that should be shown when completing the provided slash command with the given query.
export complete-slash-command-argument: func(command: slash-command, query: string) -> result<list<string>, string>;
/// Returns the output from running the provided slash command.
export run-slash-command: func(command: slash-command, argument: option<string>, worktree: borrow<worktree>) -> result<slash-command-output, string>; export run-slash-command: func(command: slash-command, argument: option<string>, worktree: borrow<worktree>) -> result<slash-command-output, string>;
} }

View File

@ -146,6 +146,21 @@ impl zed::Extension for GleamExtension {
}) })
} }
fn complete_slash_command_argument(
&self,
command: SlashCommand,
_query: String,
) -> Result<Vec<String>, String> {
match command.name.as_str() {
"gleam-project" => Ok(vec![
"apple".to_string(),
"banana".to_string(),
"cherry".to_string(),
]),
_ => Ok(Vec::new()),
}
}
fn run_slash_command( fn run_slash_command(
&self, &self,
command: SlashCommand, command: SlashCommand,