Detailed changes
@@ -30,8 +30,8 @@ use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsStore};
use slash_command::{
active_command, default_command, diagnostics_command, docs_command, fetch_command,
- file_command, now_command, project_command, prompt_command, search_command, tabs_command,
- term_command,
+ file_command, now_command, project_command, prompt_command, search_command, symbols_command,
+ tabs_command, term_command,
};
use std::{
fmt::{self, Display},
@@ -367,6 +367,7 @@ fn register_slash_commands(cx: &mut AppContext) {
let slash_command_registry = SlashCommandRegistry::global(cx);
slash_command_registry.register_command(file_command::FileSlashCommand, true);
slash_command_registry.register_command(active_command::ActiveSlashCommand, true);
+ slash_command_registry.register_command(symbols_command::OutlineSlashCommand, true);
slash_command_registry.register_command(tabs_command::TabsSlashCommand, true);
slash_command_registry.register_command(project_command::ProjectSlashCommand, true);
slash_command_registry.register_command(search_command::SearchSlashCommand, true);
@@ -27,6 +27,7 @@ pub mod now_command;
pub mod project_command;
pub mod prompt_command;
pub mod search_command;
+pub mod symbols_command;
pub mod tabs_command;
pub mod term_command;
@@ -23,7 +23,7 @@ impl SlashCommand for NowSlashCommand {
}
fn menu_text(&self) -> String {
- "Insert current date and time".into()
+ "Insert Current Date and Time".into()
}
fn requires_argument(&self) -> bool {
@@ -0,0 +1,89 @@
+use super::{SlashCommand, SlashCommandOutput};
+use anyhow::{anyhow, Context as _, Result};
+use assistant_slash_command::{ArgumentCompletion, SlashCommandOutputSection};
+use editor::Editor;
+use gpui::{AppContext, Task, WeakView};
+use language::LspAdapterDelegate;
+use std::sync::Arc;
+use std::{path::Path, sync::atomic::AtomicBool};
+use ui::{IconName, WindowContext};
+use workspace::Workspace;
+
+pub(crate) struct OutlineSlashCommand;
+
+impl SlashCommand for OutlineSlashCommand {
+ fn name(&self) -> String {
+ "symbols".into()
+ }
+
+ fn description(&self) -> String {
+ "insert symbols for active tab".into()
+ }
+
+ fn menu_text(&self) -> String {
+ "Insert Symbols for Active Tab".into()
+ }
+
+ fn complete_argument(
+ self: Arc<Self>,
+ _query: String,
+ _cancel: Arc<AtomicBool>,
+ _workspace: Option<WeakView<Workspace>>,
+ _cx: &mut AppContext,
+ ) -> Task<Result<Vec<ArgumentCompletion>>> {
+ Task::ready(Err(anyhow!("this command does not require argument")))
+ }
+
+ fn requires_argument(&self) -> bool {
+ false
+ }
+
+ fn run(
+ self: Arc<Self>,
+ _argument: Option<&str>,
+ workspace: WeakView<Workspace>,
+ _delegate: Arc<dyn LspAdapterDelegate>,
+ cx: &mut WindowContext,
+ ) -> Task<Result<SlashCommandOutput>> {
+ let output = workspace.update(cx, |workspace, cx| {
+ let Some(active_item) = workspace.active_item(cx) else {
+ return Task::ready(Err(anyhow!("no active tab")));
+ };
+ let Some(buffer) = active_item
+ .downcast::<Editor>()
+ .and_then(|editor| editor.read(cx).buffer().read(cx).as_singleton())
+ else {
+ return Task::ready(Err(anyhow!("active tab is not an editor")));
+ };
+
+ let snapshot = buffer.read(cx).snapshot();
+ let path = snapshot.resolve_file_path(cx, true);
+
+ cx.background_executor().spawn(async move {
+ let outline = snapshot
+ .outline(None)
+ .context("no symbols for active tab")?;
+
+ let path = path.as_deref().unwrap_or(Path::new("untitled"));
+ let mut outline_text = format!("Symbols for {}:\n", path.display());
+ for item in &outline.path_candidates {
+ outline_text.push_str("- ");
+ outline_text.push_str(&item.string);
+ outline_text.push('\n');
+ }
+
+ Ok(SlashCommandOutput {
+ sections: vec![SlashCommandOutputSection {
+ range: 0..outline_text.len(),
+ icon: IconName::ListTree,
+ label: path.to_string_lossy().to_string().into(),
+ }],
+ text: outline_text,
+ run_commands_in_text: false,
+ })
+ })
+ });
+
+ output.unwrap_or_else(|error| Task::ready(Err(error)))
+ }
+}
@@ -31,7 +31,7 @@ impl SlashCommand for TermSlashCommand {
}
fn menu_text(&self) -> String {
- "Insert terminal output".into()
+ "Insert Terminal Output".into()
}
fn requires_argument(&self) -> bool {
@@ -12,7 +12,7 @@ use theme::{color_alpha, ActiveTheme, ThemeSettings};
pub struct Outline<T> {
pub items: Vec<OutlineItem<T>>,
candidates: Vec<StringMatchCandidate>,
- path_candidates: Vec<StringMatchCandidate>,
+ pub path_candidates: Vec<StringMatchCandidate>,
path_candidate_prefixes: Vec<usize>,
}