Provide wasm extensions with APIs needed for using pre-installed LSP binaries (#9085)
In this PR, we've added two new methods that LSP extensions can call: * `shell_env()`, for retrieving the environment variables set in the user's default shell in the worktree * `which(command)`, for looking up paths to an executable (accounting for the user's shell env in the worktree) To test this out, we moved the `uiua` language support into an extension. We went ahead and removed the built-in support, since this language is extremely obscure. Sorry @mikayla-maki. To continue coding in Uiua in Zed, for now you can `Add Dev Extension` from the extensions pane, and select the `extensions/uiua` directory in the Zed repo. Very soon, we'll support publishing these extensions so that you'll be able to just install it normally. Release Notes: - N/A --------- Co-authored-by: Marshall <marshall@zed.dev>
This commit is contained in:
parent
5abcc1c3c5
commit
8a6264d933
23 changed files with 235 additions and 256 deletions
|
@ -72,7 +72,7 @@ use std::{
|
|||
cmp::{self, Ordering},
|
||||
convert::TryInto,
|
||||
env,
|
||||
ffi::OsString,
|
||||
ffi::OsStr,
|
||||
hash::Hash,
|
||||
mem,
|
||||
num::NonZeroU32,
|
||||
|
@ -9390,6 +9390,7 @@ struct ProjectLspAdapterDelegate {
|
|||
fs: Arc<dyn Fs>,
|
||||
http_client: Arc<dyn HttpClient>,
|
||||
language_registry: Arc<LanguageRegistry>,
|
||||
shell_env: Mutex<Option<HashMap<String, String>>>,
|
||||
}
|
||||
|
||||
impl ProjectLspAdapterDelegate {
|
||||
|
@ -9400,8 +9401,21 @@ impl ProjectLspAdapterDelegate {
|
|||
fs: project.fs.clone(),
|
||||
http_client: project.client.http_client(),
|
||||
language_registry: project.languages.clone(),
|
||||
shell_env: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
async fn load_shell_env(&self) {
|
||||
let worktree_abs_path = self.worktree.abs_path();
|
||||
let shell_env = load_shell_environment(&worktree_abs_path)
|
||||
.await
|
||||
.with_context(|| {
|
||||
format!("failed to determine load login shell environment in {worktree_abs_path:?}")
|
||||
})
|
||||
.log_err()
|
||||
.unwrap_or_default();
|
||||
*self.shell_env.lock() = Some(shell_env);
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
|
@ -9416,32 +9430,20 @@ impl LspAdapterDelegate for ProjectLspAdapterDelegate {
|
|||
self.http_client.clone()
|
||||
}
|
||||
|
||||
async fn which_command(&self, command: OsString) -> Option<(PathBuf, HashMap<String, String>)> {
|
||||
async fn shell_env(&self) -> HashMap<String, String> {
|
||||
self.load_shell_env().await;
|
||||
self.shell_env.lock().as_ref().cloned().unwrap_or_default()
|
||||
}
|
||||
|
||||
async fn which(&self, command: &OsStr) -> Option<PathBuf> {
|
||||
let worktree_abs_path = self.worktree.abs_path();
|
||||
|
||||
let shell_env = load_shell_environment(&worktree_abs_path)
|
||||
.await
|
||||
.with_context(|| {
|
||||
format!("failed to determine load login shell environment in {worktree_abs_path:?}")
|
||||
})
|
||||
.log_err();
|
||||
|
||||
if let Some(shell_env) = shell_env {
|
||||
let shell_path = shell_env.get("PATH");
|
||||
match which::which_in(&command, shell_path, &worktree_abs_path) {
|
||||
Ok(command_path) => Some((command_path, shell_env)),
|
||||
Err(error) => {
|
||||
log::warn!(
|
||||
"failed to determine path for command {:?} in shell PATH {:?}: {error}",
|
||||
command.to_string_lossy(),
|
||||
shell_path.map(String::as_str).unwrap_or("")
|
||||
);
|
||||
None
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
self.load_shell_env().await;
|
||||
let shell_path = self
|
||||
.shell_env
|
||||
.lock()
|
||||
.as_ref()
|
||||
.and_then(|shell_env| shell_env.get("PATH").cloned());
|
||||
which::which_in(command, shell_path.as_ref(), &worktree_abs_path).ok()
|
||||
}
|
||||
|
||||
fn update_status(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue