extensions: Add support for snippets provided by extensions (#14020)

For now extensions can only register global snippets, but there'll be
follow-up work to support scope attribute in snippets.json.

Release Notes:

- Extensions can now provide snippets by including `snippets.json` file
next to the extension manifest.

---------

Co-authored-by: Marshall <marshall@zed.dev>
Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
This commit is contained in:
Piotr Osiewicz 2024-07-10 09:40:50 +02:00 committed by GitHub
parent 2f2047ab22
commit 6f99399224
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 129 additions and 16 deletions

View file

@ -44,6 +44,7 @@ use release_channel::ReleaseChannel;
use semantic_version::SemanticVersion;
use serde::{Deserialize, Serialize};
use settings::Settings;
use snippet_provider::SnippetRegistry;
use std::ops::RangeInclusive;
use std::str::FromStr;
use std::{
@ -115,6 +116,7 @@ pub struct ExtensionStore {
theme_registry: Arc<ThemeRegistry>,
slash_command_registry: Arc<SlashCommandRegistry>,
indexed_docs_registry: Arc<IndexedDocsRegistry>,
snippet_registry: Arc<SnippetRegistry>,
modified_extensions: HashSet<Arc<str>>,
wasm_host: Arc<WasmHost>,
wasm_extensions: Vec<(Arc<ExtensionManifest>, WasmExtension)>,
@ -193,6 +195,7 @@ pub fn init(
theme_registry,
SlashCommandRegistry::global(cx),
IndexedDocsRegistry::global(cx),
SnippetRegistry::global(cx),
cx,
)
});
@ -227,6 +230,7 @@ impl ExtensionStore {
theme_registry: Arc<ThemeRegistry>,
slash_command_registry: Arc<SlashCommandRegistry>,
indexed_docs_registry: Arc<IndexedDocsRegistry>,
snippet_registry: Arc<SnippetRegistry>,
cx: &mut ModelContext<Self>,
) -> Self {
let work_dir = extensions_dir.join("work");
@ -259,6 +263,7 @@ impl ExtensionStore {
theme_registry,
slash_command_registry,
indexed_docs_registry,
snippet_registry,
reload_tx,
tasks: Vec::new(),
};
@ -1045,6 +1050,7 @@ impl ExtensionStore {
.collect::<Vec<_>>();
let mut grammars_to_add = Vec::new();
let mut themes_to_add = Vec::new();
let mut snippets_to_add = Vec::new();
for extension_id in &extensions_to_load {
let Some(extension) = new_index.extensions.get(extension_id) else {
continue;
@ -1062,6 +1068,11 @@ impl ExtensionStore {
path.extend([Path::new(extension_id.as_ref()), theme_path.as_path()]);
path
}));
snippets_to_add.extend(extension.manifest.snippets.iter().map(|snippets_path| {
let mut path = self.installed_dir.clone();
path.extend([Path::new(extension_id.as_ref()), snippets_path.as_path()]);
path
}));
}
self.language_registry
@ -1097,6 +1108,7 @@ impl ExtensionStore {
let wasm_host = self.wasm_host.clone();
let root_dir = self.installed_dir.clone();
let theme_registry = self.theme_registry.clone();
let snippet_registry = self.snippet_registry.clone();
let extension_entries = extensions_to_load
.iter()
.filter_map(|name| new_index.extensions.get(name).cloned())
@ -1117,6 +1129,15 @@ impl ExtensionStore {
.await
.log_err();
}
for snippets_path in &snippets_to_add {
if let Some(snippets_contents) = fs.load(snippets_path).await.log_err()
{
snippet_registry
.register_snippets(snippets_path, &snippets_contents)
.log_err();
}
}
}
})
.await;