WIP

Antonio Scandurra created

Change summary

Cargo.lock                              |  20 +
Cargo.toml                              |   1 
crates/gpui2/src/app.rs                 |  50 +-
crates/gpui2/src/gpui2.rs               |  19 
crates/gpui2/src/window.rs              |  94 +++-
crates/prettier2/Cargo.toml             |  34 +
crates/prettier2/src/prettier2.rs       | 513 +++++++++++++++++++++++++++
crates/prettier2/src/prettier_server.js | 217 +++++++++++
crates/project2/src/project2.rs         |   6 
crates/terminal2/src/mappings/colors.rs | 253 ++++++------
10 files changed, 1,015 insertions(+), 192 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -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"

Cargo.toml 🔗

@@ -61,6 +61,7 @@ members = [
     "crates/plugin_macros",
     "crates/plugin_runtime",
     "crates/prettier",
+    "crates/prettier2",
     "crates/project",
     "crates/project2",
     "crates/project_panel",

crates/gpui2/src/app.rs 🔗

@@ -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,

crates/gpui2/src/gpui2.rs 🔗

@@ -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)
     }
 }
 

crates/gpui2/src/window.rs 🔗

@@ -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
     }
 }

crates/prettier2/Cargo.toml 🔗

@@ -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"] }

crates/prettier2/src/prettier2.rs 🔗

@@ -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";
+}

crates/prettier2/src/prettier_server.js 🔗

@@ -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}`);
+                }
+            }
+        });
+    });
+}

crates/project2/src/project2.rs 🔗

@@ -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(())
         })?

crates/terminal2/src/mappings/colors.rs 🔗

@@ -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);
+//         }
+//     }
+// }