Rank exact extension ID matches higher in search results (#14588)

Release Notes:

- Improved relevance of extension search results

Co-authored-by: Marshall <marshall@zed.dev>
This commit is contained in:
Conrad Irwin 2024-07-16 12:33:28 -06:00 committed by GitHub
parent cf8bd4a90a
commit cb6fc11abc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 42 additions and 4 deletions

View File

@ -10,7 +10,7 @@ use axum::{
Extension, Json, Router, Extension, Json, Router,
}; };
use collections::HashMap; use collections::HashMap;
use rpc::{ExtensionApiManifest, GetExtensionsResponse}; use rpc::{ExtensionApiManifest, ExtensionMetadata, GetExtensionsResponse};
use semantic_version::SemanticVersion; use semantic_version::SemanticVersion;
use serde::Deserialize; use serde::Deserialize;
use std::{sync::Arc, time::Duration}; use std::{sync::Arc, time::Duration};
@ -43,7 +43,7 @@ async fn get_extensions(
Extension(app): Extension<Arc<AppState>>, Extension(app): Extension<Arc<AppState>>,
Query(params): Query<GetExtensionsParams>, Query(params): Query<GetExtensionsParams>,
) -> Result<Json<GetExtensionsResponse>> { ) -> Result<Json<GetExtensionsResponse>> {
let extensions = app let mut extensions = app
.db .db
.get_extensions(params.filter.as_deref(), params.max_schema_version, 500) .get_extensions(params.filter.as_deref(), params.max_schema_version, 500)
.await?; .await?;
@ -53,6 +53,23 @@ async fn get_extensions(
tracing::info!(query, count, "extension_search") tracing::info!(query, count, "extension_search")
} }
if let Some(filter) = params.filter.as_deref() {
let mut exact_match: Option<ExtensionMetadata> = None;
extensions.retain(|extension| {
exact_match = Some(extension.clone());
extension.id.as_ref() != &filter.to_lowercase()
});
if exact_match == None {
exact_match = app
.db
.get_extensions_by_ids(&[&filter.to_lowercase()], None)
.await?
.first()
.cloned();
}
extensions.splice(0..0, exact_match);
};
Ok(Json(GetExtensionsResponse { data: extensions })) Ok(Json(GetExtensionsResponse { data: extensions }))
} }

View File

@ -136,11 +136,14 @@ impl ExtensionFilter {
enum Feature { enum Feature {
Git, Git,
Vim, Vim,
LanguageBash,
LanguageC, LanguageC,
LanguageCpp, LanguageCpp,
LanguageGo, LanguageGo,
LanguagePython, LanguagePython,
LanguageReact,
LanguageRust, LanguageRust,
LanguageTypescript,
} }
fn keywords_by_feature() -> &'static BTreeMap<Feature, Vec<&'static str>> { fn keywords_by_feature() -> &'static BTreeMap<Feature, Vec<&'static str>> {
@ -149,11 +152,17 @@ fn keywords_by_feature() -> &'static BTreeMap<Feature, Vec<&'static str>> {
BTreeMap::from_iter([ BTreeMap::from_iter([
(Feature::Git, vec!["git"]), (Feature::Git, vec!["git"]),
(Feature::Vim, vec!["vim"]), (Feature::Vim, vec!["vim"]),
(Feature::LanguageBash, vec!["sh", "bash"]),
(Feature::LanguageC, vec!["c", "clang"]), (Feature::LanguageC, vec!["c", "clang"]),
(Feature::LanguageCpp, vec!["c++", "cpp", "clang"]), (Feature::LanguageCpp, vec!["c++", "cpp", "clang"]),
(Feature::LanguageGo, vec!["go", "golang"]), (Feature::LanguageGo, vec!["go", "golang"]),
(Feature::LanguagePython, vec!["python", "py"]), (Feature::LanguagePython, vec!["python", "py"]),
(Feature::LanguageReact, vec!["react"]),
(Feature::LanguageRust, vec!["rust", "rs"]), (Feature::LanguageRust, vec!["rust", "rs"]),
(
Feature::LanguageTypescript,
vec!["type", "typescript", "ts"],
),
]) ])
}) })
} }
@ -973,6 +982,10 @@ impl ExtensionsPage {
); );
}), }),
)), )),
Feature::LanguageBash => {
FeatureUpsell::new(telemetry, "Shell support is built-in to Zed!")
.docs_url("https://zed.dev/docs/languages/bash")
}
Feature::LanguageC => { Feature::LanguageC => {
FeatureUpsell::new(telemetry, "C support is built-in to Zed!") FeatureUpsell::new(telemetry, "C support is built-in to Zed!")
.docs_url("https://zed.dev/docs/languages/c") .docs_url("https://zed.dev/docs/languages/c")
@ -989,10 +1002,18 @@ impl ExtensionsPage {
FeatureUpsell::new(telemetry, "Python support is built-in to Zed!") FeatureUpsell::new(telemetry, "Python support is built-in to Zed!")
.docs_url("https://zed.dev/docs/languages/python") .docs_url("https://zed.dev/docs/languages/python")
} }
Feature::LanguageReact => {
FeatureUpsell::new(telemetry, "React support is built-in to Zed!")
.docs_url("https://zed.dev/docs/languages/typescript")
}
Feature::LanguageRust => { Feature::LanguageRust => {
FeatureUpsell::new(telemetry, "Rust support is built-in to Zed!") FeatureUpsell::new(telemetry, "Rust support is built-in to Zed!")
.docs_url("https://zed.dev/docs/languages/rust") .docs_url("https://zed.dev/docs/languages/rust")
} }
Feature::LanguageTypescript => {
FeatureUpsell::new(telemetry, "Typescript support is built-in to Zed!")
.docs_url("https://zed.dev/docs/languages/typescript")
}
}; };
upsell.when(ix < upsells_count, |upsell| upsell.border_b_1()) upsell.when(ix < upsells_count, |upsell| upsell.border_b_1())

View File

@ -2,7 +2,7 @@ use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::sync::Arc; use std::sync::Arc;
#[derive(Serialize, Deserialize, Debug, PartialEq)] #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
pub struct ExtensionApiManifest { pub struct ExtensionApiManifest {
pub name: String, pub name: String,
pub version: Arc<str>, pub version: Arc<str>,
@ -13,7 +13,7 @@ pub struct ExtensionApiManifest {
pub wasm_api_version: Option<String>, pub wasm_api_version: Option<String>,
} }
#[derive(Serialize, Deserialize, Debug, PartialEq)] #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
pub struct ExtensionMetadata { pub struct ExtensionMetadata {
pub id: Arc<str>, pub id: Arc<str>,
#[serde(flatten)] #[serde(flatten)]