assistant: Improve /docs
argument completions (#13876)
This PR improves the completions for arguments in the `/docs` slash command. We achieved this by extending the `complete_argument` method on the `SlashCommand` trait to return a `Vec<ArgumentCompletion>` instead of a `Vec<String>`. In addition to the completion `label`, `ArgumentCompletion` has two new fields that are can be used to customize the completion behavior: - `new_text`: The actual text that will be inserted when the completion is accepted, which may be different from what is shown by the completion label. - `run_command`: Whether the command is run when the completion is accepted. This can be set to `false` to allow accepting a completion without running the command. Release Notes: - N/A --------- Co-authored-by: Antonio <antonio@zed.dev>
This commit is contained in:
parent
ca27f42a9d
commit
68accaeb00
15 changed files with 115 additions and 40 deletions
|
@ -170,7 +170,7 @@ impl SlashCommandCompletionProvider {
|
||||||
.await?
|
.await?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|command_argument| {
|
.map(|command_argument| {
|
||||||
let confirm =
|
let confirm = if command_argument.run_command {
|
||||||
editor
|
editor
|
||||||
.clone()
|
.clone()
|
||||||
.zip(workspace.clone())
|
.zip(workspace.clone())
|
||||||
|
@ -178,7 +178,7 @@ impl SlashCommandCompletionProvider {
|
||||||
Arc::new({
|
Arc::new({
|
||||||
let command_range = command_range.clone();
|
let command_range = command_range.clone();
|
||||||
let command_name = command_name.clone();
|
let command_name = command_name.clone();
|
||||||
let command_argument = command_argument.clone();
|
let command_argument = command_argument.new_text.clone();
|
||||||
move |cx: &mut WindowContext| {
|
move |cx: &mut WindowContext| {
|
||||||
editor
|
editor
|
||||||
.update(cx, |editor, cx| {
|
.update(cx, |editor, cx| {
|
||||||
|
@ -194,15 +194,24 @@ impl SlashCommandCompletionProvider {
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
}) as Arc<_>
|
}) as Arc<_>
|
||||||
});
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut new_text = command_argument.new_text.clone();
|
||||||
|
if !command_argument.run_command {
|
||||||
|
new_text.push(' ');
|
||||||
|
}
|
||||||
|
|
||||||
project::Completion {
|
project::Completion {
|
||||||
old_range: argument_range.clone(),
|
old_range: argument_range.clone(),
|
||||||
label: CodeLabel::plain(command_argument.clone(), None),
|
label: CodeLabel::plain(command_argument.label, None),
|
||||||
new_text: command_argument.clone(),
|
new_text,
|
||||||
documentation: None,
|
documentation: None,
|
||||||
server_id: LanguageServerId(0),
|
server_id: LanguageServerId(0),
|
||||||
lsp_completion: Default::default(),
|
lsp_completion: Default::default(),
|
||||||
show_new_completions_on_confirm: false,
|
show_new_completions_on_confirm: !command_argument.run_command,
|
||||||
confirm,
|
confirm,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -4,6 +4,7 @@ use super::{
|
||||||
SlashCommand, SlashCommandOutput,
|
SlashCommand, SlashCommandOutput,
|
||||||
};
|
};
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
|
use assistant_slash_command::ArgumentCompletion;
|
||||||
use editor::Editor;
|
use editor::Editor;
|
||||||
use gpui::{AppContext, Task, WeakView};
|
use gpui::{AppContext, Task, WeakView};
|
||||||
use language::LspAdapterDelegate;
|
use language::LspAdapterDelegate;
|
||||||
|
@ -33,7 +34,7 @@ impl SlashCommand for ActiveSlashCommand {
|
||||||
_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<ArgumentCompletion>>> {
|
||||||
Task::ready(Err(anyhow!("this command does not require argument")))
|
Task::ready(Err(anyhow!("this command does not require argument")))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use super::{SlashCommand, SlashCommandOutput};
|
use super::{SlashCommand, SlashCommandOutput};
|
||||||
use crate::prompt_library::PromptStore;
|
use crate::prompt_library::PromptStore;
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use assistant_slash_command::SlashCommandOutputSection;
|
use assistant_slash_command::{ArgumentCompletion, SlashCommandOutputSection};
|
||||||
use gpui::{AppContext, Task, WeakView};
|
use gpui::{AppContext, Task, WeakView};
|
||||||
use language::LspAdapterDelegate;
|
use language::LspAdapterDelegate;
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -36,7 +36,7 @@ impl SlashCommand for DefaultSlashCommand {
|
||||||
_cancellation_flag: Arc<AtomicBool>,
|
_cancellation_flag: Arc<AtomicBool>,
|
||||||
_workspace: Option<WeakView<Workspace>>,
|
_workspace: Option<WeakView<Workspace>>,
|
||||||
_cx: &mut AppContext,
|
_cx: &mut AppContext,
|
||||||
) -> Task<Result<Vec<String>>> {
|
) -> Task<Result<Vec<ArgumentCompletion>>> {
|
||||||
Task::ready(Err(anyhow!("this command does not require argument")))
|
Task::ready(Err(anyhow!("this command does not require argument")))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use super::{create_label_for_command, SlashCommand, SlashCommandOutput};
|
use super::{create_label_for_command, SlashCommand, SlashCommandOutput};
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use assistant_slash_command::SlashCommandOutputSection;
|
use assistant_slash_command::{ArgumentCompletion, SlashCommandOutputSection};
|
||||||
use fuzzy::{PathMatch, StringMatchCandidate};
|
use fuzzy::{PathMatch, StringMatchCandidate};
|
||||||
use gpui::{AppContext, Model, Task, View, WeakView};
|
use gpui::{AppContext, Model, Task, View, WeakView};
|
||||||
use language::{
|
use language::{
|
||||||
|
@ -108,7 +108,7 @@ impl SlashCommand for DiagnosticsSlashCommand {
|
||||||
cancellation_flag: Arc<AtomicBool>,
|
cancellation_flag: Arc<AtomicBool>,
|
||||||
workspace: Option<WeakView<Workspace>>,
|
workspace: Option<WeakView<Workspace>>,
|
||||||
cx: &mut AppContext,
|
cx: &mut AppContext,
|
||||||
) -> Task<Result<Vec<String>>> {
|
) -> Task<Result<Vec<ArgumentCompletion>>> {
|
||||||
let Some(workspace) = workspace.and_then(|workspace| workspace.upgrade()) else {
|
let Some(workspace) = workspace.and_then(|workspace| workspace.upgrade()) else {
|
||||||
return Task::ready(Err(anyhow!("workspace was dropped")));
|
return Task::ready(Err(anyhow!("workspace was dropped")));
|
||||||
};
|
};
|
||||||
|
@ -143,7 +143,14 @@ impl SlashCommand for DiagnosticsSlashCommand {
|
||||||
.map(|candidate| candidate.string),
|
.map(|candidate| candidate.string),
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(matches)
|
Ok(matches
|
||||||
|
.into_iter()
|
||||||
|
.map(|completion| ArgumentCompletion {
|
||||||
|
label: completion.clone(),
|
||||||
|
new_text: completion,
|
||||||
|
run_command: true,
|
||||||
|
})
|
||||||
|
.collect())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,9 @@ use std::sync::atomic::AtomicBool;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use anyhow::{anyhow, bail, Result};
|
use anyhow::{anyhow, bail, Result};
|
||||||
use assistant_slash_command::{SlashCommand, SlashCommandOutput, SlashCommandOutputSection};
|
use assistant_slash_command::{
|
||||||
|
ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
|
||||||
|
};
|
||||||
use gpui::{AppContext, Model, Task, WeakView};
|
use gpui::{AppContext, Model, Task, WeakView};
|
||||||
use indexed_docs::{
|
use indexed_docs::{
|
||||||
IndexedDocsRegistry, IndexedDocsStore, LocalProvider, PackageName, ProviderId, RustdocIndexer,
|
IndexedDocsRegistry, IndexedDocsStore, LocalProvider, PackageName, ProviderId, RustdocIndexer,
|
||||||
|
@ -92,7 +94,7 @@ impl SlashCommand for DocsSlashCommand {
|
||||||
_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<ArgumentCompletion>>> {
|
||||||
self.ensure_rustdoc_provider_is_registered(workspace, cx);
|
self.ensure_rustdoc_provider_is_registered(workspace, cx);
|
||||||
|
|
||||||
let indexed_docs_registry = IndexedDocsRegistry::global(cx);
|
let indexed_docs_registry = IndexedDocsRegistry::global(cx);
|
||||||
|
@ -107,10 +109,17 @@ impl SlashCommand for DocsSlashCommand {
|
||||||
///
|
///
|
||||||
/// We will likely want to extend `complete_argument` with support for replacing just
|
/// We will likely want to extend `complete_argument` with support for replacing just
|
||||||
/// a particular range of the argument when a completion is accepted.
|
/// a particular range of the argument when a completion is accepted.
|
||||||
fn prefix_with_provider(provider: ProviderId, items: Vec<String>) -> Vec<String> {
|
fn prefix_with_provider(
|
||||||
|
provider: ProviderId,
|
||||||
|
items: Vec<String>,
|
||||||
|
) -> Vec<ArgumentCompletion> {
|
||||||
items
|
items
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|item| format!("{provider} {item}"))
|
.map(|item| ArgumentCompletion {
|
||||||
|
label: item.clone(),
|
||||||
|
new_text: format!("{provider} {item}"),
|
||||||
|
run_command: true,
|
||||||
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +128,11 @@ impl SlashCommand for DocsSlashCommand {
|
||||||
let providers = indexed_docs_registry.list_providers();
|
let providers = indexed_docs_registry.list_providers();
|
||||||
Ok(providers
|
Ok(providers
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|provider| provider.to_string())
|
.map(|provider| ArgumentCompletion {
|
||||||
|
label: provider.to_string(),
|
||||||
|
new_text: provider.to_string(),
|
||||||
|
run_command: false,
|
||||||
|
})
|
||||||
.collect())
|
.collect())
|
||||||
}
|
}
|
||||||
DocsSlashCommandArgs::SearchPackageDocs {
|
DocsSlashCommandArgs::SearchPackageDocs {
|
||||||
|
|
|
@ -4,7 +4,9 @@ use std::sync::atomic::AtomicBool;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use anyhow::{anyhow, bail, Context, Result};
|
use anyhow::{anyhow, bail, Context, Result};
|
||||||
use assistant_slash_command::{SlashCommand, SlashCommandOutput, SlashCommandOutputSection};
|
use assistant_slash_command::{
|
||||||
|
ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
|
||||||
|
};
|
||||||
use futures::AsyncReadExt;
|
use futures::AsyncReadExt;
|
||||||
use gpui::{AppContext, Task, WeakView};
|
use gpui::{AppContext, Task, WeakView};
|
||||||
use html_to_markdown::{convert_html_to_markdown, markdown, TagHandler};
|
use html_to_markdown::{convert_html_to_markdown, markdown, TagHandler};
|
||||||
|
@ -119,7 +121,7 @@ impl SlashCommand for FetchSlashCommand {
|
||||||
_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<ArgumentCompletion>>> {
|
||||||
Task::ready(Ok(Vec::new()))
|
Task::ready(Ok(Vec::new()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use super::{diagnostics_command::write_single_file_diagnostics, SlashCommand, SlashCommandOutput};
|
use super::{diagnostics_command::write_single_file_diagnostics, SlashCommand, SlashCommandOutput};
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use assistant_slash_command::SlashCommandOutputSection;
|
use assistant_slash_command::{ArgumentCompletion, SlashCommandOutputSection};
|
||||||
use fuzzy::PathMatch;
|
use fuzzy::PathMatch;
|
||||||
use gpui::{AppContext, Model, Task, View, WeakView};
|
use gpui::{AppContext, Model, Task, View, WeakView};
|
||||||
use language::{BufferSnapshot, LineEnding, LspAdapterDelegate};
|
use language::{BufferSnapshot, LineEnding, LspAdapterDelegate};
|
||||||
|
@ -105,7 +105,7 @@ impl SlashCommand for FileSlashCommand {
|
||||||
cancellation_flag: Arc<AtomicBool>,
|
cancellation_flag: Arc<AtomicBool>,
|
||||||
workspace: Option<WeakView<Workspace>>,
|
workspace: Option<WeakView<Workspace>>,
|
||||||
cx: &mut AppContext,
|
cx: &mut AppContext,
|
||||||
) -> Task<Result<Vec<String>>> {
|
) -> Task<Result<Vec<ArgumentCompletion>>> {
|
||||||
let Some(workspace) = workspace.and_then(|workspace| workspace.upgrade()) else {
|
let Some(workspace) = workspace.and_then(|workspace| workspace.upgrade()) else {
|
||||||
return Task::ready(Err(anyhow!("workspace was dropped")));
|
return Task::ready(Err(anyhow!("workspace was dropped")));
|
||||||
};
|
};
|
||||||
|
@ -116,11 +116,17 @@ impl SlashCommand for FileSlashCommand {
|
||||||
.await
|
.await
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|path_match| {
|
.map(|path_match| {
|
||||||
format!(
|
let text = format!(
|
||||||
"{}{}",
|
"{}{}",
|
||||||
path_match.path_prefix,
|
path_match.path_prefix,
|
||||||
path_match.path.to_string_lossy()
|
path_match.path.to_string_lossy()
|
||||||
)
|
);
|
||||||
|
|
||||||
|
ArgumentCompletion {
|
||||||
|
label: text.clone(),
|
||||||
|
new_text: text,
|
||||||
|
run_command: true,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.collect())
|
.collect())
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,7 +2,9 @@ use std::sync::atomic::AtomicBool;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use assistant_slash_command::{SlashCommand, SlashCommandOutput, SlashCommandOutputSection};
|
use assistant_slash_command::{
|
||||||
|
ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
|
||||||
|
};
|
||||||
use chrono::Local;
|
use chrono::Local;
|
||||||
use gpui::{AppContext, Task, WeakView};
|
use gpui::{AppContext, Task, WeakView};
|
||||||
use language::LspAdapterDelegate;
|
use language::LspAdapterDelegate;
|
||||||
|
@ -34,7 +36,7 @@ impl SlashCommand for NowSlashCommand {
|
||||||
_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<ArgumentCompletion>>> {
|
||||||
Task::ready(Ok(Vec::new()))
|
Task::ready(Ok(Vec::new()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use super::{SlashCommand, SlashCommandOutput};
|
use super::{SlashCommand, SlashCommandOutput};
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
use assistant_slash_command::SlashCommandOutputSection;
|
use assistant_slash_command::{ArgumentCompletion, SlashCommandOutputSection};
|
||||||
use fs::Fs;
|
use fs::Fs;
|
||||||
use gpui::{AppContext, Model, Task, WeakView};
|
use gpui::{AppContext, Model, Task, WeakView};
|
||||||
use language::LspAdapterDelegate;
|
use language::LspAdapterDelegate;
|
||||||
|
@ -107,7 +107,7 @@ impl SlashCommand for ProjectSlashCommand {
|
||||||
_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<ArgumentCompletion>>> {
|
||||||
Task::ready(Err(anyhow!("this command does not require argument")))
|
Task::ready(Err(anyhow!("this command does not require argument")))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use super::{SlashCommand, SlashCommandOutput};
|
use super::{SlashCommand, SlashCommandOutput};
|
||||||
use crate::prompt_library::PromptStore;
|
use crate::prompt_library::PromptStore;
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
use assistant_slash_command::SlashCommandOutputSection;
|
use assistant_slash_command::{ArgumentCompletion, SlashCommandOutputSection};
|
||||||
use gpui::{AppContext, Task, WeakView};
|
use gpui::{AppContext, Task, WeakView};
|
||||||
use language::LspAdapterDelegate;
|
use language::LspAdapterDelegate;
|
||||||
use std::sync::{atomic::AtomicBool, Arc};
|
use std::sync::{atomic::AtomicBool, Arc};
|
||||||
|
@ -33,13 +33,20 @@ impl SlashCommand for PromptSlashCommand {
|
||||||
_cancellation_flag: Arc<AtomicBool>,
|
_cancellation_flag: Arc<AtomicBool>,
|
||||||
_workspace: Option<WeakView<Workspace>>,
|
_workspace: Option<WeakView<Workspace>>,
|
||||||
cx: &mut AppContext,
|
cx: &mut AppContext,
|
||||||
) -> Task<Result<Vec<String>>> {
|
) -> Task<Result<Vec<ArgumentCompletion>>> {
|
||||||
let store = PromptStore::global(cx);
|
let store = PromptStore::global(cx);
|
||||||
cx.background_executor().spawn(async move {
|
cx.background_executor().spawn(async move {
|
||||||
let prompts = store.await?.search(query).await;
|
let prompts = store.await?.search(query).await;
|
||||||
Ok(prompts
|
Ok(prompts
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|prompt| Some(prompt.title?.to_string()))
|
.filter_map(|prompt| {
|
||||||
|
let prompt_title = prompt.title?.to_string();
|
||||||
|
Some(ArgumentCompletion {
|
||||||
|
label: prompt_title.clone(),
|
||||||
|
new_text: prompt_title,
|
||||||
|
run_command: true,
|
||||||
|
})
|
||||||
|
})
|
||||||
.collect())
|
.collect())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use super::{
|
||||||
SlashCommand, SlashCommandOutput,
|
SlashCommand, SlashCommandOutput,
|
||||||
};
|
};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use assistant_slash_command::SlashCommandOutputSection;
|
use assistant_slash_command::{ArgumentCompletion, SlashCommandOutputSection};
|
||||||
use gpui::{AppContext, Task, WeakView};
|
use gpui::{AppContext, Task, WeakView};
|
||||||
use language::{CodeLabel, LineEnding, LspAdapterDelegate};
|
use language::{CodeLabel, LineEnding, LspAdapterDelegate};
|
||||||
use semantic_index::SemanticIndex;
|
use semantic_index::SemanticIndex;
|
||||||
|
@ -46,7 +46,7 @@ impl SlashCommand for SearchSlashCommand {
|
||||||
_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<ArgumentCompletion>>> {
|
||||||
Task::ready(Ok(Vec::new()))
|
Task::ready(Ok(Vec::new()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ use super::{
|
||||||
SlashCommand, SlashCommandOutput,
|
SlashCommand, SlashCommandOutput,
|
||||||
};
|
};
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
|
use assistant_slash_command::ArgumentCompletion;
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use editor::Editor;
|
use editor::Editor;
|
||||||
use gpui::{AppContext, Entity, Task, WeakView};
|
use gpui::{AppContext, Entity, Task, WeakView};
|
||||||
|
@ -37,7 +38,7 @@ impl SlashCommand for TabsSlashCommand {
|
||||||
_cancel: Arc<std::sync::atomic::AtomicBool>,
|
_cancel: Arc<std::sync::atomic::AtomicBool>,
|
||||||
_workspace: Option<WeakView<Workspace>>,
|
_workspace: Option<WeakView<Workspace>>,
|
||||||
_cx: &mut AppContext,
|
_cx: &mut AppContext,
|
||||||
) -> Task<Result<Vec<String>>> {
|
) -> Task<Result<Vec<ArgumentCompletion>>> {
|
||||||
Task::ready(Err(anyhow!("this command does not require argument")))
|
Task::ready(Err(anyhow!("this command does not require argument")))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,9 @@ use std::sync::atomic::AtomicBool;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use assistant_slash_command::{SlashCommand, SlashCommandOutput, SlashCommandOutputSection};
|
use assistant_slash_command::{
|
||||||
|
ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
|
||||||
|
};
|
||||||
use gpui::{AppContext, Task, WeakView};
|
use gpui::{AppContext, Task, WeakView};
|
||||||
use language::{CodeLabel, LspAdapterDelegate};
|
use language::{CodeLabel, LspAdapterDelegate};
|
||||||
use terminal_view::{terminal_panel::TerminalPanel, TerminalView};
|
use terminal_view::{terminal_panel::TerminalPanel, TerminalView};
|
||||||
|
@ -42,8 +44,12 @@ impl SlashCommand for TermSlashCommand {
|
||||||
_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<ArgumentCompletion>>> {
|
||||||
Task::ready(Ok(vec![LINE_COUNT_ARG.to_string()]))
|
Task::ready(Ok(vec![ArgumentCompletion {
|
||||||
|
label: LINE_COUNT_ARG.to_string(),
|
||||||
|
new_text: LINE_COUNT_ARG.to_string(),
|
||||||
|
run_command: true,
|
||||||
|
}]))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(
|
fn run(
|
||||||
|
|
|
@ -15,6 +15,16 @@ pub fn init(cx: &mut AppContext) {
|
||||||
SlashCommandRegistry::default_global(cx);
|
SlashCommandRegistry::default_global(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ArgumentCompletion {
|
||||||
|
/// The label to display for this completion.
|
||||||
|
pub label: String,
|
||||||
|
/// The new text that should be inserted into the command when this completion is accepted.
|
||||||
|
pub new_text: String,
|
||||||
|
/// Whether the command should be run when accepting this completion.
|
||||||
|
pub run_command: bool,
|
||||||
|
}
|
||||||
|
|
||||||
pub trait SlashCommand: 'static + Send + Sync {
|
pub trait SlashCommand: 'static + Send + Sync {
|
||||||
fn name(&self) -> String;
|
fn name(&self) -> String;
|
||||||
fn label(&self, _cx: &AppContext) -> CodeLabel {
|
fn label(&self, _cx: &AppContext) -> CodeLabel {
|
||||||
|
@ -28,7 +38,7 @@ pub trait SlashCommand: 'static + Send + Sync {
|
||||||
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<ArgumentCompletion>>>;
|
||||||
fn requires_argument(&self) -> bool;
|
fn requires_argument(&self) -> bool;
|
||||||
fn run(
|
fn run(
|
||||||
self: Arc<Self>,
|
self: Arc<Self>,
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
use std::sync::{atomic::AtomicBool, Arc};
|
use std::sync::{atomic::AtomicBool, Arc};
|
||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use assistant_slash_command::{SlashCommand, SlashCommandOutput, SlashCommandOutputSection};
|
use assistant_slash_command::{
|
||||||
|
ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
|
||||||
|
};
|
||||||
use futures::FutureExt;
|
use futures::FutureExt;
|
||||||
use gpui::{AppContext, Task, WeakView, WindowContext};
|
use gpui::{AppContext, Task, WeakView, WindowContext};
|
||||||
use language::LspAdapterDelegate;
|
use language::LspAdapterDelegate;
|
||||||
|
@ -41,7 +43,7 @@ impl SlashCommand for ExtensionSlashCommand {
|
||||||
_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<ArgumentCompletion>>> {
|
||||||
cx.background_executor().spawn(async move {
|
cx.background_executor().spawn(async move {
|
||||||
self.extension
|
self.extension
|
||||||
.call({
|
.call({
|
||||||
|
@ -57,7 +59,16 @@ impl SlashCommand for ExtensionSlashCommand {
|
||||||
.await?
|
.await?
|
||||||
.map_err(|e| anyhow!("{}", e))?;
|
.map_err(|e| anyhow!("{}", e))?;
|
||||||
|
|
||||||
anyhow::Ok(completions)
|
anyhow::Ok(
|
||||||
|
completions
|
||||||
|
.into_iter()
|
||||||
|
.map(|completion| ArgumentCompletion {
|
||||||
|
label: completion.clone(),
|
||||||
|
new_text: completion,
|
||||||
|
run_command: true,
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue