mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-24 17:28:40 +00:00
Install default prettier and plugins on startup
This commit is contained in:
parent
12ea12e4e7
commit
1ff17bd15d
2 changed files with 113 additions and 18 deletions
|
@ -204,10 +204,3 @@ async fn find_closest_prettier_dir(
|
|||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
async fn prepare_default_prettier(
|
||||
fs: Arc<dyn Fs>,
|
||||
node: Arc<dyn NodeRuntime>,
|
||||
) -> anyhow::Result<PathBuf> {
|
||||
todo!("TODO kb need to call per language that supports it, and have to use extra packages sometimes")
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ use futures::{
|
|||
mpsc::{self, UnboundedReceiver},
|
||||
oneshot,
|
||||
},
|
||||
future::{try_join_all, Shared},
|
||||
future::{self, try_join_all, Shared},
|
||||
stream::FuturesUnordered,
|
||||
AsyncWriteExt, Future, FutureExt, StreamExt, TryFutureExt,
|
||||
};
|
||||
|
@ -31,7 +31,9 @@ use gpui::{
|
|||
};
|
||||
use itertools::Itertools;
|
||||
use language::{
|
||||
language_settings::{language_settings, FormatOnSave, Formatter, InlayHintKind},
|
||||
language_settings::{
|
||||
language_settings, FormatOnSave, Formatter, InlayHintKind, LanguageSettings,
|
||||
},
|
||||
point_to_lsp,
|
||||
proto::{
|
||||
deserialize_anchor, deserialize_fingerprint, deserialize_line_ending, deserialize_version,
|
||||
|
@ -79,8 +81,11 @@ use std::{
|
|||
use terminals::Terminals;
|
||||
use text::Anchor;
|
||||
use util::{
|
||||
debug_panic, defer, http::HttpClient, merge_json_value_into,
|
||||
paths::LOCAL_SETTINGS_RELATIVE_PATH, post_inc, ResultExt, TryFutureExt as _,
|
||||
debug_panic, defer,
|
||||
http::HttpClient,
|
||||
merge_json_value_into,
|
||||
paths::{DEFAULT_PRETTIER_DIR, LOCAL_SETTINGS_RELATIVE_PATH},
|
||||
post_inc, ResultExt, TryFutureExt as _,
|
||||
};
|
||||
|
||||
pub use fs::*;
|
||||
|
@ -832,17 +837,28 @@ impl Project {
|
|||
|
||||
fn on_settings_changed(&mut self, cx: &mut ModelContext<Self>) {
|
||||
let mut language_servers_to_start = Vec::new();
|
||||
let mut language_formatters_to_check = Vec::new();
|
||||
for buffer in self.opened_buffers.values() {
|
||||
if let Some(buffer) = buffer.upgrade(cx) {
|
||||
let buffer = buffer.read(cx);
|
||||
if let Some((file, language)) = buffer.file().zip(buffer.language()) {
|
||||
let settings = language_settings(Some(language), Some(file), cx);
|
||||
let buffer_file = buffer.file();
|
||||
let buffer_language = buffer.language();
|
||||
let settings = language_settings(buffer_language, buffer_file, cx);
|
||||
if let Some(language) = buffer_language {
|
||||
if settings.enable_language_server {
|
||||
if let Some(file) = File::from_dyn(Some(file)) {
|
||||
if let Some(file) = File::from_dyn(buffer_file) {
|
||||
language_servers_to_start
|
||||
.push((file.worktree.clone(), language.clone()));
|
||||
.push((file.worktree.clone(), Arc::clone(language)));
|
||||
}
|
||||
}
|
||||
let worktree = buffer_file
|
||||
.map(|f| f.worktree_id())
|
||||
.map(WorktreeId::from_usize);
|
||||
language_formatters_to_check.push((
|
||||
worktree,
|
||||
Arc::clone(language),
|
||||
settings.clone(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -895,6 +911,11 @@ impl Project {
|
|||
.detach();
|
||||
}
|
||||
|
||||
// TODO kb restart all formatters if settings change
|
||||
for (worktree, language, settings) in language_formatters_to_check {
|
||||
self.maybe_start_default_formatters(worktree, &language, &settings, cx);
|
||||
}
|
||||
|
||||
// Start all the newly-enabled language servers.
|
||||
for (worktree, language) in language_servers_to_start {
|
||||
let worktree_path = worktree.read(cx).abs_path();
|
||||
|
@ -2643,7 +2664,15 @@ impl Project {
|
|||
}
|
||||
});
|
||||
|
||||
if let Some(file) = File::from_dyn(buffer.read(cx).file()) {
|
||||
let buffer_file = buffer.read(cx).file().cloned();
|
||||
let worktree = buffer_file
|
||||
.as_ref()
|
||||
.map(|f| f.worktree_id())
|
||||
.map(WorktreeId::from_usize);
|
||||
let settings = language_settings(Some(&new_language), buffer_file.as_ref(), cx).clone();
|
||||
self.maybe_start_default_formatters(worktree, &new_language, &settings, cx);
|
||||
|
||||
if let Some(file) = File::from_dyn(buffer_file.as_ref()) {
|
||||
let worktree = file.worktree.clone();
|
||||
if let Some(tree) = worktree.read(cx).as_local() {
|
||||
self.start_language_servers(&worktree, tree.abs_path().clone(), new_language, cx);
|
||||
|
@ -2651,8 +2680,6 @@ impl Project {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO kb 2 usages of this method (buffer language select + settings change) should take care of
|
||||
// `LspAdapter::enabled_formatters` collecting and initializing. Remove `Option<WorktreeId>` for prettier instances?
|
||||
fn start_language_servers(
|
||||
&mut self,
|
||||
worktree: &ModelHandle<Worktree>,
|
||||
|
@ -8279,6 +8306,81 @@ impl Project {
|
|||
});
|
||||
Some(task)
|
||||
}
|
||||
|
||||
fn maybe_start_default_formatters(
|
||||
&mut self,
|
||||
worktree: Option<WorktreeId>,
|
||||
new_language: &Language,
|
||||
language_settings: &LanguageSettings,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) {
|
||||
match &language_settings.formatter {
|
||||
Formatter::Prettier { .. } | Formatter::Auto => {}
|
||||
Formatter::LanguageServer | Formatter::External { .. } => return,
|
||||
};
|
||||
let Some(node) = self.node.as_ref().cloned() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let mut prettier_plugins = None;
|
||||
for formatter in new_language
|
||||
.lsp_adapters()
|
||||
.into_iter()
|
||||
.flat_map(|adapter| adapter.enabled_formatters())
|
||||
{
|
||||
match formatter {
|
||||
BundledFormatter::Prettier { plugin_names } => prettier_plugins
|
||||
.get_or_insert_with(|| HashSet::default())
|
||||
.extend(plugin_names),
|
||||
}
|
||||
}
|
||||
let Some(prettier_plugins) = prettier_plugins else {
|
||||
return;
|
||||
};
|
||||
|
||||
let default_prettier_dir = DEFAULT_PRETTIER_DIR.as_path();
|
||||
if let Some(_already_running) = self
|
||||
.prettier_instances
|
||||
.get(&(worktree, default_prettier_dir.to_path_buf()))
|
||||
{
|
||||
// TODO kb need to compare plugins, install missing and restart prettier
|
||||
return;
|
||||
}
|
||||
|
||||
let fs = Arc::clone(&self.fs);
|
||||
cx.background()
|
||||
.spawn(async move {
|
||||
let prettier_dir_metadata = fs.metadata(default_prettier_dir).await.with_context(|| format!("fetching FS metadata for prettier default dir {default_prettier_dir:?}"))?;
|
||||
if prettier_dir_metadata.is_none() {
|
||||
fs.create_dir(default_prettier_dir).await.with_context(|| format!("creating prettier default dir {default_prettier_dir:?}"))?;
|
||||
}
|
||||
|
||||
let packages_to_versions = future::try_join_all(
|
||||
prettier_plugins
|
||||
.iter()
|
||||
.map(|s| s.as_str())
|
||||
.chain(Some("prettier"))
|
||||
.map(|package_name| async {
|
||||
let returned_package_name = package_name.to_string();
|
||||
let latest_version = node.npm_package_latest_version(package_name)
|
||||
.await
|
||||
.with_context(|| {
|
||||
format!("fetching latest npm version for package {returned_package_name}")
|
||||
})?;
|
||||
anyhow::Ok((returned_package_name, latest_version))
|
||||
}),
|
||||
)
|
||||
.await
|
||||
.context("fetching latest npm versions")?;
|
||||
|
||||
let borrowed_packages = packages_to_versions.iter().map(|(package, version)| {
|
||||
(package.as_str(), version.as_str())
|
||||
}).collect::<Vec<_>>();
|
||||
node.npm_install_packages(default_prettier_dir, &borrowed_packages).await.context("fetching formatter packages")?;
|
||||
anyhow::Ok(())
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
}
|
||||
}
|
||||
|
||||
fn subscribe_for_copilot_events(
|
||||
|
|
Loading…
Reference in a new issue