diff --git a/Cargo.lock b/Cargo.lock index cb65bace02..bf7bea9f42 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12490,6 +12490,13 @@ dependencies = [ "zed_extension_api 0.0.4", ] +[[package]] +name = "zed_emmet" +version = "0.0.1" +dependencies = [ + "zed_extension_api 0.0.4", +] + [[package]] name = "zed_erlang" version = "0.0.1" diff --git a/Cargo.toml b/Cargo.toml index db2676af04..0955d9bdc9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -102,6 +102,7 @@ members = [ "extensions/astro", "extensions/clojure", "extensions/csharp", + "extensions/emmet", "extensions/erlang", "extensions/gleam", "extensions/haskell", diff --git a/extensions/emmet/.gitignore b/extensions/emmet/.gitignore new file mode 100644 index 0000000000..6aba30215e --- /dev/null +++ b/extensions/emmet/.gitignore @@ -0,0 +1,3 @@ +target +*.wasm +grammars diff --git a/extensions/emmet/Cargo.toml b/extensions/emmet/Cargo.toml new file mode 100644 index 0000000000..edeb75645f --- /dev/null +++ b/extensions/emmet/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "zed_emmet" +version = "0.0.1" +edition = "2021" +publish = false +license = "Apache-2.0" + +[lints] +workspace = true + +[lib] +path = "src/emmet.rs" +crate-type = ["cdylib"] + +[dependencies] +zed_extension_api = "0.0.4" diff --git a/extensions/emmet/LICENSE-APACHE b/extensions/emmet/LICENSE-APACHE new file mode 120000 index 0000000000..1cd601d0a3 --- /dev/null +++ b/extensions/emmet/LICENSE-APACHE @@ -0,0 +1 @@ +../../LICENSE-APACHE \ No newline at end of file diff --git a/extensions/emmet/extension.toml b/extensions/emmet/extension.toml new file mode 100644 index 0000000000..40572cfbc5 --- /dev/null +++ b/extensions/emmet/extension.toml @@ -0,0 +1,11 @@ +id = "emmet" +name = "Emmet" +description = "Emmet support" +version = "0.0.1" +schema_version = 1 +authors = [] +repository = "https://github.com/zed-industries/zed" + +[language_servers.emmet-language-server] +name = "Emmet Language Server" +language = "HTML" diff --git a/extensions/emmet/src/emmet.rs b/extensions/emmet/src/emmet.rs new file mode 100644 index 0000000000..40874b7b84 --- /dev/null +++ b/extensions/emmet/src/emmet.rs @@ -0,0 +1,93 @@ +use std::{env, fs}; +use zed_extension_api::{self as zed, Result}; + +struct EmmetExtension { + did_find_server: bool, +} + +const SERVER_PATH: &str = "node_modules/.bin/emmet-language-server"; +const PACKAGE_NAME: &str = "@olrtg/emmet-language-server"; + +impl EmmetExtension { + fn server_exists(&self) -> bool { + fs::metadata(SERVER_PATH).map_or(false, |stat| stat.is_file()) + } + + fn server_script_path(&mut self, config: zed::LanguageServerConfig) -> Result { + let server_exists = self.server_exists(); + if self.did_find_server && server_exists { + return Ok(SERVER_PATH.to_string()); + } + + zed::set_language_server_installation_status( + &config.name, + &zed::LanguageServerInstallationStatus::CheckingForUpdate, + ); + let version = zed::npm_package_latest_version(PACKAGE_NAME)?; + + if !server_exists + || zed::npm_package_installed_version(PACKAGE_NAME)?.as_ref() != Some(&version) + { + zed::set_language_server_installation_status( + &config.name, + &zed::LanguageServerInstallationStatus::Downloading, + ); + let result = zed::npm_install_package(PACKAGE_NAME, &version); + match result { + Ok(()) => { + if !self.server_exists() { + Err(format!( + "installed package '{PACKAGE_NAME}' did not contain expected path '{SERVER_PATH}'", + ))?; + } + } + Err(error) => { + if !self.server_exists() { + Err(error)?; + } + } + } + } + + self.did_find_server = true; + Ok(SERVER_PATH.to_string()) + } +} + +impl zed::Extension for EmmetExtension { + fn new() -> Self { + Self { + did_find_server: false, + } + } + + fn language_server_command( + &mut self, + config: zed::LanguageServerConfig, + _: &zed::Worktree, + ) -> Result { + let server_path = self.server_script_path(config)?; + Ok(zed::Command { + command: zed::node_binary_path()?, + args: vec![ + env::current_dir() + .unwrap() + .join(&server_path) + .to_string_lossy() + .to_string(), + "--stdio".to_string(), + ], + env: Default::default(), + }) + } + + fn language_server_initialization_options( + &mut self, + _: zed::LanguageServerConfig, + _: &zed::Worktree, + ) -> Result> { + Ok(None) + } +} + +zed::register_extension!(EmmetExtension);