Detailed changes
@@ -5815,6 +5815,26 @@ dependencies = [
"util",
]
+[[package]]
+name = "prettier2"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "client2",
+ "collections",
+ "fs",
+ "futures 0.3.28",
+ "gpui2",
+ "language2",
+ "log",
+ "lsp2",
+ "node_runtime",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "util",
+]
+
[[package]]
name = "pretty_assertions"
version = "1.4.0"
@@ -61,6 +61,7 @@ members = [
"crates/plugin_macros",
"crates/plugin_runtime",
"crates/prettier",
+ "crates/prettier2",
"crates/project",
"crates/project2",
"crates/project_panel",
@@ -22,6 +22,7 @@ use parking_lot::{Mutex, RwLock};
use slotmap::SlotMap;
use std::{
any::{type_name, Any, TypeId},
+ borrow::Borrow,
mem,
sync::{atomic::Ordering::SeqCst, Arc, Weak},
time::Duration,
@@ -670,29 +671,12 @@ impl Context for AppContext {
}
}
-impl MainThread<AppContext> {
- fn update<R>(&mut self, update: impl FnOnce(&mut Self) -> R) -> R {
- self.0.update(|cx| {
- update(unsafe {
- std::mem::transmute::<&mut AppContext, &mut MainThread<AppContext>>(cx)
- })
- })
- }
-
- pub(crate) fn update_window<R>(
- &mut self,
- id: WindowId,
- update: impl FnOnce(&mut MainThread<WindowContext>) -> R,
- ) -> Result<R> {
- self.0.update_window(id, |cx| {
- update(unsafe {
- std::mem::transmute::<&mut WindowContext, &mut MainThread<WindowContext>>(cx)
- })
- })
- }
-
+impl<C> MainThread<C>
+where
+ C: Borrow<AppContext>,
+{
pub(crate) fn platform(&self) -> &dyn Platform {
- self.platform.borrow_on_main_thread()
+ self.0.borrow().platform.borrow_on_main_thread()
}
pub fn activate(&self, ignoring_other_apps: bool) {
@@ -722,6 +706,28 @@ impl MainThread<AppContext> {
pub fn open_url(&self, url: &str) {
self.platform().open_url(url);
}
+}
+
+impl MainThread<AppContext> {
+ fn update<R>(&mut self, update: impl FnOnce(&mut Self) -> R) -> R {
+ self.0.update(|cx| {
+ update(unsafe {
+ std::mem::transmute::<&mut AppContext, &mut MainThread<AppContext>>(cx)
+ })
+ })
+ }
+
+ pub(crate) fn update_window<R>(
+ &mut self,
+ id: WindowId,
+ update: impl FnOnce(&mut MainThread<WindowContext>) -> R,
+ ) -> Result<R> {
+ self.0.update_window(id, |cx| {
+ update(unsafe {
+ std::mem::transmute::<&mut WindowContext, &mut MainThread<WindowContext>>(cx)
+ })
+ })
+ }
pub fn open_window<S: 'static + Send + Sync>(
&mut self,
@@ -56,7 +56,7 @@ pub use window::*;
use derive_more::{Deref, DerefMut};
use std::{
any::{Any, TypeId},
- borrow::Borrow,
+ borrow::{Borrow, BorrowMut},
mem,
ops::{Deref, DerefMut},
sync::Arc,
@@ -141,20 +141,29 @@ impl<C: Context> Context for MainThread<C> {
}
pub trait BorrowAppContext {
- fn app_mut(&mut self) -> &mut AppContext;
+ fn with_text_style<F, R>(&mut self, style: TextStyleRefinement, f: F) -> R
+ where
+ F: FnOnce(&mut Self) -> R;
+
+ fn set_global<T: Send + Sync + 'static>(&mut self, global: T);
+}
+impl<C> BorrowAppContext for C
+where
+ C: BorrowMut<AppContext>,
+{
fn with_text_style<F, R>(&mut self, style: TextStyleRefinement, f: F) -> R
where
F: FnOnce(&mut Self) -> R,
{
- self.app_mut().push_text_style(style);
+ self.borrow_mut().push_text_style(style);
let result = f(self);
- self.app_mut().pop_text_style();
+ self.borrow_mut().pop_text_style();
result
}
fn set_global<T: Send + Sync + 'static>(&mut self, global: T) {
- self.app_mut().set_global(global)
+ self.borrow_mut().set_global(global)
}
}
@@ -1,13 +1,13 @@
use crate::{
- px, size, Action, AnyBox, AnyView, AppContext, AsyncWindowContext, AvailableSpace,
- BorrowAppContext, Bounds, BoxShadow, Context, Corners, DevicePixels, DispatchContext,
- DisplayId, Edges, Effect, Element, EntityId, EventEmitter, FocusEvent, FontId, GlobalElementId,
- GlyphId, Handle, Hsla, ImageData, InputEvent, IsZero, KeyListener, KeyMatch, KeyMatcher,
- Keystroke, LayoutId, MainThread, MainThreadOnly, MonochromeSprite, MouseMoveEvent,
- MouseUpEvent, Path, Pixels, Platform, PlatformAtlas, PlatformWindow, Point, PolychromeSprite,
- Quad, Reference, RenderGlyphParams, RenderImageParams, RenderSvgParams, ScaledPixels,
- SceneBuilder, Shadow, SharedString, Size, Style, Subscription, TaffyLayoutEngine, Task,
- Underline, UnderlineStyle, WeakHandle, WindowOptions, SUBPIXEL_VARIANTS,
+ px, size, Action, AnyBox, AnyView, AppContext, AsyncWindowContext, AvailableSpace, Bounds,
+ BoxShadow, Context, Corners, DevicePixels, DispatchContext, DisplayId, Edges, Effect, Element,
+ EntityId, EventEmitter, FocusEvent, FontId, GlobalElementId, GlyphId, Handle, Hsla, ImageData,
+ InputEvent, IsZero, KeyListener, KeyMatch, KeyMatcher, Keystroke, LayoutId, MainThread,
+ MainThreadOnly, MonochromeSprite, MouseMoveEvent, MouseUpEvent, Path, Pixels, PlatformAtlas,
+ PlatformWindow, Point, PolychromeSprite, Quad, Reference, RenderGlyphParams, RenderImageParams,
+ RenderSvgParams, ScaledPixels, SceneBuilder, Shadow, SharedString, Size, Style, Subscription,
+ TaffyLayoutEngine, Task, Underline, UnderlineStyle, WeakHandle, WindowOptions,
+ SUBPIXEL_VARIANTS,
};
use anyhow::Result;
use collections::HashMap;
@@ -17,7 +17,7 @@ use slotmap::SlotMap;
use smallvec::SmallVec;
use std::{
any::{Any, TypeId},
- borrow::Cow,
+ borrow::{Borrow, BorrowMut, Cow},
fmt::Debug,
future::Future,
marker::PhantomData,
@@ -1122,12 +1122,6 @@ impl<'a, 'w> WindowContext<'a, 'w> {
}
}
-impl<'a, 'w> MainThread<WindowContext<'a, 'w>> {
- fn platform(&self) -> &dyn Platform {
- self.platform.borrow_on_main_thread()
- }
-}
-
impl Context for WindowContext<'_, '_> {
type EntityContext<'a, 'w, T: 'static + Send + Sync> = ViewContext<'a, 'w, T>;
type Result<T> = T;
@@ -1174,15 +1168,30 @@ impl<'a, 'w> std::ops::DerefMut for WindowContext<'a, 'w> {
}
}
-impl BorrowAppContext for WindowContext<'_, '_> {
- fn app_mut(&mut self) -> &mut AppContext {
- &mut *self.app
+impl<'a, 'w> Borrow<AppContext> for WindowContext<'a, 'w> {
+ fn borrow(&self) -> &AppContext {
+ &self.app
+ }
+}
+
+impl<'a, 'w> BorrowMut<AppContext> for WindowContext<'a, 'w> {
+ fn borrow_mut(&mut self) -> &mut AppContext {
+ &mut self.app
}
}
-pub trait BorrowWindow: BorrowAppContext {
- fn window(&self) -> &Window;
- fn window_mut(&mut self) -> &mut Window;
+pub trait BorrowWindow: BorrowMut<Window> + BorrowMut<AppContext> {
+ fn app_mut(&mut self) -> &mut AppContext {
+ self.borrow_mut()
+ }
+
+ fn window(&self) -> &Window {
+ self.borrow()
+ }
+
+ fn window_mut(&mut self) -> &mut Window {
+ self.borrow_mut()
+ }
fn with_element_id<R>(
&mut self,
@@ -1205,7 +1214,8 @@ pub trait BorrowWindow: BorrowAppContext {
}
let result = f(global_id, self);
- self.window_mut().element_id_stack.pop();
+ let window: &mut Window = self.borrow_mut();
+ window.element_id_stack.pop();
result
}
@@ -1308,34 +1318,46 @@ pub trait BorrowWindow: BorrowAppContext {
}
}
-impl BorrowWindow for WindowContext<'_, '_> {
- fn window(&self) -> &Window {
- &*self.window
+impl Borrow<Window> for WindowContext<'_, '_> {
+ fn borrow(&self) -> &Window {
+ &self.window
}
+}
- fn window_mut(&mut self) -> &mut Window {
- &mut *self.window
+impl BorrowMut<Window> for WindowContext<'_, '_> {
+ fn borrow_mut(&mut self) -> &mut Window {
+ &mut self.window
}
}
-pub struct ViewContext<'a, 'w, S> {
+impl<T> BorrowWindow for T where T: BorrowMut<AppContext> + BorrowMut<Window> {}
+
+pub struct ViewContext<'a, 'w, V> {
window_cx: WindowContext<'a, 'w>,
- entity_type: PhantomData<S>,
+ entity_type: PhantomData<V>,
entity_id: EntityId,
}
-impl<S> BorrowAppContext for ViewContext<'_, '_, S> {
- fn app_mut(&mut self) -> &mut AppContext {
+impl<V> Borrow<AppContext> for ViewContext<'_, '_, V> {
+ fn borrow(&self) -> &AppContext {
+ &*self.window_cx.app
+ }
+}
+
+impl<V> BorrowMut<AppContext> for ViewContext<'_, '_, V> {
+ fn borrow_mut(&mut self) -> &mut AppContext {
&mut *self.window_cx.app
}
}
-impl<S> BorrowWindow for ViewContext<'_, '_, S> {
- fn window(&self) -> &Window {
- &self.window_cx.window
+impl<V> Borrow<Window> for ViewContext<'_, '_, V> {
+ fn borrow(&self) -> &Window {
+ &*self.window_cx.window
}
+}
- fn window_mut(&mut self) -> &mut Window {
+impl<V> BorrowMut<Window> for ViewContext<'_, '_, V> {
+ fn borrow_mut(&mut self) -> &mut Window {
&mut *self.window_cx.window
}
}
@@ -0,0 +1,34 @@
+[package]
+name = "prettier2"
+version = "0.1.0"
+edition = "2021"
+publish = false
+
+[lib]
+path = "src/prettier2.rs"
+doctest = false
+
+[features]
+test-support = []
+
+[dependencies]
+client2 = { path = "../client2" }
+collections = { path = "../collections"}
+language2 = { path = "../language2" }
+gpui2 = { path = "../gpui2" }
+fs = { path = "../fs" }
+lsp2 = { path = "../lsp2" }
+node_runtime = { path = "../node_runtime"}
+util = { path = "../util" }
+
+log.workspace = true
+serde.workspace = true
+serde_derive.workspace = true
+serde_json.workspace = true
+anyhow.workspace = true
+futures.workspace = true
+
+[dev-dependencies]
+language2 = { path = "../language2", features = ["test-support"] }
+gpui2 = { path = "../gpui2", features = ["test-support"] }
+fs = { path = "../fs", features = ["test-support"] }
@@ -0,0 +1,513 @@
+use anyhow::Context;
+use collections::{HashMap, HashSet};
+use fs::Fs;
+use gpui2::{AsyncAppContext, Handle};
+use language2::{language_settings::language_settings, Buffer, BundledFormatter, Diff};
+use lsp2::{LanguageServer, LanguageServerId};
+use node_runtime::NodeRuntime;
+use serde::{Deserialize, Serialize};
+use std::{
+ collections::VecDeque,
+ path::{Path, PathBuf},
+ sync::Arc,
+};
+use util::paths::DEFAULT_PRETTIER_DIR;
+
+pub enum Prettier {
+ Real(RealPrettier),
+ #[cfg(any(test, feature = "test-support"))]
+ Test(TestPrettier),
+}
+
+pub struct RealPrettier {
+ worktree_id: Option<usize>,
+ default: bool,
+ prettier_dir: PathBuf,
+ server: Arc<LanguageServer>,
+}
+
+#[cfg(any(test, feature = "test-support"))]
+pub struct TestPrettier {
+ worktree_id: Option<usize>,
+ prettier_dir: PathBuf,
+ default: bool,
+}
+
+#[derive(Debug)]
+pub struct LocateStart {
+ pub worktree_root_path: Arc<Path>,
+ pub starting_path: Arc<Path>,
+}
+
+pub const PRETTIER_SERVER_FILE: &str = "prettier_server.js";
+pub const PRETTIER_SERVER_JS: &str = include_str!("./prettier_server.js");
+const PRETTIER_PACKAGE_NAME: &str = "prettier";
+const TAILWIND_PRETTIER_PLUGIN_PACKAGE_NAME: &str = "prettier-plugin-tailwindcss";
+
+impl Prettier {
+ pub const CONFIG_FILE_NAMES: &'static [&'static str] = &[
+ ".prettierrc",
+ ".prettierrc.json",
+ ".prettierrc.json5",
+ ".prettierrc.yaml",
+ ".prettierrc.yml",
+ ".prettierrc.toml",
+ ".prettierrc.js",
+ ".prettierrc.cjs",
+ "package.json",
+ "prettier.config.js",
+ "prettier.config.cjs",
+ ".editorconfig",
+ ];
+
+ #[cfg(any(test, feature = "test-support"))]
+ pub const FORMAT_SUFFIX: &str = "\nformatted by test prettier";
+
+ pub async fn locate(
+ starting_path: Option<LocateStart>,
+ fs: Arc<dyn Fs>,
+ ) -> anyhow::Result<PathBuf> {
+ let paths_to_check = match starting_path.as_ref() {
+ Some(starting_path) => {
+ let worktree_root = starting_path
+ .worktree_root_path
+ .components()
+ .into_iter()
+ .take_while(|path_component| {
+ path_component.as_os_str().to_string_lossy() != "node_modules"
+ })
+ .collect::<PathBuf>();
+
+ if worktree_root != starting_path.worktree_root_path.as_ref() {
+ vec![worktree_root]
+ } else {
+ let (worktree_root_metadata, start_path_metadata) = if starting_path
+ .starting_path
+ .as_ref()
+ == Path::new("")
+ {
+ let worktree_root_data =
+ fs.metadata(&worktree_root).await.with_context(|| {
+ format!(
+ "FS metadata fetch for worktree root path {worktree_root:?}",
+ )
+ })?;
+ (worktree_root_data.unwrap_or_else(|| {
+ panic!("cannot query prettier for non existing worktree root at {worktree_root_data:?}")
+ }), None)
+ } else {
+ let full_starting_path = worktree_root.join(&starting_path.starting_path);
+ let (worktree_root_data, start_path_data) = futures::try_join!(
+ fs.metadata(&worktree_root),
+ fs.metadata(&full_starting_path),
+ )
+ .with_context(|| {
+ format!("FS metadata fetch for starting path {full_starting_path:?}",)
+ })?;
+ (
+ worktree_root_data.unwrap_or_else(|| {
+ panic!("cannot query prettier for non existing worktree root at {worktree_root_data:?}")
+ }),
+ start_path_data,
+ )
+ };
+
+ match start_path_metadata {
+ Some(start_path_metadata) => {
+ anyhow::ensure!(worktree_root_metadata.is_dir,
+ "For non-empty start path, worktree root {starting_path:?} should be a directory");
+ anyhow::ensure!(
+ !start_path_metadata.is_dir,
+ "For non-empty start path, it should not be a directory {starting_path:?}"
+ );
+ anyhow::ensure!(
+ !start_path_metadata.is_symlink,
+ "For non-empty start path, it should not be a symlink {starting_path:?}"
+ );
+
+ let file_to_format = starting_path.starting_path.as_ref();
+ let mut paths_to_check = VecDeque::from(vec![worktree_root.clone()]);
+ let mut current_path = worktree_root;
+ for path_component in file_to_format.components().into_iter() {
+ current_path = current_path.join(path_component);
+ paths_to_check.push_front(current_path.clone());
+ if path_component.as_os_str().to_string_lossy() == "node_modules" {
+ break;
+ }
+ }
+ paths_to_check.pop_front(); // last one is the file itself or node_modules, skip it
+ Vec::from(paths_to_check)
+ }
+ None => {
+ anyhow::ensure!(
+ !worktree_root_metadata.is_dir,
+ "For empty start path, worktree root should not be a directory {starting_path:?}"
+ );
+ anyhow::ensure!(
+ !worktree_root_metadata.is_symlink,
+ "For empty start path, worktree root should not be a symlink {starting_path:?}"
+ );
+ worktree_root
+ .parent()
+ .map(|path| vec![path.to_path_buf()])
+ .unwrap_or_default()
+ }
+ }
+ }
+ }
+ None => Vec::new(),
+ };
+
+ match find_closest_prettier_dir(paths_to_check, fs.as_ref())
+ .await
+ .with_context(|| format!("finding prettier starting with {starting_path:?}"))?
+ {
+ Some(prettier_dir) => Ok(prettier_dir),
+ None => Ok(DEFAULT_PRETTIER_DIR.to_path_buf()),
+ }
+ }
+
+ #[cfg(any(test, feature = "test-support"))]
+ pub async fn start(
+ worktree_id: Option<usize>,
+ _: LanguageServerId,
+ prettier_dir: PathBuf,
+ _: Arc<dyn NodeRuntime>,
+ _: AsyncAppContext,
+ ) -> anyhow::Result<Self> {
+ Ok(
+ #[cfg(any(test, feature = "test-support"))]
+ Self::Test(TestPrettier {
+ worktree_id,
+ default: prettier_dir == DEFAULT_PRETTIER_DIR.as_path(),
+ prettier_dir,
+ }),
+ )
+ }
+
+ #[cfg(not(any(test, feature = "test-support")))]
+ pub async fn start(
+ worktree_id: Option<usize>,
+ server_id: LanguageServerId,
+ prettier_dir: PathBuf,
+ node: Arc<dyn NodeRuntime>,
+ cx: AsyncAppContext,
+ ) -> anyhow::Result<Self> {
+ use lsp2::LanguageServerBinary;
+
+ let executor = cx.executor();
+ anyhow::ensure!(
+ prettier_dir.is_dir(),
+ "Prettier dir {prettier_dir:?} is not a directory"
+ );
+ let prettier_server = DEFAULT_PRETTIER_DIR.join(PRETTIER_SERVER_FILE);
+ anyhow::ensure!(
+ prettier_server.is_file(),
+ "no prettier server package found at {prettier_server:?}"
+ );
+
+ let node_path = executor
+ .spawn(async move { node.binary_path().await })
+ .await?;
+ let server = LanguageServer::new(
+ server_id,
+ LanguageServerBinary {
+ path: node_path,
+ arguments: vec![prettier_server.into(), prettier_dir.as_path().into()],
+ },
+ Path::new("/"),
+ None,
+ cx,
+ )
+ .context("prettier server creation")?;
+ let server = executor
+ .spawn(server.initialize(None))
+ .await
+ .context("prettier server initialization")?;
+ Ok(Self::Real(RealPrettier {
+ worktree_id,
+ server,
+ default: prettier_dir == DEFAULT_PRETTIER_DIR.as_path(),
+ prettier_dir,
+ }))
+ }
+
+ pub async fn format(
+ &self,
+ buffer: &Handle<Buffer>,
+ buffer_path: Option<PathBuf>,
+ cx: &mut AsyncAppContext,
+ ) -> anyhow::Result<Diff> {
+ match self {
+ Self::Real(local) => {
+ let params = buffer.update(cx, |buffer, cx| {
+ let buffer_language = buffer.language();
+ let parsers_with_plugins = buffer_language
+ .into_iter()
+ .flat_map(|language| {
+ language
+ .lsp_adapters()
+ .iter()
+ .flat_map(|adapter| adapter.enabled_formatters())
+ .filter_map(|formatter| match formatter {
+ BundledFormatter::Prettier {
+ parser_name,
+ plugin_names,
+ } => Some((parser_name, plugin_names)),
+ })
+ })
+ .fold(
+ HashMap::default(),
+ |mut parsers_with_plugins, (parser_name, plugins)| {
+ match parser_name {
+ Some(parser_name) => parsers_with_plugins
+ .entry(parser_name)
+ .or_insert_with(HashSet::default)
+ .extend(plugins),
+ None => parsers_with_plugins.values_mut().for_each(|existing_plugins| {
+ existing_plugins.extend(plugins.iter());
+ }),
+ }
+ parsers_with_plugins
+ },
+ );
+
+ let selected_parser_with_plugins = parsers_with_plugins.iter().max_by_key(|(_, plugins)| plugins.len());
+ if parsers_with_plugins.len() > 1 {
+ log::warn!("Found multiple parsers with plugins {parsers_with_plugins:?}, will select only one: {selected_parser_with_plugins:?}");
+ }
+
+ let prettier_node_modules = self.prettier_dir().join("node_modules");
+ anyhow::ensure!(prettier_node_modules.is_dir(), "Prettier node_modules dir does not exist: {prettier_node_modules:?}");
+ let plugin_name_into_path = |plugin_name: &str| {
+ let prettier_plugin_dir = prettier_node_modules.join(plugin_name);
+ for possible_plugin_path in [
+ prettier_plugin_dir.join("dist").join("index.mjs"),
+ prettier_plugin_dir.join("dist").join("index.js"),
+ prettier_plugin_dir.join("dist").join("plugin.js"),
+ prettier_plugin_dir.join("index.mjs"),
+ prettier_plugin_dir.join("index.js"),
+ prettier_plugin_dir.join("plugin.js"),
+ prettier_plugin_dir,
+ ] {
+ if possible_plugin_path.is_file() {
+ return Some(possible_plugin_path);
+ }
+ }
+ None
+ };
+ let (parser, located_plugins) = match selected_parser_with_plugins {
+ Some((parser, plugins)) => {
+ // Tailwind plugin requires being added last
+ // https://github.com/tailwindlabs/prettier-plugin-tailwindcss#compatibility-with-other-prettier-plugins
+ let mut add_tailwind_back = false;
+
+ let mut plugins = plugins.into_iter().filter(|&&plugin_name| {
+ if plugin_name == TAILWIND_PRETTIER_PLUGIN_PACKAGE_NAME {
+ add_tailwind_back = true;
+ false
+ } else {
+ true
+ }
+ }).map(|plugin_name| (plugin_name, plugin_name_into_path(plugin_name))).collect::<Vec<_>>();
+ if add_tailwind_back {
+ plugins.push((&TAILWIND_PRETTIER_PLUGIN_PACKAGE_NAME, plugin_name_into_path(TAILWIND_PRETTIER_PLUGIN_PACKAGE_NAME)));
+ }
+ (Some(parser.to_string()), plugins)
+ },
+ None => (None, Vec::new()),
+ };
+
+ let prettier_options = if self.is_default() {
+ let language_settings = language_settings(buffer_language, buffer.file(), cx);
+ let mut options = language_settings.prettier.clone();
+ if !options.contains_key("tabWidth") {
+ options.insert(
+ "tabWidth".to_string(),
+ serde_json::Value::Number(serde_json::Number::from(
+ language_settings.tab_size.get(),
+ )),
+ );
+ }
+ if !options.contains_key("printWidth") {
+ options.insert(
+ "printWidth".to_string(),
+ serde_json::Value::Number(serde_json::Number::from(
+ language_settings.preferred_line_length,
+ )),
+ );
+ }
+ Some(options)
+ } else {
+ None
+ };
+
+ let plugins = located_plugins.into_iter().filter_map(|(plugin_name, located_plugin_path)| {
+ match located_plugin_path {
+ Some(path) => Some(path),
+ None => {
+ log::error!("Have not found plugin path for {plugin_name:?} inside {prettier_node_modules:?}");
+ None},
+ }
+ }).collect();
+ log::debug!("Formatting file {:?} with prettier, plugins :{plugins:?}, options: {prettier_options:?}", buffer.file().map(|f| f.full_path(cx)));
+
+ anyhow::Ok(FormatParams {
+ text: buffer.text(),
+ options: FormatOptions {
+ parser,
+ plugins,
+ path: buffer_path,
+ prettier_options,
+ },
+ })
+ })?.context("prettier params calculation")?;
+ let response = local
+ .server
+ .request::<Format>(params)
+ .await
+ .context("prettier format request")?;
+ let diff_task = buffer.update(cx, |buffer, cx| buffer.diff(response.text, cx))?;
+ Ok(diff_task.await)
+ }
+ #[cfg(any(test, feature = "test-support"))]
+ Self::Test(_) => Ok(buffer
+ .update(cx, |buffer, cx| {
+ let formatted_text = buffer.text() + Self::FORMAT_SUFFIX;
+ buffer.diff(formatted_text, cx)
+ })?
+ .await),
+ }
+ }
+
+ pub async fn clear_cache(&self) -> anyhow::Result<()> {
+ match self {
+ Self::Real(local) => local
+ .server
+ .request::<ClearCache>(())
+ .await
+ .context("prettier clear cache"),
+ #[cfg(any(test, feature = "test-support"))]
+ Self::Test(_) => Ok(()),
+ }
+ }
+
+ pub fn server(&self) -> Option<&Arc<LanguageServer>> {
+ match self {
+ Self::Real(local) => Some(&local.server),
+ #[cfg(any(test, feature = "test-support"))]
+ Self::Test(_) => None,
+ }
+ }
+
+ pub fn is_default(&self) -> bool {
+ match self {
+ Self::Real(local) => local.default,
+ #[cfg(any(test, feature = "test-support"))]
+ Self::Test(test_prettier) => test_prettier.default,
+ }
+ }
+
+ pub fn prettier_dir(&self) -> &Path {
+ match self {
+ Self::Real(local) => &local.prettier_dir,
+ #[cfg(any(test, feature = "test-support"))]
+ Self::Test(test_prettier) => &test_prettier.prettier_dir,
+ }
+ }
+
+ pub fn worktree_id(&self) -> Option<usize> {
+ match self {
+ Self::Real(local) => local.worktree_id,
+ #[cfg(any(test, feature = "test-support"))]
+ Self::Test(test_prettier) => test_prettier.worktree_id,
+ }
+ }
+}
+
+async fn find_closest_prettier_dir(
+ paths_to_check: Vec<PathBuf>,
+ fs: &dyn Fs,
+) -> anyhow::Result<Option<PathBuf>> {
+ for path in paths_to_check {
+ let possible_package_json = path.join("package.json");
+ if let Some(package_json_metadata) = fs
+ .metadata(&possible_package_json)
+ .await
+ .with_context(|| format!("Fetching metadata for {possible_package_json:?}"))?
+ {
+ if !package_json_metadata.is_dir && !package_json_metadata.is_symlink {
+ let package_json_contents = fs
+ .load(&possible_package_json)
+ .await
+ .with_context(|| format!("reading {possible_package_json:?} file contents"))?;
+ if let Ok(json_contents) = serde_json::from_str::<HashMap<String, serde_json::Value>>(
+ &package_json_contents,
+ ) {
+ if let Some(serde_json::Value::Object(o)) = json_contents.get("dependencies") {
+ if o.contains_key(PRETTIER_PACKAGE_NAME) {
+ return Ok(Some(path));
+ }
+ }
+ if let Some(serde_json::Value::Object(o)) = json_contents.get("devDependencies")
+ {
+ if o.contains_key(PRETTIER_PACKAGE_NAME) {
+ return Ok(Some(path));
+ }
+ }
+ }
+ }
+ }
+
+ let possible_node_modules_location = path.join("node_modules").join(PRETTIER_PACKAGE_NAME);
+ if let Some(node_modules_location_metadata) = fs
+ .metadata(&possible_node_modules_location)
+ .await
+ .with_context(|| format!("fetching metadata for {possible_node_modules_location:?}"))?
+ {
+ if node_modules_location_metadata.is_dir {
+ return Ok(Some(path));
+ }
+ }
+ }
+ Ok(None)
+}
+
+enum Format {}
+
+#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+struct FormatParams {
+ text: String,
+ options: FormatOptions,
+}
+
+#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+struct FormatOptions {
+ plugins: Vec<PathBuf>,
+ parser: Option<String>,
+ #[serde(rename = "filepath")]
+ path: Option<PathBuf>,
+ prettier_options: Option<HashMap<String, serde_json::Value>>,
+}
+
+#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+struct FormatResult {
+ text: String,
+}
+
+impl lsp2::request::Request for Format {
+ type Params = FormatParams;
+ type Result = FormatResult;
+ const METHOD: &'static str = "prettier/format";
+}
+
+enum ClearCache {}
+
+impl lsp2::request::Request for ClearCache {
+ type Params = ();
+ type Result = ();
+ const METHOD: &'static str = "prettier/clear_cache";
+}
@@ -0,0 +1,217 @@
+const { Buffer } = require('buffer');
+const fs = require("fs");
+const path = require("path");
+const { once } = require('events');
+
+const prettierContainerPath = process.argv[2];
+if (prettierContainerPath == null || prettierContainerPath.length == 0) {
+ process.stderr.write(`Prettier path argument was not specified or empty.\nUsage: ${process.argv[0]} ${process.argv[1]} prettier/path\n`);
+ process.exit(1);
+}
+fs.stat(prettierContainerPath, (err, stats) => {
+ if (err) {
+ process.stderr.write(`Path '${prettierContainerPath}' does not exist\n`);
+ process.exit(1);
+ }
+
+ if (!stats.isDirectory()) {
+ process.stderr.write(`Path '${prettierContainerPath}' exists but is not a directory\n`);
+ process.exit(1);
+ }
+});
+const prettierPath = path.join(prettierContainerPath, 'node_modules/prettier');
+
+class Prettier {
+ constructor(path, prettier, config) {
+ this.path = path;
+ this.prettier = prettier;
+ this.config = config;
+ }
+}
+
+(async () => {
+ let prettier;
+ let config;
+ try {
+ prettier = await loadPrettier(prettierPath);
+ config = await prettier.resolveConfig(prettierPath) || {};
+ } catch (e) {
+ process.stderr.write(`Failed to load prettier: ${e}\n`);
+ process.exit(1);
+ }
+ process.stderr.write(`Prettier at path '${prettierPath}' loaded successfully, config: ${JSON.stringify(config)}\n`);
+ process.stdin.resume();
+ handleBuffer(new Prettier(prettierPath, prettier, config));
+})()
+
+async function handleBuffer(prettier) {
+ for await (const messageText of readStdin()) {
+ let message;
+ try {
+ message = JSON.parse(messageText);
+ } catch (e) {
+ sendResponse(makeError(`Failed to parse message '${messageText}': ${e}`));
+ continue;
+ }
+ // allow concurrent request handling by not `await`ing the message handling promise (async function)
+ handleMessage(message, prettier).catch(e => {
+ sendResponse({ id: message.id, ...makeError(`error during message handling: ${e}`) });
+ });
+ }
+}
+
+const headerSeparator = "\r\n";
+const contentLengthHeaderName = 'Content-Length';
+
+async function* readStdin() {
+ let buffer = Buffer.alloc(0);
+ let streamEnded = false;
+ process.stdin.on('end', () => {
+ streamEnded = true;
+ });
+ process.stdin.on('data', (data) => {
+ buffer = Buffer.concat([buffer, data]);
+ });
+
+ async function handleStreamEnded(errorMessage) {
+ sendResponse(makeError(errorMessage));
+ buffer = Buffer.alloc(0);
+ messageLength = null;
+ await once(process.stdin, 'readable');
+ streamEnded = false;
+ }
+
+ try {
+ let headersLength = null;
+ let messageLength = null;
+ main_loop: while (true) {
+ if (messageLength === null) {
+ while (buffer.indexOf(`${headerSeparator}${headerSeparator}`) === -1) {
+ if (streamEnded) {
+ await handleStreamEnded('Unexpected end of stream: headers not found');
+ continue main_loop;
+ } else if (buffer.length > contentLengthHeaderName.length * 10) {
+ await handleStreamEnded(`Unexpected stream of bytes: no headers end found after ${buffer.length} bytes of input`);
+ continue main_loop;
+ }
+ await once(process.stdin, 'readable');
+ }
+ const headers = buffer.subarray(0, buffer.indexOf(`${headerSeparator}${headerSeparator}`)).toString('ascii');
+ const contentLengthHeader = headers.split(headerSeparator)
+ .map(header => header.split(':'))
+ .filter(header => header[2] === undefined)
+ .filter(header => (header[1] || '').length > 0)
+ .find(header => (header[0] || '').trim() === contentLengthHeaderName);
+ const contentLength = (contentLengthHeader || [])[1];
+ if (contentLength === undefined) {
+ await handleStreamEnded(`Missing or incorrect ${contentLengthHeaderName} header: ${headers}`);
+ continue main_loop;
+ }
+ headersLength = headers.length + headerSeparator.length * 2;
+ messageLength = parseInt(contentLength, 10);
+ }
+
+ while (buffer.length < (headersLength + messageLength)) {
+ if (streamEnded) {
+ await handleStreamEnded(
+ `Unexpected end of stream: buffer length ${buffer.length} does not match expected header length ${headersLength} + body length ${messageLength}`);
+ continue main_loop;
+ }
+ await once(process.stdin, 'readable');
+ }
+
+ const messageEnd = headersLength + messageLength;
+ const message = buffer.subarray(headersLength, messageEnd);
+ buffer = buffer.subarray(messageEnd);
+ headersLength = null;
+ messageLength = null;
+ yield message.toString('utf8');
+ }
+ } catch (e) {
+ sendResponse(makeError(`Error reading stdin: ${e}`));
+ } finally {
+ process.stdin.off('data', () => { });
+ }
+}
+
+async function handleMessage(message, prettier) {
+ const { method, id, params } = message;
+ if (method === undefined) {
+ throw new Error(`Message method is undefined: ${JSON.stringify(message)}`);
+ }
+ if (id === undefined) {
+ throw new Error(`Message id is undefined: ${JSON.stringify(message)}`);
+ }
+
+ if (method === 'prettier/format') {
+ if (params === undefined || params.text === undefined) {
+ throw new Error(`Message params.text is undefined: ${JSON.stringify(message)}`);
+ }
+ if (params.options === undefined) {
+ throw new Error(`Message params.options is undefined: ${JSON.stringify(message)}`);
+ }
+
+ let resolvedConfig = {};
+ if (params.options.filepath !== undefined) {
+ resolvedConfig = await prettier.prettier.resolveConfig(params.options.filepath) || {};
+ }
+
+ const options = {
+ ...(params.options.prettierOptions || prettier.config),
+ ...resolvedConfig,
+ parser: params.options.parser,
+ plugins: params.options.plugins,
+ path: params.options.filepath
+ };
+ process.stderr.write(`Resolved config: ${JSON.stringify(resolvedConfig)}, will format file '${params.options.filepath || ''}' with options: ${JSON.stringify(options)}\n`);
+ const formattedText = await prettier.prettier.format(params.text, options);
+ sendResponse({ id, result: { text: formattedText } });
+ } else if (method === 'prettier/clear_cache') {
+ prettier.prettier.clearConfigCache();
+ prettier.config = await prettier.prettier.resolveConfig(prettier.path) || {};
+ sendResponse({ id, result: null });
+ } else if (method === 'initialize') {
+ sendResponse({
+ id,
+ result: {
+ "capabilities": {}
+ }
+ });
+ } else {
+ throw new Error(`Unknown method: ${method}`);
+ }
+}
+
+function makeError(message) {
+ return {
+ error: {
+ "code": -32600, // invalid request code
+ message,
+ }
+ };
+}
+
+function sendResponse(response) {
+ const responsePayloadString = JSON.stringify({
+ jsonrpc: "2.0",
+ ...response
+ });
+ const headers = `${contentLengthHeaderName}: ${Buffer.byteLength(responsePayloadString)}${headerSeparator}${headerSeparator}`;
+ process.stdout.write(headers + responsePayloadString);
+}
+
+function loadPrettier(prettierPath) {
+ return new Promise((resolve, reject) => {
+ fs.access(prettierPath, fs.constants.F_OK, (err) => {
+ if (err) {
+ reject(`Path '${prettierPath}' does not exist.Error: ${err}`);
+ } else {
+ try {
+ resolve(require(prettierPath));
+ } catch (err) {
+ reject(`Error requiring prettier module from path '${prettierPath}'.Error: ${err}`);
+ }
+ }
+ });
+ });
+}
@@ -196,7 +196,7 @@ impl DelayedDebounced {
self.cancel_channel = Some(sender);
let previous_task = self.task.take();
- self.task = Some(cx.executor().spawn(|workspace, mut cx| async move {
+ self.task = Some(cx.spawn(|project, mut cx| async move {
let mut timer = cx.executor().timer(delay).fuse();
if let Some(previous_task) = previous_task {
previous_task.await;
@@ -207,7 +207,7 @@ impl DelayedDebounced {
_ = timer => {}
}
- if let Ok(task) = workspace.update(&mut cx, |workspace, cx| (func)(workspace, cx)) {
+ if let Ok(task) = project.update(&mut cx, |project, cx| (func)(project, cx)) {
task.await;
}
}));
@@ -8113,7 +8113,7 @@ impl Project {
if let Some(buffer) = buffer {
buffer.update(cx, |buffer, cx| {
buffer.did_reload(version, fingerprint, line_ending, mtime, cx);
- })?;
+ });
}
Ok(())
})?
@@ -1,130 +1,131 @@
-use alacritty_terminal::{ansi::Color as AnsiColor, term::color::Rgb as AlacRgb};
-use gpui2::color::Color;
-use theme2::TerminalStyle;
+// todo!()
+// use alacritty_terminal::{ansi::Color as AnsiColor, term::color::Rgb as AlacRgb};
+// use gpui2::color::Color;
+// use theme2::TerminalStyle;
-///Converts a 2, 8, or 24 bit color ANSI color to the GPUI equivalent
-pub fn convert_color(alac_color: &AnsiColor, style: &TerminalStyle) -> Color {
- match alac_color {
- //Named and theme defined colors
- alacritty_terminal::ansi::Color::Named(n) => match n {
- alacritty_terminal::ansi::NamedColor::Black => style.black,
- alacritty_terminal::ansi::NamedColor::Red => style.red,
- alacritty_terminal::ansi::NamedColor::Green => style.green,
- alacritty_terminal::ansi::NamedColor::Yellow => style.yellow,
- alacritty_terminal::ansi::NamedColor::Blue => style.blue,
- alacritty_terminal::ansi::NamedColor::Magenta => style.magenta,
- alacritty_terminal::ansi::NamedColor::Cyan => style.cyan,
- alacritty_terminal::ansi::NamedColor::White => style.white,
- alacritty_terminal::ansi::NamedColor::BrightBlack => style.bright_black,
- alacritty_terminal::ansi::NamedColor::BrightRed => style.bright_red,
- alacritty_terminal::ansi::NamedColor::BrightGreen => style.bright_green,
- alacritty_terminal::ansi::NamedColor::BrightYellow => style.bright_yellow,
- alacritty_terminal::ansi::NamedColor::BrightBlue => style.bright_blue,
- alacritty_terminal::ansi::NamedColor::BrightMagenta => style.bright_magenta,
- alacritty_terminal::ansi::NamedColor::BrightCyan => style.bright_cyan,
- alacritty_terminal::ansi::NamedColor::BrightWhite => style.bright_white,
- alacritty_terminal::ansi::NamedColor::Foreground => style.foreground,
- alacritty_terminal::ansi::NamedColor::Background => style.background,
- alacritty_terminal::ansi::NamedColor::Cursor => style.cursor,
- alacritty_terminal::ansi::NamedColor::DimBlack => style.dim_black,
- alacritty_terminal::ansi::NamedColor::DimRed => style.dim_red,
- alacritty_terminal::ansi::NamedColor::DimGreen => style.dim_green,
- alacritty_terminal::ansi::NamedColor::DimYellow => style.dim_yellow,
- alacritty_terminal::ansi::NamedColor::DimBlue => style.dim_blue,
- alacritty_terminal::ansi::NamedColor::DimMagenta => style.dim_magenta,
- alacritty_terminal::ansi::NamedColor::DimCyan => style.dim_cyan,
- alacritty_terminal::ansi::NamedColor::DimWhite => style.dim_white,
- alacritty_terminal::ansi::NamedColor::BrightForeground => style.bright_foreground,
- alacritty_terminal::ansi::NamedColor::DimForeground => style.dim_foreground,
- },
- //'True' colors
- alacritty_terminal::ansi::Color::Spec(rgb) => Color::new(rgb.r, rgb.g, rgb.b, u8::MAX),
- //8 bit, indexed colors
- alacritty_terminal::ansi::Color::Indexed(i) => get_color_at_index(&(*i as usize), style),
- }
-}
+// ///Converts a 2, 8, or 24 bit color ANSI color to the GPUI equivalent
+// pub fn convert_color(alac_color: &AnsiColor, style: &TerminalStyle) -> Color {
+// match alac_color {
+// //Named and theme defined colors
+// alacritty_terminal::ansi::Color::Named(n) => match n {
+// alacritty_terminal::ansi::NamedColor::Black => style.black,
+// alacritty_terminal::ansi::NamedColor::Red => style.red,
+// alacritty_terminal::ansi::NamedColor::Green => style.green,
+// alacritty_terminal::ansi::NamedColor::Yellow => style.yellow,
+// alacritty_terminal::ansi::NamedColor::Blue => style.blue,
+// alacritty_terminal::ansi::NamedColor::Magenta => style.magenta,
+// alacritty_terminal::ansi::NamedColor::Cyan => style.cyan,
+// alacritty_terminal::ansi::NamedColor::White => style.white,
+// alacritty_terminal::ansi::NamedColor::BrightBlack => style.bright_black,
+// alacritty_terminal::ansi::NamedColor::BrightRed => style.bright_red,
+// alacritty_terminal::ansi::NamedColor::BrightGreen => style.bright_green,
+// alacritty_terminal::ansi::NamedColor::BrightYellow => style.bright_yellow,
+// alacritty_terminal::ansi::NamedColor::BrightBlue => style.bright_blue,
+// alacritty_terminal::ansi::NamedColor::BrightMagenta => style.bright_magenta,
+// alacritty_terminal::ansi::NamedColor::BrightCyan => style.bright_cyan,
+// alacritty_terminal::ansi::NamedColor::BrightWhite => style.bright_white,
+// alacritty_terminal::ansi::NamedColor::Foreground => style.foreground,
+// alacritty_terminal::ansi::NamedColor::Background => style.background,
+// alacritty_terminal::ansi::NamedColor::Cursor => style.cursor,
+// alacritty_terminal::ansi::NamedColor::DimBlack => style.dim_black,
+// alacritty_terminal::ansi::NamedColor::DimRed => style.dim_red,
+// alacritty_terminal::ansi::NamedColor::DimGreen => style.dim_green,
+// alacritty_terminal::ansi::NamedColor::DimYellow => style.dim_yellow,
+// alacritty_terminal::ansi::NamedColor::DimBlue => style.dim_blue,
+// alacritty_terminal::ansi::NamedColor::DimMagenta => style.dim_magenta,
+// alacritty_terminal::ansi::NamedColor::DimCyan => style.dim_cyan,
+// alacritty_terminal::ansi::NamedColor::DimWhite => style.dim_white,
+// alacritty_terminal::ansi::NamedColor::BrightForeground => style.bright_foreground,
+// alacritty_terminal::ansi::NamedColor::DimForeground => style.dim_foreground,
+// },
+// //'True' colors
+// alacritty_terminal::ansi::Color::Spec(rgb) => Color::new(rgb.r, rgb.g, rgb.b, u8::MAX),
+// //8 bit, indexed colors
+// alacritty_terminal::ansi::Color::Indexed(i) => get_color_at_index(&(*i as usize), style),
+// }
+// }
-///Converts an 8 bit ANSI color to it's GPUI equivalent.
-///Accepts usize for compatibility with the alacritty::Colors interface,
-///Other than that use case, should only be called with values in the [0,255] range
-pub fn get_color_at_index(index: &usize, style: &TerminalStyle) -> Color {
- match index {
- //0-15 are the same as the named colors above
- 0 => style.black,
- 1 => style.red,
- 2 => style.green,
- 3 => style.yellow,
- 4 => style.blue,
- 5 => style.magenta,
- 6 => style.cyan,
- 7 => style.white,
- 8 => style.bright_black,
- 9 => style.bright_red,
- 10 => style.bright_green,
- 11 => style.bright_yellow,
- 12 => style.bright_blue,
- 13 => style.bright_magenta,
- 14 => style.bright_cyan,
- 15 => style.bright_white,
- //16-231 are mapped to their RGB colors on a 0-5 range per channel
- 16..=231 => {
- let (r, g, b) = rgb_for_index(&(*index as u8)); //Split the index into it's ANSI-RGB components
- let step = (u8::MAX as f32 / 5.).floor() as u8; //Split the RGB range into 5 chunks, with floor so no overflow
- Color::new(r * step, g * step, b * step, u8::MAX) //Map the ANSI-RGB components to an RGB color
- }
- //232-255 are a 24 step grayscale from black to white
- 232..=255 => {
- let i = *index as u8 - 232; //Align index to 0..24
- let step = (u8::MAX as f32 / 24.).floor() as u8; //Split the RGB grayscale values into 24 chunks
- Color::new(i * step, i * step, i * step, u8::MAX) //Map the ANSI-grayscale components to the RGB-grayscale
- }
- //For compatibility with the alacritty::Colors interface
- 256 => style.foreground,
- 257 => style.background,
- 258 => style.cursor,
- 259 => style.dim_black,
- 260 => style.dim_red,
- 261 => style.dim_green,
- 262 => style.dim_yellow,
- 263 => style.dim_blue,
- 264 => style.dim_magenta,
- 265 => style.dim_cyan,
- 266 => style.dim_white,
- 267 => style.bright_foreground,
- 268 => style.black, //'Dim Background', non-standard color
- _ => Color::new(0, 0, 0, 255),
- }
-}
-///Generates the rgb channels in [0, 5] for a given index into the 6x6x6 ANSI color cube
-///See: [8 bit ansi color](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit).
-///
-///Wikipedia gives a formula for calculating the index for a given color:
-///
-///index = 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
-///
-///This function does the reverse, calculating the r, g, and b components from a given index.
-fn rgb_for_index(i: &u8) -> (u8, u8, u8) {
- debug_assert!((&16..=&231).contains(&i));
- let i = i - 16;
- let r = (i - (i % 36)) / 36;
- let g = ((i % 36) - (i % 6)) / 6;
- let b = (i % 36) % 6;
- (r, g, b)
-}
+// ///Converts an 8 bit ANSI color to it's GPUI equivalent.
+// ///Accepts usize for compatibility with the alacritty::Colors interface,
+// ///Other than that use case, should only be called with values in the [0,255] range
+// pub fn get_color_at_index(index: &usize, style: &TerminalStyle) -> Color {
+// match index {
+// //0-15 are the same as the named colors above
+// 0 => style.black,
+// 1 => style.red,
+// 2 => style.green,
+// 3 => style.yellow,
+// 4 => style.blue,
+// 5 => style.magenta,
+// 6 => style.cyan,
+// 7 => style.white,
+// 8 => style.bright_black,
+// 9 => style.bright_red,
+// 10 => style.bright_green,
+// 11 => style.bright_yellow,
+// 12 => style.bright_blue,
+// 13 => style.bright_magenta,
+// 14 => style.bright_cyan,
+// 15 => style.bright_white,
+// //16-231 are mapped to their RGB colors on a 0-5 range per channel
+// 16..=231 => {
+// let (r, g, b) = rgb_for_index(&(*index as u8)); //Split the index into it's ANSI-RGB components
+// let step = (u8::MAX as f32 / 5.).floor() as u8; //Split the RGB range into 5 chunks, with floor so no overflow
+// Color::new(r * step, g * step, b * step, u8::MAX) //Map the ANSI-RGB components to an RGB color
+// }
+// //232-255 are a 24 step grayscale from black to white
+// 232..=255 => {
+// let i = *index as u8 - 232; //Align index to 0..24
+// let step = (u8::MAX as f32 / 24.).floor() as u8; //Split the RGB grayscale values into 24 chunks
+// Color::new(i * step, i * step, i * step, u8::MAX) //Map the ANSI-grayscale components to the RGB-grayscale
+// }
+// //For compatibility with the alacritty::Colors interface
+// 256 => style.foreground,
+// 257 => style.background,
+// 258 => style.cursor,
+// 259 => style.dim_black,
+// 260 => style.dim_red,
+// 261 => style.dim_green,
+// 262 => style.dim_yellow,
+// 263 => style.dim_blue,
+// 264 => style.dim_magenta,
+// 265 => style.dim_cyan,
+// 266 => style.dim_white,
+// 267 => style.bright_foreground,
+// 268 => style.black, //'Dim Background', non-standard color
+// _ => Color::new(0, 0, 0, 255),
+// }
+// }
+// ///Generates the rgb channels in [0, 5] for a given index into the 6x6x6 ANSI color cube
+// ///See: [8 bit ansi color](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit).
+// ///
+// ///Wikipedia gives a formula for calculating the index for a given color:
+// ///
+// ///index = 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
+// ///
+// ///This function does the reverse, calculating the r, g, and b components from a given index.
+// fn rgb_for_index(i: &u8) -> (u8, u8, u8) {
+// debug_assert!((&16..=&231).contains(&i));
+// let i = i - 16;
+// let r = (i - (i % 36)) / 36;
+// let g = ((i % 36) - (i % 6)) / 6;
+// let b = (i % 36) % 6;
+// (r, g, b)
+// }
-//Convenience method to convert from a GPUI color to an alacritty Rgb
-pub fn to_alac_rgb(color: Color) -> AlacRgb {
- AlacRgb::new(color.r, color.g, color.g)
-}
+// //Convenience method to convert from a GPUI color to an alacritty Rgb
+// pub fn to_alac_rgb(color: Color) -> AlacRgb {
+// AlacRgb::new(color.r, color.g, color.g)
+// }
-#[cfg(test)]
-mod tests {
- #[test]
- fn test_rgb_for_index() {
- //Test every possible value in the color cube
- for i in 16..=231 {
- let (r, g, b) = crate::mappings::colors::rgb_for_index(&(i as u8));
- assert_eq!(i, 16 + 36 * r + 6 * g + b);
- }
- }
-}
+// #[cfg(test)]
+// mod tests {
+// #[test]
+// fn test_rgb_for_index() {
+// //Test every possible value in the color cube
+// for i in 16..=231 {
+// let (r, g, b) = crate::mappings::colors::rgb_for_index(&(i as u8));
+// assert_eq!(i, 16 + 36 * r + 6 * g + b);
+// }
+// }
+// }