Skip to content

Commit c7fab07

Browse files
authored
feat: mvp zed extension going (#75)
Get's a Zed Extension impl going. Where the LSP is downloaded from GitHub release assets. Even though Zed extensions are Rust projects, we shouldn't include that as part of our `hdx` workspace. Furthermore, we should treat the lsp as external, and not try to compile our lsp directly within the extension wasm. The `lsp` location is resolved through either; 1. env: `HDX_SERVER_PATH` (which is the same as the VSCode one) 1. we download it from GitHub's release assets ![CleanShot 2024-12-17 at 18 00 26](https://github.com/user-attachments/assets/d2d0ca5e-6724-4faf-b526-150661637b5e)
1 parent 7065ed9 commit c7fab07

File tree

8 files changed

+145
-6
lines changed

8 files changed

+145
-6
lines changed

.github/workflows/release.yml

+5-4
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
git config user.name "github-actions[bot]"
2424
git config user.email "github-actions[bot]@users.noreply.github.com"
2525
git tag -fa canary -m "Latest Continuous Release" ${GITHUB_SHA}
26-
git push --force-with-lease origin canaray:refs/tags/canary
26+
git push --force-with-lease origin canary:refs/tags/canary
2727
2828
build:
2929
if: |
@@ -96,13 +96,14 @@ jobs:
9696
BIN_NAME=hdx-${{ matrix.code-target }}
9797
mv target/${{ matrix.target }}/release/hdx $BIN_NAME
9898
99+
- run: chmod +x hdx-*
100+
99101
- name: Upload Binary
100102
uses: actions/upload-artifact@v4
101103
with:
102104
if-no-files-found: error
103105
name: binary-${{ matrix.code-target }}
104-
path: |
105-
hdx-*
106+
path: hdx-*
106107

107108
deploy:
108109
env:
@@ -121,7 +122,7 @@ jobs:
121122
cache: "npm"
122123
- name: Download Artifacts
123124
uses: actions/download-artifact@v4
124-
- run: cp binary-*/* packages/hdx/bin && chmod +x packages/hdx/bin/*
125+
- run: cp binary-*/* packages/hdx/bin
125126
- run: tree
126127
- run: npm i
127128
working-directory: ./packages/hdx

Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
[workspace]
22
resolver = "2"
33
members = ["crates/*"]
4+
exclude = ["packages/hdx_zed"]
45

56
[workspace.package]
67
authors = ["Keith Cirkel (https://keithcirkel.co.uk)"]
@@ -24,7 +25,7 @@ hdx_transform = { version = "0.0.0", path = "crates/hdx_transform" }
2425
hdx_highlight = { version = "0.0.0", path = "crates/hdx_highlight" }
2526
hdx_lsp = { version = "0.0.0", path = "crates/hdx_lsp" }
2627

27-
# Memory
28+
# Memory
2829
bumpalo = { version = "3.16.0" }
2930

3031
# Data structure libraries/helpers

packages/hdx_vscode/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"url": "https://github.com/sponsors/keithamus"
1010
},
1111
"license": "MIT",
12-
"author": "Keith Cirkel (https://keithcirke.co.uk)",
12+
"author": "Keith Cirkel (https://keithcirkel.co.uk)",
1313
"type": "commonjs",
1414
"main": "./src/main.js",
1515
"files": [

packages/hdx_zed/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Cargo.lock

packages/hdx_zed/Cargo.toml

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[package]
2+
name = "hdx_zed"
3+
version = "0.0.1"
4+
edition = "2021"
5+
6+
[lib]
7+
crate-type = ["cdylib"]
8+
9+
[dependencies]
10+
zed_extension_api = "0.1"

packages/hdx_zed/dev.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
To install the dev version of the zed extension:
2+
3+
1. `rustup target add wasm32-wasip1`
4+
2. Extensions > Install Dev Extension > Select the `pacakges/hdx_zed` folder
5+
3. You may wish to disable the default css LSP's:
6+
```json
7+
"language_servers": [
8+
"!vscode-css-language-server",
9+
"!tailwindcss-language-server",
10+
"..."
11+
]
12+
```

packages/hdx_zed/extension.toml

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
id = "hdx"
2+
name = "hdx"
3+
version = "0.0.1"
4+
schema_version = 1
5+
authors = ["Keith Cirkel (https://keithcirkel.co.uk)", "Marais Rossouw (https://marais.io)"]
6+
description = "Refreshing CSS!"
7+
repository = "https://github.com/keithamus/hdx"
8+
9+
[language_servers.hdx]
10+
language = "CSS"
11+
name = "hdx Language Server"

packages/hdx_zed/src/lib.rs

+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
use std::env;
2+
use std::fs;
3+
use zed_extension_api::{self as zed, Result};
4+
5+
// The bin at ~Library/Application Support/Zed/extensions/work/{NAME}
6+
// this does not need to be a constant, and may choose to resolve it in the #language_server_binary_path method
7+
const HDX_BIN_PATH: &str = "hdx";
8+
9+
struct HdxExtension;
10+
11+
impl HdxExtension {
12+
fn language_server_binary_path(
13+
&mut self,
14+
language_server_id: &zed_extension_api::LanguageServerId,
15+
worktree: &zed::Worktree,
16+
) -> Result<String> {
17+
if let Ok(path) = env::var("HDX_SERVER_PATH") {
18+
if fs::metadata(&path).map_or(false, |stat| stat.is_file()) {
19+
return Ok(path.to_string());
20+
}
21+
}
22+
23+
if let Some(path) = worktree.which("hdx") {
24+
return Ok(path);
25+
}
26+
27+
zed::set_language_server_installation_status(
28+
language_server_id,
29+
&zed::LanguageServerInstallationStatus::CheckingForUpdate,
30+
);
31+
32+
let release = zed::github_release_by_tag_name("keithamus/hdx", "canary")?;
33+
34+
let (platform, arch) = zed::current_platform();
35+
let asset_name = format!(
36+
"hdx-{platform}-{arch}",
37+
platform = match platform {
38+
zed::Os::Mac => "darwin",
39+
zed::Os::Linux => "linux",
40+
zed::Os::Windows => "win32",
41+
},
42+
arch = match arch {
43+
zed::Architecture::Aarch64 => "arm64",
44+
zed::Architecture::X8664 => "x64",
45+
_ => return Err(format!("unsupported architecture: {arch:?}")),
46+
},
47+
);
48+
49+
let asset = release
50+
.assets
51+
.iter()
52+
.find(|asset| asset.name == asset_name)
53+
.ok_or_else(|| format!("no asset found matching {:?}", asset_name))?;
54+
55+
if !fs::metadata(&asset_name).map_or(false, |stat| stat.is_file()) {
56+
zed::set_language_server_installation_status(
57+
language_server_id,
58+
&zed::LanguageServerInstallationStatus::Downloading,
59+
);
60+
61+
zed::download_file(&asset.download_url, HDX_BIN_PATH, zed::DownloadedFileType::Uncompressed)
62+
.map_err(|e| format!("failed to download file: {e}"))?;
63+
64+
zed::make_file_executable(HDX_BIN_PATH).map_err(|e| format!("failed to make file executable: {e}"))?;
65+
}
66+
67+
Ok(HDX_BIN_PATH.to_string())
68+
}
69+
}
70+
71+
impl zed::Extension for HdxExtension {
72+
fn new() -> Self {
73+
Self
74+
}
75+
76+
fn language_server_command(
77+
&mut self,
78+
language_server_id: &zed_extension_api::LanguageServerId,
79+
worktree: &zed_extension_api::Worktree,
80+
) -> zed_extension_api::Result<zed_extension_api::Command> {
81+
let settings = zed_extension_api::settings::LspSettings::for_worktree(language_server_id.as_ref(), worktree)?;
82+
83+
let mut args = vec![];
84+
85+
if let Some(settings) = settings.settings {
86+
let is_debug = settings.get("debug").and_then(|value| value.as_bool()).unwrap_or(false);
87+
88+
if is_debug {
89+
args.push("--debug".to_string());
90+
}
91+
}
92+
93+
args.push("lsp".to_string());
94+
95+
Ok(zed::Command {
96+
command: self.language_server_binary_path(language_server_id, worktree)?,
97+
args,
98+
env: Default::default(),
99+
})
100+
}
101+
}
102+
103+
zed::register_extension!(HdxExtension);

0 commit comments

Comments
 (0)