forked from wingyplus/zed-powershell
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathpowershell.rs
More file actions
118 lines (103 loc) · 4.3 KB
/
powershell.rs
File metadata and controls
118 lines (103 loc) · 4.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use std::fs;
use std::path;
use zed_extension_api::{self as zed, Result};
struct PowerShellExtension {
/// The PowerShell binary, default to `pwsh`.
// TODO: allow to configure via Zed settings.
powershell_bin: Option<String>,
}
impl zed::Extension for PowerShellExtension {
fn new() -> Self
where
Self: Sized,
{
Self {
powershell_bin: None,
}
}
fn language_server_command(
&mut self,
language_server_id: &zed_extension_api::LanguageServerId,
worktree: &zed_extension_api::Worktree,
) -> zed_extension_api::Result<zed_extension_api::Command> {
let pwsh_bin = PowerShellExtension::powershell_binary_path(self, worktree).unwrap();
let bundle_path = self
.language_server_path(language_server_id)
.map_err(|err| format!("failed to get editor services: {}", err))?;
let command = format!("Import-Module (Join-Path '{bundle_path}' 'PowerShellEditorServices/PowerShellEditorServices.psd1'); Start-EditorServices -Stdio -SessionDetailsPath '{bundle_path}/powershell-es.session.json' -LogPath '{bundle_path}/logs' -FeatureFlags @() -AdditionalModules @() -HostName zed -HostProfileId 0 -HostVersion 1.0.0 -LogLevel Diagnostic");
Ok(zed::Command {
command: pwsh_bin,
args: vec![
"-NoLogo".to_string(),
"-NoProfile".to_string(),
"-Command".to_string(),
command.to_string(),
],
env: Default::default(),
})
}
}
impl PowerShellExtension {
fn powershell_binary_path(&mut self, worktree: &zed::Worktree) -> Result<String> {
let pwsh_path = match &self.powershell_bin {
Some(path) if fs::metadata(path).map_or(false, |stat| stat.is_file()) => path.clone(),
Some(path) => worktree
.which(path.clone().as_str())
.ok_or_else(|| "PowerShell must be installed for PowerShell Extension")?,
None => worktree
.which("pwsh")
.ok_or_else(|| "PowerShell must be installed for PowerShell Extension")?,
};
self.powershell_bin = Some(pwsh_path.clone());
Ok(pwsh_path)
}
fn language_server_path(
&mut self,
language_server_id: &zed_extension_api::LanguageServerId,
) -> Result<String> {
zed::set_language_server_installation_status(
language_server_id,
&zed::LanguageServerInstallationStatus::CheckingForUpdate,
);
let release = zed::latest_github_release(
"PowerShell/PowerShellEditorServices",
zed::GithubReleaseOptions {
require_assets: true,
pre_release: false,
},
)?;
let asset = release
.assets
.iter()
.find(|asset| asset.name == "PowerShellEditorServices.zip")
.ok_or_else(|| format!("no PowerShellEditorServices.zip found"))?;
let version_dir = format!("powershell-es-{}", release.version);
let lsp_path = format!("{version_dir}/PowerShellEditorServices/Start-EditorServices.ps1");
if !fs::metadata(&lsp_path).map_or(false, |stat| stat.is_file()) {
// Download the asset
zed::set_language_server_installation_status(
&language_server_id,
&zed::LanguageServerInstallationStatus::Downloading,
);
zed::download_file(
&asset.download_url,
&version_dir,
zed::DownloadedFileType::Zip,
)
.map_err(|err| format!("download error {}", err))?;
// Ensure the binary exists
let entries =
fs::read_dir(".").map_err(|e| format!("failed to list working directory {e}"))?;
for entry in entries {
let entry = entry.map_err(|e| format!("failed to load directory entry {e}"))?;
if entry.file_name().to_str() != Some(&version_dir) {
fs::remove_dir_all(entry.path()).ok();
}
}
}
let abs_path =
path::absolute(&version_dir).map_err(|e| format!("failed to get absolute path {e}"))?;
Ok(abs_path.display().to_string())
}
}
zed::register_extension!(PowerShellExtension);