From e3b0de5dda5b9c3bcc347772fd9bf6a3b06e97ce Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Tue, 13 Aug 2024 12:37:13 -0400 Subject: [PATCH] assistant: Auto-suggest crates for `/docs` when using the docs.rs provider (#16169) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR improves the initial experience of using `/docs docs-rs` with an empty index. We now show a brief explainer of what is expected (a crate name) as well as list some popular Rust crates to try: Screenshot 2024-08-13 at 12 25 39 PM Release Notes: - N/A --- .../src/slash_command/docs_command.rs | 49 ++++++++++++++++--- crates/indexed_docs/src/providers/rustdoc.rs | 20 ++++++++ 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/crates/assistant/src/slash_command/docs_command.rs b/crates/assistant/src/slash_command/docs_command.rs index cb3cb663be..3872f8f8d8 100644 --- a/crates/assistant/src/slash_command/docs_command.rs +++ b/crates/assistant/src/slash_command/docs_command.rs @@ -230,6 +230,36 @@ impl SlashCommand for DocsSlashCommand { } let items = store.search(package).await; + if items.is_empty() { + if provider == DocsDotRsProvider::id() { + return Ok(std::iter::once(ArgumentCompletion { + label: format!( + "Enter a {package_term} name or try one of these:", + package_term = package_term(&provider) + ), + new_text: provider.to_string(), + run_command: false, + }) + .chain(DocsDotRsProvider::AUTO_SUGGESTED_CRATES.into_iter().map( + |crate_name| ArgumentCompletion { + label: crate_name.to_string(), + new_text: format!("{provider} {crate_name}"), + run_command: true, + }, + )) + .collect()); + } + + return Ok(vec![ArgumentCompletion { + label: format!( + "Enter a {package_term} name.", + package_term = package_term(&provider) + ), + new_text: provider.to_string(), + run_command: false, + }]); + } + Ok(build_completions(provider, items)) } DocsSlashCommandArgs::SearchItemDocs { @@ -277,12 +307,10 @@ impl SlashCommand for DocsSlashCommand { }; if key.trim().is_empty() { - let package_term = match provider.as_ref() { - "docs-rs" | "rustdoc" => "crate", - _ => "package", - }; - - bail!("no {package_term} name provided"); + bail!( + "no {package_term} name provided", + package_term = package_term(&provider) + ); } let store = store?; @@ -407,6 +435,15 @@ impl DocsSlashCommandArgs { } } +/// Returns the term used to refer to a package. +fn package_term(provider: &ProviderId) -> &'static str { + if provider == &DocsDotRsProvider::id() || provider == &LocalRustdocProvider::id() { + return "crate"; + } + + "package" +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/indexed_docs/src/providers/rustdoc.rs b/crates/indexed_docs/src/providers/rustdoc.rs index 4e27792e79..f2526f3a73 100644 --- a/crates/indexed_docs/src/providers/rustdoc.rs +++ b/crates/indexed_docs/src/providers/rustdoc.rs @@ -98,6 +98,26 @@ pub struct DocsDotRsProvider { } impl DocsDotRsProvider { + /// The list of crates to auto-suggest for the docs.rs provider when + /// the index is empty. + /// + /// List has been chosen loosely based on [this list](https://lib.rs/std) of + /// popular Rust libraries. + /// + /// Keep this alphabetized. + pub const AUTO_SUGGESTED_CRATES: &'static [&'static str] = &[ + "anyhow", + "axum", + "chrono", + "itertools", + "rand", + "regex", + "serde", + "strum", + "thiserror", + "tokio", + ]; + pub fn id() -> ProviderId { ProviderId("docs-rs".into()) }