Slightly better prettier settings and discovery
This commit is contained in:
parent
ce6b31d938
commit
4f956d71e2
8 changed files with 52 additions and 52 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -5531,6 +5531,7 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"util",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -201,6 +201,8 @@
|
||||||
// }
|
// }
|
||||||
// TODO kb description
|
// TODO kb description
|
||||||
"formatter": "auto",
|
"formatter": "auto",
|
||||||
|
// TODO kb description + better settings
|
||||||
|
"prettier": true,
|
||||||
// How to soft-wrap long lines of text. This setting can take
|
// How to soft-wrap long lines of text. This setting can take
|
||||||
// three values:
|
// three values:
|
||||||
//
|
//
|
||||||
|
|
|
@ -15,6 +15,7 @@ use fs::FakeFs;
|
||||||
use futures::{channel::oneshot, StreamExt as _};
|
use futures::{channel::oneshot, StreamExt as _};
|
||||||
use gpui::{executor::Deterministic, ModelHandle, Task, TestAppContext, WindowHandle};
|
use gpui::{executor::Deterministic, ModelHandle, Task, TestAppContext, WindowHandle};
|
||||||
use language::LanguageRegistry;
|
use language::LanguageRegistry;
|
||||||
|
use node_runtime::FakeNodeRuntime;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use project::{Project, WorktreeId};
|
use project::{Project, WorktreeId};
|
||||||
use rpc::RECEIVE_TIMEOUT;
|
use rpc::RECEIVE_TIMEOUT;
|
||||||
|
@ -218,6 +219,7 @@ impl TestServer {
|
||||||
build_window_options: |_, _, _| Default::default(),
|
build_window_options: |_, _, _| Default::default(),
|
||||||
initialize_workspace: |_, _, _, _| Task::ready(Ok(())),
|
initialize_workspace: |_, _, _, _| Task::ready(Ok(())),
|
||||||
background_actions: || &[],
|
background_actions: || &[],
|
||||||
|
node_runtime: FakeNodeRuntime::new(),
|
||||||
});
|
});
|
||||||
|
|
||||||
cx.update(|cx| {
|
cx.update(|cx| {
|
||||||
|
@ -569,6 +571,7 @@ impl TestClient {
|
||||||
self.client().clone(),
|
self.client().clone(),
|
||||||
self.app_state.user_store.clone(),
|
self.app_state.user_store.clone(),
|
||||||
self.app_state.languages.clone(),
|
self.app_state.languages.clone(),
|
||||||
|
self.app_state.node_runtime.clone(),
|
||||||
self.app_state.fs.clone(),
|
self.app_state.fs.clone(),
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
|
|
|
@ -47,6 +47,7 @@ pub struct LanguageSettings {
|
||||||
pub show_wrap_guides: bool,
|
pub show_wrap_guides: bool,
|
||||||
pub wrap_guides: Vec<usize>,
|
pub wrap_guides: Vec<usize>,
|
||||||
pub format_on_save: FormatOnSave,
|
pub format_on_save: FormatOnSave,
|
||||||
|
pub prettier: bool,
|
||||||
pub remove_trailing_whitespace_on_save: bool,
|
pub remove_trailing_whitespace_on_save: bool,
|
||||||
pub ensure_final_newline_on_save: bool,
|
pub ensure_final_newline_on_save: bool,
|
||||||
pub formatter: Formatter,
|
pub formatter: Formatter,
|
||||||
|
@ -92,6 +93,8 @@ pub struct LanguageSettingsContent {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub format_on_save: Option<FormatOnSave>,
|
pub format_on_save: Option<FormatOnSave>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
pub prettier: Option<bool>,
|
||||||
|
#[serde(default)]
|
||||||
pub remove_trailing_whitespace_on_save: Option<bool>,
|
pub remove_trailing_whitespace_on_save: Option<bool>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub ensure_final_newline_on_save: Option<bool>,
|
pub ensure_final_newline_on_save: Option<bool>,
|
||||||
|
@ -398,6 +401,7 @@ fn merge_settings(settings: &mut LanguageSettings, src: &LanguageSettingsContent
|
||||||
);
|
);
|
||||||
merge(&mut settings.formatter, src.formatter.clone());
|
merge(&mut settings.formatter, src.formatter.clone());
|
||||||
merge(&mut settings.format_on_save, src.format_on_save.clone());
|
merge(&mut settings.format_on_save, src.format_on_save.clone());
|
||||||
|
merge(&mut settings.prettier, src.prettier);
|
||||||
merge(
|
merge(
|
||||||
&mut settings.remove_trailing_whitespace_on_save,
|
&mut settings.remove_trailing_whitespace_on_save,
|
||||||
src.remove_trailing_whitespace_on_save,
|
src.remove_trailing_whitespace_on_save,
|
||||||
|
|
|
@ -11,6 +11,7 @@ language = { path = "../language" }
|
||||||
gpui = { path = "../gpui" }
|
gpui = { path = "../gpui" }
|
||||||
fs = { path = "../fs" }
|
fs = { path = "../fs" }
|
||||||
node_runtime = { path = "../node_runtime"}
|
node_runtime = { path = "../node_runtime"}
|
||||||
|
util = { path = "../util" }
|
||||||
|
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
serde_derive.workspace = true
|
serde_derive.workspace = true
|
||||||
|
|
|
@ -130,20 +130,21 @@ impl Prettier {
|
||||||
None => Vec::new(),
|
None => Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
match find_closest_prettier_path(paths_to_check, fs.as_ref())
|
match find_closest_prettier_dir(paths_to_check, fs.as_ref())
|
||||||
.await
|
.await
|
||||||
.with_context(|| format!("Finding prettier starting with {starting_path:?}"))?
|
.with_context(|| format!("finding prettier starting with {starting_path:?}"))?
|
||||||
{
|
{
|
||||||
Some(prettier_path) => Ok(prettier_path),
|
Some(prettier_dir) => Ok(prettier_dir),
|
||||||
None => {
|
None => Ok(util::paths::DEFAULT_PRETTIER_DIR.to_path_buf()),
|
||||||
// TODO kb return the default prettier, how, without state?
|
|
||||||
Ok(PathBuf::new())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn start(prettier_path: &Path, node: Arc<dyn NodeRuntime>) -> anyhow::Result<Self> {
|
pub async fn start(prettier_dir: &Path, node: Arc<dyn NodeRuntime>) -> anyhow::Result<Self> {
|
||||||
todo!()
|
anyhow::ensure!(
|
||||||
|
prettier_dir.is_dir(),
|
||||||
|
"Prettier dir {prettier_dir:?} is not a directory"
|
||||||
|
);
|
||||||
|
anyhow::bail!("TODO kb: start prettier server in {prettier_dir:?}")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn format(&self, buffer: &ModelHandle<Buffer>) -> anyhow::Result<Diff> {
|
pub async fn format(&self, buffer: &ModelHandle<Buffer>) -> anyhow::Result<Diff> {
|
||||||
|
@ -156,14 +157,14 @@ impl Prettier {
|
||||||
}
|
}
|
||||||
|
|
||||||
const PRETTIER_PACKAGE_NAME: &str = "prettier";
|
const PRETTIER_PACKAGE_NAME: &str = "prettier";
|
||||||
async fn find_closest_prettier_path(
|
async fn find_closest_prettier_dir(
|
||||||
paths_to_check: Vec<PathBuf>,
|
paths_to_check: Vec<PathBuf>,
|
||||||
fs: &dyn Fs,
|
fs: &dyn Fs,
|
||||||
) -> anyhow::Result<Option<PathBuf>> {
|
) -> anyhow::Result<Option<PathBuf>> {
|
||||||
for path in paths_to_check {
|
for path in paths_to_check {
|
||||||
let possible_package_json = path.join("package.json");
|
let possible_package_json = path.join("package.json");
|
||||||
if let Some(package_json_metadata) = fs
|
if let Some(package_json_metadata) = fs
|
||||||
.metadata(&path)
|
.metadata(&possible_package_json)
|
||||||
.await
|
.await
|
||||||
.with_context(|| format!("Fetching metadata for {possible_package_json:?}"))?
|
.with_context(|| format!("Fetching metadata for {possible_package_json:?}"))?
|
||||||
{
|
{
|
||||||
|
@ -192,7 +193,7 @@ async fn find_closest_prettier_path(
|
||||||
|
|
||||||
let possible_node_modules_location = path.join("node_modules").join(PRETTIER_PACKAGE_NAME);
|
let possible_node_modules_location = path.join("node_modules").join(PRETTIER_PACKAGE_NAME);
|
||||||
if let Some(node_modules_location_metadata) = fs
|
if let Some(node_modules_location_metadata) = fs
|
||||||
.metadata(&path)
|
.metadata(&possible_node_modules_location)
|
||||||
.await
|
.await
|
||||||
.with_context(|| format!("fetching metadata for {possible_node_modules_location:?}"))?
|
.with_context(|| format!("fetching metadata for {possible_node_modules_location:?}"))?
|
||||||
{
|
{
|
||||||
|
@ -203,3 +204,10 @@ async fn find_closest_prettier_path(
|
||||||
}
|
}
|
||||||
Ok(None)
|
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")
|
||||||
|
}
|
||||||
|
|
|
@ -154,7 +154,7 @@ pub struct Project {
|
||||||
copilot_lsp_subscription: Option<gpui::Subscription>,
|
copilot_lsp_subscription: Option<gpui::Subscription>,
|
||||||
copilot_log_subscription: Option<lsp::Subscription>,
|
copilot_log_subscription: Option<lsp::Subscription>,
|
||||||
current_lsp_settings: HashMap<Arc<str>, LspSettings>,
|
current_lsp_settings: HashMap<Arc<str>, LspSettings>,
|
||||||
node_runtime: Option<Arc<dyn NodeRuntime>>,
|
node: Option<Arc<dyn NodeRuntime>>,
|
||||||
prettier_instances: HashMap<
|
prettier_instances: HashMap<
|
||||||
(Option<WorktreeId>, PathBuf),
|
(Option<WorktreeId>, PathBuf),
|
||||||
Shared<Task<Result<Arc<Prettier>, Arc<anyhow::Error>>>>,
|
Shared<Task<Result<Arc<Prettier>, Arc<anyhow::Error>>>>,
|
||||||
|
@ -612,7 +612,7 @@ impl Project {
|
||||||
|
|
||||||
pub fn local(
|
pub fn local(
|
||||||
client: Arc<Client>,
|
client: Arc<Client>,
|
||||||
node_runtime: Arc<dyn NodeRuntime>,
|
node: Arc<dyn NodeRuntime>,
|
||||||
user_store: ModelHandle<UserStore>,
|
user_store: ModelHandle<UserStore>,
|
||||||
languages: Arc<LanguageRegistry>,
|
languages: Arc<LanguageRegistry>,
|
||||||
fs: Arc<dyn Fs>,
|
fs: Arc<dyn Fs>,
|
||||||
|
@ -668,7 +668,7 @@ impl Project {
|
||||||
copilot_lsp_subscription,
|
copilot_lsp_subscription,
|
||||||
copilot_log_subscription: None,
|
copilot_log_subscription: None,
|
||||||
current_lsp_settings: settings::get::<ProjectSettings>(cx).lsp.clone(),
|
current_lsp_settings: settings::get::<ProjectSettings>(cx).lsp.clone(),
|
||||||
node_runtime: Some(node_runtime),
|
node: Some(node),
|
||||||
prettier_instances: HashMap::default(),
|
prettier_instances: HashMap::default(),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -767,7 +767,7 @@ impl Project {
|
||||||
copilot_lsp_subscription,
|
copilot_lsp_subscription,
|
||||||
copilot_log_subscription: None,
|
copilot_log_subscription: None,
|
||||||
current_lsp_settings: settings::get::<ProjectSettings>(cx).lsp.clone(),
|
current_lsp_settings: settings::get::<ProjectSettings>(cx).lsp.clone(),
|
||||||
node_runtime: None,
|
node: None,
|
||||||
prettier_instances: HashMap::default(),
|
prettier_instances: HashMap::default(),
|
||||||
};
|
};
|
||||||
for worktree in worktrees {
|
for worktree in worktrees {
|
||||||
|
@ -802,8 +802,6 @@ impl Project {
|
||||||
root_paths: impl IntoIterator<Item = &Path>,
|
root_paths: impl IntoIterator<Item = &Path>,
|
||||||
cx: &mut gpui::TestAppContext,
|
cx: &mut gpui::TestAppContext,
|
||||||
) -> ModelHandle<Project> {
|
) -> ModelHandle<Project> {
|
||||||
use node_runtime::FakeNodeRuntime;
|
|
||||||
|
|
||||||
let mut languages = LanguageRegistry::test();
|
let mut languages = LanguageRegistry::test();
|
||||||
languages.set_executor(cx.background());
|
languages.set_executor(cx.background());
|
||||||
let http_client = util::http::FakeHttpClient::with_404_response();
|
let http_client = util::http::FakeHttpClient::with_404_response();
|
||||||
|
@ -812,7 +810,7 @@ impl Project {
|
||||||
let project = cx.update(|cx| {
|
let project = cx.update(|cx| {
|
||||||
Project::local(
|
Project::local(
|
||||||
client,
|
client,
|
||||||
FakeNodeRuntime::new(),
|
node_runtime::FakeNodeRuntime::new(),
|
||||||
user_store,
|
user_store,
|
||||||
Arc::new(languages),
|
Arc::new(languages),
|
||||||
fs,
|
fs,
|
||||||
|
@ -8202,43 +8200,25 @@ impl Project {
|
||||||
buffer: &ModelHandle<Buffer>,
|
buffer: &ModelHandle<Buffer>,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> Option<Task<Shared<Task<Result<Arc<Prettier>, Arc<anyhow::Error>>>>>> {
|
) -> Option<Task<Shared<Task<Result<Arc<Prettier>, Arc<anyhow::Error>>>>>> {
|
||||||
let node_runtime = Arc::clone(self.node_runtime.as_ref()?);
|
let buffer = buffer.read(cx);
|
||||||
let buffer_file = File::from_dyn(buffer.read(cx).file());
|
let buffer_file = buffer.file();
|
||||||
|
let language_settings = language_settings(buffer.language(), buffer_file, cx).clone();
|
||||||
|
if !language_settings.prettier {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let node = Arc::clone(self.node.as_ref()?);
|
||||||
|
let buffer_file = File::from_dyn(buffer_file);
|
||||||
let buffer_path = buffer_file.map(|file| Arc::clone(file.path()));
|
let buffer_path = buffer_file.map(|file| Arc::clone(file.path()));
|
||||||
let worktree_path = buffer_file
|
let worktree_path = buffer_file
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|file| file.worktree.read(cx).abs_path());
|
.map(|file| file.worktree.read(cx).abs_path());
|
||||||
let worktree_id = buffer_file.map(|file| file.worktree_id(cx));
|
let worktree_id = buffer_file.map(|file| file.worktree_id(cx));
|
||||||
|
|
||||||
// TODO kb return None if config opted out of prettier
|
|
||||||
if true {
|
|
||||||
let fs = Arc::clone(&self.fs);
|
|
||||||
let buffer_path = buffer_path.clone();
|
|
||||||
let worktree_path = worktree_path.clone();
|
|
||||||
cx.spawn(|_, _| async move {
|
|
||||||
let prettier_path = Prettier::locate(
|
|
||||||
worktree_path
|
|
||||||
.zip(buffer_path)
|
|
||||||
.map(|(worktree_root_path, starting_path)| {
|
|
||||||
dbg!(LocateStart {
|
|
||||||
worktree_root_path,
|
|
||||||
starting_path,
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
fs,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
dbg!(prettier_path);
|
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let task = cx.spawn(|this, mut cx| async move {
|
let task = cx.spawn(|this, mut cx| async move {
|
||||||
let fs = this.update(&mut cx, |project, _| Arc::clone(&project.fs));
|
let fs = this.update(&mut cx, |project, _| Arc::clone(&project.fs));
|
||||||
// TODO kb can we have a cache for this instead?
|
// TODO kb can we have a cache for this instead?
|
||||||
let prettier_path = match cx
|
let prettier_dir = match cx
|
||||||
.background()
|
.background()
|
||||||
.spawn(Prettier::locate(
|
.spawn(Prettier::locate(
|
||||||
worktree_path
|
worktree_path
|
||||||
|
@ -8263,21 +8243,21 @@ impl Project {
|
||||||
if let Some(existing_prettier) = this.update(&mut cx, |project, _| {
|
if let Some(existing_prettier) = this.update(&mut cx, |project, _| {
|
||||||
project
|
project
|
||||||
.prettier_instances
|
.prettier_instances
|
||||||
.get(&(worktree_id, prettier_path.clone()))
|
.get(&(worktree_id, prettier_dir.clone()))
|
||||||
.cloned()
|
.cloned()
|
||||||
}) {
|
}) {
|
||||||
return existing_prettier;
|
return existing_prettier;
|
||||||
}
|
}
|
||||||
|
|
||||||
let task_prettier_path = prettier_path.clone();
|
let task_prettier_dir = prettier_dir.clone();
|
||||||
let new_prettier_task = cx
|
let new_prettier_task = cx
|
||||||
.background()
|
.background()
|
||||||
.spawn(async move {
|
.spawn(async move {
|
||||||
Ok(Arc::new(
|
Ok(Arc::new(
|
||||||
Prettier::start(&task_prettier_path, node_runtime)
|
Prettier::start(&task_prettier_dir, node)
|
||||||
.await
|
.await
|
||||||
.with_context(|| {
|
.with_context(|| {
|
||||||
format!("starting new prettier for path {task_prettier_path:?}")
|
format!("starting new prettier for path {task_prettier_dir:?}")
|
||||||
})?,
|
})?,
|
||||||
))
|
))
|
||||||
.map_err(Arc::new)
|
.map_err(Arc::new)
|
||||||
|
@ -8286,7 +8266,7 @@ impl Project {
|
||||||
this.update(&mut cx, |project, _| {
|
this.update(&mut cx, |project, _| {
|
||||||
project
|
project
|
||||||
.prettier_instances
|
.prettier_instances
|
||||||
.insert((worktree_id, prettier_path), new_prettier_task.clone());
|
.insert((worktree_id, prettier_dir), new_prettier_task.clone());
|
||||||
});
|
});
|
||||||
new_prettier_task
|
new_prettier_task
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,6 +11,7 @@ lazy_static::lazy_static! {
|
||||||
pub static ref SUPPORT_DIR: PathBuf = HOME.join("Library/Application Support/Zed");
|
pub static ref SUPPORT_DIR: PathBuf = HOME.join("Library/Application Support/Zed");
|
||||||
pub static ref LANGUAGES_DIR: PathBuf = HOME.join("Library/Application Support/Zed/languages");
|
pub static ref LANGUAGES_DIR: PathBuf = HOME.join("Library/Application Support/Zed/languages");
|
||||||
pub static ref COPILOT_DIR: PathBuf = HOME.join("Library/Application Support/Zed/copilot");
|
pub static ref COPILOT_DIR: PathBuf = HOME.join("Library/Application Support/Zed/copilot");
|
||||||
|
pub static ref DEFAULT_PRETTIER_DIR: PathBuf = HOME.join("Library/Application Support/Zed/prettier");
|
||||||
pub static ref DB_DIR: PathBuf = HOME.join("Library/Application Support/Zed/db");
|
pub static ref DB_DIR: PathBuf = HOME.join("Library/Application Support/Zed/db");
|
||||||
pub static ref SETTINGS: PathBuf = CONFIG_DIR.join("settings.json");
|
pub static ref SETTINGS: PathBuf = CONFIG_DIR.join("settings.json");
|
||||||
pub static ref KEYMAP: PathBuf = CONFIG_DIR.join("keymap.json");
|
pub static ref KEYMAP: PathBuf = CONFIG_DIR.join("keymap.json");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue