Skip to content

Commit 3126305

Browse files
committed
add LSP support in Zed extension
1 parent 1da2db5 commit 3126305

File tree

4 files changed

+154
-2
lines changed

4 files changed

+154
-2
lines changed

.zed/settings.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"lsp": {
3+
"isograph": {
4+
"settings": {
5+
"rootDirectory": "./demos/pet-demo",
6+
"pathToIso": "scripts/start-debug-cli.js"
7+
}
8+
}
9+
}
10+
}

scripts/start-debug-cli.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
'use strict';
2+
3+
var path = require('path');
4+
var spawn = require('child_process').spawn;
5+
6+
var input = process.argv.slice(2);
7+
8+
spawn(path.join(__dirname, '../target/debug/isograph_cli'), input, {
9+
stdio: 'inherit',
10+
}).on('exit', process.exit);

zed-extension/extension.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,8 @@ repository = "https://github.com/XiNiHa/isograph"
1212
# TODO: switch to some valid commit
1313
rev = "tree-sitter"
1414
path = "tree-sitter"
15+
16+
[language_servers.isograph]
17+
name = "Isograph"
18+
language = "Isograph"
19+
languages = ["JavaScript", "JSX", "TypeScript", "TSX"]

zed-extension/src/lib.rs

Lines changed: 129 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,138 @@
1-
use zed_extension_api as zed;
1+
use std::{env, fs, path::PathBuf};
2+
3+
use zed_extension_api::{self as zed, Worktree};
4+
5+
const SERVER_PATH: &str = "node_modules/.bin/iso";
6+
const PACKAGE_NAME: &str = "@isograph/compiler";
27

38
struct IsographExtension;
49

10+
impl IsographExtension {
11+
fn server_exists(&self) -> bool {
12+
fs::metadata(SERVER_PATH).is_ok_and(|metadata| metadata.is_file())
13+
}
14+
15+
fn server_script_path(
16+
&mut self,
17+
language_server_id: &zed::LanguageServerId,
18+
path_to_iso: Option<String>,
19+
worktree: &Worktree,
20+
) -> zed::Result<String> {
21+
if let Some(path) = path_to_iso {
22+
println!(
23+
"You've manually specified 'pathToIso'. We cannot confirm this version of the Isograph Compiler is supported by this version of the extension. I hope you know what you're doing."
24+
);
25+
return Ok(PathBuf::from(worktree.root_path())
26+
.join(path)
27+
.to_string_lossy()
28+
.to_string());
29+
}
30+
31+
let server_path = env::current_dir()
32+
.unwrap()
33+
.join(SERVER_PATH)
34+
.to_string_lossy()
35+
.to_string();
36+
let server_exists = self.server_exists();
37+
if server_exists {
38+
return Ok(server_path);
39+
}
40+
41+
zed::set_language_server_installation_status(
42+
language_server_id,
43+
&zed::LanguageServerInstallationStatus::CheckingForUpdate,
44+
);
45+
let version = zed::npm_package_latest_version(PACKAGE_NAME)?;
46+
47+
if !server_exists
48+
|| zed::npm_package_installed_version(PACKAGE_NAME)?.as_ref() != Some(&version)
49+
{
50+
zed::set_language_server_installation_status(
51+
language_server_id,
52+
&zed::LanguageServerInstallationStatus::Downloading,
53+
);
54+
let result = zed::npm_install_package(PACKAGE_NAME, &version);
55+
match result {
56+
Ok(()) => {
57+
if !self.server_exists() {
58+
Err(format!(
59+
"installed package '{PACKAGE_NAME}' did not contain expected path '{SERVER_PATH}'",
60+
))?;
61+
}
62+
}
63+
Err(error) => {
64+
if !self.server_exists() {
65+
Err(error)?;
66+
}
67+
}
68+
}
69+
}
70+
71+
Ok(server_path)
72+
}
73+
}
74+
575
impl zed::Extension for IsographExtension {
676
fn new() -> Self {
7-
IsographExtension
77+
Self
78+
}
79+
80+
fn language_server_command(
81+
&mut self,
82+
language_server_id: &zed::LanguageServerId,
83+
worktree: &zed::Worktree,
84+
) -> zed::Result<zed::Command> {
85+
let settings = Settings::from_lsp_settings(zed::settings::LspSettings::for_worktree(
86+
language_server_id.as_ref(),
87+
worktree,
88+
)?);
89+
let server_path =
90+
self.server_script_path(language_server_id, settings.path_to_iso, worktree)?;
91+
92+
let args = vec![server_path, "lsp".to_string()];
93+
94+
let working_directory = settings
95+
.root_directory
96+
.unwrap_or_else(|| worktree.root_path());
97+
98+
Ok(zed::Command {
99+
command: "/bin/sh".to_string(),
100+
args: vec![
101+
"-c".to_string(),
102+
format!(
103+
r#"cd {}; "{}" {}"#,
104+
working_directory,
105+
zed::node_binary_path()?,
106+
args.into_iter()
107+
.map(|arg| format!(r#""{}""#, arg))
108+
.collect::<Vec<_>>()
109+
.join(" ")
110+
),
111+
],
112+
env: Vec::new(),
113+
})
8114
}
9115
}
10116

117+
struct Settings {
118+
root_directory: Option<String>,
119+
path_to_iso: Option<String>,
120+
}
121+
122+
impl Settings {
123+
fn from_lsp_settings(settings: zed::settings::LspSettings) -> Self {
124+
Settings {
125+
root_directory: settings.settings.as_ref().and_then(|s| {
126+
s.get("rootDirectory")
127+
.and_then(|v| v.as_str())
128+
.map(|v| v.to_string())
129+
}),
130+
path_to_iso: settings.settings.as_ref().and_then(|s| {
131+
s.get("pathToIso")
132+
.and_then(|v| v.as_str())
133+
.map(|v| v.to_string())
134+
}),
135+
}
136+
}
137+
}
11138
zed::register_extension!(IsographExtension);

0 commit comments

Comments
 (0)