treesitter revamp :)

This commit is contained in:
Borodinov Ilya 2024-05-15 22:14:17 +03:00
parent 4382205e84
commit 638a9a112b
Signed by: noth
GPG key ID: 75503B2EF596D1BD
14 changed files with 467 additions and 207 deletions

226
Cargo.lock generated
View file

@ -306,27 +306,12 @@ dependencies = [
"rustc-demangle", "rustc-demangle",
] ]
[[package]]
name = "base64"
version = "0.21.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
[[package]] [[package]]
name = "base64" name = "base64"
version = "0.22.1" version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "bit-set" name = "bit-set"
version = "0.5.3" version = "0.5.3"
@ -432,6 +417,15 @@ dependencies = [
"piper", "piper",
] ]
[[package]]
name = "brownstone"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5839ee4f953e811bfdcf223f509cb2c6a3e1447959b0bff459405575bc17f22"
dependencies = [
"arrayvec",
]
[[package]] [[package]]
name = "bstr" name = "bstr"
version = "1.9.1" version = "1.9.1"
@ -1641,6 +1635,12 @@ version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "029d73f573d8e8d63e6d5020011d3255b28c3ba85d6cf870a07184ed23de9284" checksum = "029d73f573d8e8d63e6d5020011d3255b28c3ba85d6cf870a07184ed23de9284"
[[package]]
name = "indent_write"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0cfe9645a18782869361d9c8732246be7b410ad4e919d3609ebabdac00ba12c3"
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.2.6" version = "2.2.6"
@ -1740,6 +1740,12 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "joinery"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72167d68f5fce3b8655487b8038691a3c9984ee769590f93f2a631f4ad64e4f5"
[[package]] [[package]]
name = "jpeg-decoder" name = "jpeg-decoder"
version = "0.1.22" version = "0.1.22"
@ -1758,6 +1764,34 @@ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
[[package]]
name = "kaydle"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b2de193d14f7d6f3288f5ee1c38b0d7869e95c322fc5e54d1c385765172db53"
dependencies = [
"kaydle-primitives",
"lazy_format",
"nom",
"nom-supreme",
"serde",
"serde-mobile",
"thiserror",
]
[[package]]
name = "kaydle-primitives"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f31f657f34304c4853f1e3a3f3c9a556d0462d7004460791728713d61d88272"
dependencies = [
"arrayvec",
"memchr",
"nom",
"nom-supreme",
"serde",
]
[[package]] [[package]]
name = "khronos-egl" name = "khronos-egl"
version = "5.0.0" version = "5.0.0"
@ -1784,6 +1818,12 @@ version = "5.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10257499f089cd156ad82d0a9cd57d9501fa2c989068992a97eb3c27836f206b" checksum = "10257499f089cd156ad82d0a9cd57d9501fa2c989068992a97eb3c27836f206b"
[[package]]
name = "lazy_format"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b05662be9cd63006934464f935195ae936460edb75de7b9a07e0509795afbdc3"
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.4.0" version = "1.4.0"
@ -1849,18 +1889,6 @@ dependencies = [
"vcpkg", "vcpkg",
] ]
[[package]]
name = "line-wrap"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd1bc4d24ad230d21fb898d1116b1801d7adfc449d42026475862ab48b11e70e"
[[package]]
name = "linked-hash-map"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]] [[package]]
name = "linkme" name = "linkme"
version = "0.3.26" version = "0.3.26"
@ -2052,6 +2080,12 @@ dependencies = [
"syn 2.0.63", "syn 2.0.63",
] ]
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.3.7" version = "0.3.7"
@ -2133,9 +2167,12 @@ version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"funnylog", "funnylog",
"kaydle",
"log", "log",
"ming", "ming",
"syntect", "serde",
"tree-sitter-highlight",
"tree-sitter-rust",
"widestring", "widestring",
] ]
@ -2152,6 +2189,29 @@ dependencies = [
"memoffset", "memoffset",
] ]
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "nom-supreme"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bd3ae6c901f1959588759ff51c95d24b491ecb9ff91aa9c2ef4acc5b1dcab27"
dependencies = [
"brownstone",
"indent_write",
"joinery",
"memchr",
"nom",
]
[[package]] [[package]]
name = "num" name = "num"
version = "0.4.3" version = "0.4.3"
@ -2324,28 +2384,6 @@ version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "onig"
version = "6.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c4b31c8722ad9171c6d77d3557db078cab2bd50afcc9d09c8b315c59df8ca4f"
dependencies = [
"bitflags 1.3.2",
"libc",
"once_cell",
"onig_sys",
]
[[package]]
name = "onig_sys"
version = "69.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b829e3d7e9cc74c7e315ee8edb185bf4190da5acde74afd7fc59c35b1f086e7"
dependencies = [
"cc",
"pkg-config",
]
[[package]] [[package]]
name = "oo7" name = "oo7"
version = "0.3.2" version = "0.3.2"
@ -2554,20 +2592,6 @@ version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
[[package]]
name = "plist"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9d34169e64b3c7a80c8621a48adaf44e0cf62c78a9b25dd9dd35f1881a17cf9"
dependencies = [
"base64 0.21.7",
"indexmap",
"line-wrap",
"quick-xml",
"serde",
"time",
]
[[package]] [[package]]
name = "png" name = "png"
version = "0.16.8" version = "0.16.8"
@ -3062,6 +3086,15 @@ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]]
name = "serde-mobile"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c32e12ac49f4f1fde3b44b9eccfcc6cb70bbb2622dac40698b34c3d607cf21a4"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.201" version = "1.0.201"
@ -3352,28 +3385,6 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "syntect"
version = "5.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "874dcfa363995604333cf947ae9f751ca3af4522c60886774c4963943b4746b1"
dependencies = [
"bincode",
"bitflags 1.3.2",
"flate2",
"fnv",
"once_cell",
"onig",
"plist",
"regex-syntax",
"serde",
"serde_derive",
"serde_json",
"thiserror",
"walkdir",
"yaml-rust",
]
[[package]] [[package]]
name = "sys-locale" name = "sys-locale"
version = "0.3.1" version = "0.3.1"
@ -3640,6 +3651,38 @@ dependencies = [
"tracing", "tracing",
] ]
[[package]]
name = "tree-sitter"
version = "0.22.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df7cc499ceadd4dcdf7ec6d4cbc34ece92c3fa07821e287aedecd4416c516dca"
dependencies = [
"cc",
"regex",
]
[[package]]
name = "tree-sitter-highlight"
version = "0.22.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eaca0fe34fa96eec6aaa8e63308dbe1bafe65a6317487c287f93938959b21907"
dependencies = [
"lazy_static",
"regex",
"thiserror",
"tree-sitter",
]
[[package]]
name = "tree-sitter-rust"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "277690f420bf90741dea984f3da038ace46c4fe6047cba57a66822226cde1c93"
dependencies = [
"cc",
"tree-sitter",
]
[[package]] [[package]]
name = "ttf-parser" name = "ttf-parser"
version = "0.20.0" version = "0.20.0"
@ -3759,7 +3802,7 @@ version = "0.41.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c704361d822337cfc00387672c7b59eaa72a1f0744f62b2a68aa228a0c6927d" checksum = "5c704361d822337cfc00387672c7b59eaa72a1f0744f62b2a68aa228a0c6927d"
dependencies = [ dependencies = [
"base64 0.22.1", "base64",
"data-url", "data-url",
"flate2", "flate2",
"imagesize", "imagesize",
@ -4285,15 +4328,6 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9" checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9"
[[package]]
name = "yaml-rust"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
dependencies = [
"linked-hash-map",
]
[[package]] [[package]]
name = "yazi" name = "yazi"
version = "0.1.6" version = "0.1.6"

View file

@ -8,8 +8,11 @@ funnylog.workspace = true
ming.workspace = true ming.workspace = true
anyhow.workspace = true anyhow.workspace = true
widestring = "1.1.0" widestring = "1.1.0"
syntect = "5.2.0"
log.workspace = true log.workspace = true
tree-sitter-highlight = "0.22.6"
tree-sitter-rust = "0.21.2"
serde = { workspace = true, features = ["derive"] }
kaydle = "0.2.0"
[workspace] [workspace]
members = [ members = [
@ -57,13 +60,7 @@ schemars = "0.8"
serde = { version = "1.0", features = ["derive", "rc"] } serde = { version = "1.0", features = ["derive", "rc"] }
serde_derive = { version = "1.0", features = ["deserialize_in_place"] } serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
serde_json = { version = "1.0", features = ["preserve_order", "raw_value"] } serde_json = { version = "1.0", features = ["preserve_order", "raw_value"] }
serde_json_lenient = { version = "0.1", features = [
"preserve_order",
"raw_value",
] }
serde_repr = "0.1"
smallvec = { version = "1.6", features = ["union"] } smallvec = { version = "1.6", features = ["union"] }
sha2 = "0.10"
thiserror = "1" thiserror = "1"
time = { version = "0.3", features = [ time = { version = "0.3", features = [
"macros", "macros",

View file

@ -29,12 +29,12 @@ use std::any::{Any, TypeId};
/// macro, which only generates the code needed to register your action before `main`. /// macro, which only generates the code needed to register your action before `main`.
/// ///
/// ``` /// ```
/// #[derive(gpui::private::serde::Deserialize, std::cmp::PartialEq, std::clone::Clone)] /// #[derive(ming::private::serde::Deserialize, std::cmp::PartialEq, std::clone::Clone)]
/// pub struct Paste { /// pub struct Paste {
/// pub content: SharedString, /// pub content: SharedString,
/// } /// }
/// ///
/// impl gpui::Action for Paste { /// impl ming::Action for Paste {
/// ///... /// ///...
/// } /// }
/// register_action!(Paste); /// register_action!(Paste);
@ -184,18 +184,18 @@ macro_rules! actions {
$( $(
#[doc = "The `"] #[doc = "The `"]
#[doc = stringify!($name)] #[doc = stringify!($name)]
#[doc = "` action, see [`gpui::actions!`]"] #[doc = "` action, see [`ming::actions!`]"]
#[derive(::std::cmp::PartialEq, ::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug, gpui::private::serde_derive::Deserialize)] #[derive(::std::cmp::PartialEq, ::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug, ming::private::serde_derive::Deserialize)]
#[serde(crate = "gpui::private::serde")] #[serde(crate = "ming::private::serde")]
pub struct $name; pub struct $name;
gpui::__impl_action!($namespace, $name, ming::__impl_action!($namespace, $name,
fn build(_: gpui::private::serde_json::Value) -> gpui::Result<::std::boxed::Box<dyn gpui::Action>> { fn build(_: ming::private::serde_json::Value) -> ming::Result<::std::boxed::Box<dyn ming::Action>> {
Ok(Box::new(Self)) Ok(Box::new(Self))
} }
); );
gpui::register_action!($name); ming::register_action!($name);
)* )*
}; };
} }
@ -205,13 +205,13 @@ macro_rules! actions {
macro_rules! impl_actions { macro_rules! impl_actions {
($namespace:path, [ $($name:ident),* $(,)? ]) => { ($namespace:path, [ $($name:ident),* $(,)? ]) => {
$( $(
gpui::__impl_action!($namespace, $name, ming::__impl_action!($namespace, $name,
fn build(value: gpui::private::serde_json::Value) -> gpui::Result<::std::boxed::Box<dyn gpui::Action>> { fn build(value: ming::private::serde_json::Value) -> ming::Result<::std::boxed::Box<dyn ming::Action>> {
Ok(std::boxed::Box::new(gpui::private::serde_json::from_value::<Self>(value)?)) Ok(std::boxed::Box::new(ming::private::serde_json::from_value::<Self>(value)?))
} }
); );
gpui::register_action!($name); ming::register_action!($name);
)* )*
}; };
} }
@ -220,7 +220,7 @@ macro_rules! impl_actions {
#[macro_export] #[macro_export]
macro_rules! __impl_action { macro_rules! __impl_action {
($namespace:path, $name:ident, $build:item) => { ($namespace:path, $name:ident, $build:item) => {
impl gpui::Action for $name { impl ming::Action for $name {
fn name(&self) -> &'static str fn name(&self) -> &'static str
{ {
concat!( concat!(
@ -243,14 +243,14 @@ macro_rules! __impl_action {
$build $build
fn partial_eq(&self, action: &dyn gpui::Action) -> bool { fn partial_eq(&self, action: &dyn ming::Action) -> bool {
action action
.as_any() .as_any()
.downcast_ref::<Self>() .downcast_ref::<Self>()
.map_or(false, |a| self == a) .map_or(false, |a| self == a)
} }
fn boxed_clone(&self) -> std::boxed::Box<dyn gpui::Action> { fn boxed_clone(&self) -> std::boxed::Box<dyn ming::Action> {
::std::boxed::Box::new(self.clone()) ::std::boxed::Box::new(self.clone())
} }
@ -262,7 +262,7 @@ macro_rules! __impl_action {
} }
mod no_action { mod no_action {
use crate as gpui; use crate as ming;
actions!(zed, [NoAction]); actions!(zed, [NoAction]);
} }

View file

@ -78,6 +78,21 @@ impl<'de> Visitor<'de> for RgbaVisitor {
fn visit_str<E: de::Error>(self, value: &str) -> Result<Rgba, E> { fn visit_str<E: de::Error>(self, value: &str) -> Result<Rgba, E> {
Rgba::try_from(value).map_err(E::custom) Rgba::try_from(value).map_err(E::custom)
} }
fn visit_u32<E>(self, hex: u32) -> Result<Self::Value, E>
where
E: de::Error,
{
let r = ((hex >> 24) & 0xFF) as f32 / 255.0;
let g = ((hex >> 16) & 0xFF) as f32 / 255.0;
let b = ((hex >> 8) & 0xFF) as f32 / 255.0;
let mut a = (hex & 0xFF) as f32 / 255.0;
if a == 0. {
a = 1.;
}
Ok(Rgba { r, g, b, a })
}
} }
impl<'de> Deserialize<'de> for Rgba { impl<'de> Deserialize<'de> for Rgba {
@ -174,7 +189,7 @@ impl TryFrom<&'_ str> for Rgba {
} }
/// An HSLA color /// An HSLA color
#[derive(Default, Copy, Clone, Debug)] #[derive(Default, Copy, Clone, Debug, serde::Serialize)]
#[repr(C)] #[repr(C)]
pub struct Hsla { pub struct Hsla {
/// Hue, in a range from 0 to 1 /// Hue, in a range from 0 to 1

View file

@ -110,6 +110,14 @@ impl<T: Clone + Debug + Default> Point<T> {
Self { x, y } Self { x, y }
} }
/// Splats a `value` across both `x` and `y`
pub const fn all(value: T) -> Self where T: Copy {
Self {
x: value,
y: value
}
}
/// Transforms the point to a `Point<U>` by applying the given function to both coordinates. /// Transforms the point to a `Point<U>` by applying the given function to both coordinates.
/// ///
/// This method allows for converting a `Point<T>` to a `Point<U>` by specifying a closure /// This method allows for converting a `Point<T>` to a `Point<U>` by specifying a closure

View file

@ -25,6 +25,7 @@ use std::{
fmt::{Debug, Display, Formatter}, fmt::{Debug, Display, Formatter},
hash::{Hash, Hasher}, hash::{Hash, Hasher},
ops::{Deref, DerefMut, Range}, ops::{Deref, DerefMut, Range},
str::FromStr,
sync::Arc, sync::Arc,
}; };
@ -593,8 +594,75 @@ impl FontWeight {
pub const BLACK: FontWeight = FontWeight(900.0); pub const BLACK: FontWeight = FontWeight(900.0);
} }
impl FromStr for FontWeight {
type Err = ();
fn from_str(s: &str) -> std::prelude::v1::Result<Self, Self::Err> {
Ok(match s {
"thin" => Self::THIN,
"extra_light" => Self::EXTRA_LIGHT,
"light" => Self::LIGHT,
"normal" => Self::NORMAL,
"medium" => Self::MEDIUM,
"semibold" => Self::SEMIBOLD,
"bold" => Self::BOLD,
"extra_bold" => Self::EXTRA_BOLD,
"black" => Self::BLACK,
_ => return Err(()),
})
}
}
impl<'de> serde::Deserialize<'de> for FontWeight {
fn deserialize<D>(deserializer: D) -> std::prelude::v1::Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct Visitor;
impl<'de> serde::de::Visitor<'de> for Visitor {
type Value = FontWeight;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(formatter, "a font weight value (e.g. 700 or 'bold')")
}
fn visit_f32<E>(self, v: f32) -> std::prelude::v1::Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(FontWeight(v))
}
fn visit_f64<E>(self, v: f64) -> std::prelude::v1::Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(FontWeight(v as f32))
}
fn visit_i64<E>(self, v: i64) -> std::prelude::v1::Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(FontWeight(v as f32))
}
fn visit_str<E>(self, v: &str) -> std::prelude::v1::Result<Self::Value, E>
where
E: serde::de::Error,
{
v.parse()
.map_err(|()| E::custom("expected a font weight value (e.g. 'normal' or 'bold')"))
}
}
}
}
/// Allows italic or oblique faces to be selected. /// Allows italic or oblique faces to be selected.
#[derive(Clone, Copy, Eq, PartialEq, Debug, Hash, Default)] #[derive(
Clone, Copy, Eq, PartialEq, Debug, Hash, Default, serde::Serialize, serde::Deserialize,
)]
pub enum FontStyle { pub enum FontStyle {
/// A face that is neither italic not obliqued. /// A face that is neither italic not obliqued.
#[default] #[default]

View file

@ -17,7 +17,7 @@ pub(crate) fn register_action(type_name: &Ident) -> proc_macro2::TokenStream {
format_ident!("__GPUI_ACTIONS_{}", type_name.to_string().to_uppercase()); format_ident!("__GPUI_ACTIONS_{}", type_name.to_string().to_uppercase());
let action_builder_fn_name = format_ident!( let action_builder_fn_name = format_ident!(
"__gpui_actions_builder_{}", "__ming_actions_builder_{}",
type_name.to_string().to_lowercase() type_name.to_string().to_lowercase()
); );
@ -29,17 +29,17 @@ pub(crate) fn register_action(type_name: &Ident) -> proc_macro2::TokenStream {
fn __autogenerated() { fn __autogenerated() {
/// This is an auto generated function, do not use. /// This is an auto generated function, do not use.
#[doc(hidden)] #[doc(hidden)]
fn #action_builder_fn_name() -> gpui::ActionData { fn #action_builder_fn_name() -> ming::ActionData {
gpui::ActionData { ming::ActionData {
name: <#type_name as gpui::Action>::debug_name(), name: <#type_name as ming::Action>::debug_name(),
type_id: ::std::any::TypeId::of::<#type_name>(), type_id: ::std::any::TypeId::of::<#type_name>(),
build: <#type_name as gpui::Action>::build, build: <#type_name as ming::Action>::build,
} }
} }
#[doc(hidden)] #[doc(hidden)]
#[gpui::private::linkme::distributed_slice(gpui::__GPUI_ACTIONS)] #[ming::private::linkme::distributed_slice(ming::__GPUI_ACTIONS)]
#[linkme(crate = gpui::private::linkme)] #[linkme(crate = ming::private::linkme)]
static #static_slice_name: gpui::MacroActionBuilder = #action_builder_fn_name; static #static_slice_name: ming::MacroActionBuilder = #action_builder_fn_name;
} }
} }

View file

@ -68,7 +68,7 @@
scripts = { scripts = {
fmt.exec = "${config.treefmt.build.wrapper}/bin/treefmt ."; fmt.exec = "${config.treefmt.build.wrapper}/bin/treefmt .";
nite.exec = "RUST_LOG=info,nite=trace,ming=trace cargo run -- $@"; nite.exec = "RUST_LOG=error,nite=trace,ming=trace cargo run -- $@";
}; };
}; };
}; };

View file

@ -1,10 +1,5 @@
use std::{ops::Range, path::PathBuf}; use std::{ops::Range, path::PathBuf};
use syntect::{ use tree_sitter_highlight::{HighlightConfiguration, Highlighter};
highlighting::{
Color, FontStyle as SFontStyle, HighlightState, Highlighter, RangedHighlightIterator, Theme,
},
parsing::{ParseState, ScopeStack, SyntaxSet},
};
use widestring::Utf16String; use widestring::Utf16String;
use super::*; use super::*;
@ -19,7 +14,6 @@ pub struct Buffer {
impl Buffer { impl Buffer {
pub fn read(path: PathBuf) -> anyhow::Result<Self> { pub fn read(path: PathBuf) -> anyhow::Result<Self> {
let text = std::fs::read_to_string(&path)?; let text = std::fs::read_to_string(&path)?;
log::trace!("read file: {text}");
Ok(Self { Ok(Self {
text: text.into(), text: text.into(),
path: Some(path), path: Some(path),
@ -40,9 +34,8 @@ impl Buffer {
pub fn styled( pub fn styled(
&self, &self,
default_style: &TextStyle, default_style: &TextStyle,
theme: &Theme, theme: &crate::editor::Theme,
syntax_set: &SyntaxSet, syntax_set: &SyntaxSet,
scrolled: usize,
) -> Vec<StyledText> { ) -> Vec<StyledText> {
let text = self.text.to_string(); let text = self.text.to_string();
@ -51,7 +44,19 @@ impl Buffer {
.as_ref() .as_ref()
.and_then(|path| path.extension()) .and_then(|path| path.extension())
.and_then(|extension| { .and_then(|extension| {
syntax_set.find_syntax_by_extension(extension.to_str().expect("non-utf8 file ext")) Some(
match extension.to_str().expect("non-utf8 file ext") {
"rs" => HighlightConfiguration::new(
tree_sitter_rust::language(),
"rust",
tree_sitter_rust::HIGHLIGHTS_QUERY,
tree_sitter_rust::INJECTIONS_QUERY,
"",
),
_ => return None,
}
.unwrap(),
)
}) })
{ {
let mut parse = ParseState::new(syntax); let mut parse = ParseState::new(syntax);
@ -59,7 +64,6 @@ impl Buffer {
let mut hl = HighlightState::new(&hler, ScopeStack::new()); let mut hl = HighlightState::new(&hler, ScopeStack::new());
text.lines() text.lines()
.skip(scrolled)
.flat_map(|line| { .flat_map(|line| {
parse.parse_line(line, &syntax_set).map(|parsed| { parse.parse_line(line, &syntax_set).map(|parsed| {
StyledText::new(Arc::from(line)).with_highlights( StyledText::new(Arc::from(line)).with_highlights(
@ -94,7 +98,6 @@ impl Buffer {
.collect() .collect()
} else { } else {
text.lines() text.lines()
.skip(scrolled)
.map(|line| StyledText::new(Arc::from(line))) .map(|line| StyledText::new(Arc::from(line)))
.collect() .collect()
} }

View file

@ -1,6 +1,6 @@
use std::path::PathBuf; use std::{collections::HashMap, path::PathBuf};
use syntect::{highlighting::ThemeSet, parsing::SyntaxSet}; use serde::{Deserialize, Serialize};
use super::*; use super::*;
@ -8,15 +8,50 @@ mod element;
mod input; mod input;
pub struct EditorSettings { pub struct EditorSettings {
theme_set: ThemeSet, style: EditorStyle,
syntax_set: SyntaxSet, }
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct Highlight {
pub color: Option<Rgba>,
#[serde(default)]
pub style: Option<FontStyle>,
#[serde(default)]
pub weight: Option<FontWeight>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Theme {
pub name: String,
pub background_color: Rgba,
pub text_color: Rgba,
pub highlights: HashMap<String, Highlight>,
}
impl Theme {
pub fn load(text: &str) -> Result<Self, kaydle::serde::de::Error> {
kaydle::serde::from_str(text)
}
}
#[derive(Clone)]
pub struct EditorStyle {
pub font_family: SharedString,
pub font_size: AbsoluteLength,
pub theme: Arc<Theme>,
} }
impl EditorSettings { impl EditorSettings {
pub fn load_defaults() -> Self { pub fn load_defaults() -> Self {
Self { Self {
theme_set: ThemeSet::load_defaults(), style: EditorStyle {
syntax_set: SyntaxSet::load_defaults_nonewlines(), font_size: AbsoluteLength::Pixels(px(14.0)),
font_family: SharedString::from_static("ComicShannsMono Nerd Font Mono"),
theme: Arc::new(
Theme::load(include_str!("../themes/catppuccin/mocha-teal.kdl"))
.expect("mocha theme failed to parse (how?)"),
),
},
} }
} }
} }
@ -25,12 +60,15 @@ pub struct Editor {
focus_handle: FocusHandle, focus_handle: FocusHandle,
buf: Model<crate::buffer::Buffer>, buf: Model<crate::buffer::Buffer>,
settings: Model<EditorSettings>, settings: Model<EditorSettings>,
cursor: Point<usize>,
logger: Logger,
} }
impl Editor { impl Editor {
pub fn make<V: 'static>( pub fn make<V: 'static>(
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
settings: Model<EditorSettings>, settings: Model<EditorSettings>,
logger: Logger,
) -> View<Self> { ) -> View<Self> {
cx.new_view(|cx| Self { cx.new_view(|cx| Self {
buf: cx.new_model(|_cx| { buf: cx.new_model(|_cx| {
@ -42,27 +80,38 @@ impl Editor {
}), }),
focus_handle: cx.focus_handle(), focus_handle: cx.focus_handle(),
settings, settings,
logger,
cursor: Point::default(),
}) })
} }
} }
impl Render for Editor { impl Render for Editor {
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement { fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
element::EditorElement::new( cx.focus(&self.focus_handle);
cx.view(),
element::EditorStyle { div()
font_size: AbsoluteLength::Pixels(px(14.0)), .key_context("Editor")
font_family: SharedString::from_static("ComicShannsMono Nerd Font Mono"), .on_action(cx.listener(|me, event: &action::CursorDown, cx| {
hl_theme: self me.cursor.y = me.cursor.y.saturating_add(1).min(
.settings me.buf
.read(cx) .read(cx)
.theme_set .text
.themes .chars()
.get("base16-mocha.dark") .filter(|char| *char == '\n')
.expect("mocha.dark wasn't available even if it's told it's there") .count(),
.clone(), );
}, funnylog::trace!(me.logger, ?me.cursor, "down");
) }))
.on_action(cx.listener(|me, event: &action::CursorUp, cx| {
me.cursor.y = me.cursor.y.saturating_sub(1);
funnylog::trace!(me.logger, ?me.cursor, "up");
}))
.child(element::EditorElement::new(
cx.view(),
self.settings.read(cx).style.clone(),
self.cursor,
))
} }
} }
@ -71,3 +120,9 @@ impl FocusableView for Editor {
self.focus_handle.clone() self.focus_handle.clone()
} }
} }
pub mod action {
use ming::actions;
actions!(nite, [CursorDown, CursorUp]);
}

View file

@ -1,29 +1,20 @@
use std::{cell::Cell, rc::Rc}; use crate::buffer::hsla_from_syntect;
use syntect::highlighting::Theme;
use self::buffer::hsla_from_syntect;
use super::*; use super::*;
pub struct EditorStyle {
pub font_family: SharedString,
pub font_size: AbsoluteLength,
pub hl_theme: Theme,
}
pub struct EditorElement { pub struct EditorElement {
editor: View<Editor>, editor: View<Editor>,
style: EditorStyle, style: EditorStyle,
scrolled: Rc<Cell<usize>>, cursor: Point<usize>,
} }
impl EditorElement { impl EditorElement {
pub fn new(viewref: &View<Editor>, style: EditorStyle) -> Self { pub fn new(viewref: &View<Editor>, style: EditorStyle, cursor: Point<usize>) -> Self {
Self { Self {
editor: viewref.clone(), editor: viewref.clone(),
style, style,
scrolled: Rc::new(Cell::new(0)), cursor,
} }
} }
} }
@ -61,9 +52,7 @@ impl Element for EditorElement {
font_family: self.style.font_family.clone(), font_family: self.style.font_family.clone(),
..Default::default() ..Default::default()
}, },
&self.style.hl_theme, &self.style.theme,
&editor.settings.read(cx).syntax_set,
self.scrolled.get(),
); );
let children = styled let children = styled
@ -77,6 +66,14 @@ impl Element for EditorElement {
display: Display::Flex, display: Display::Flex,
flex_direction: FlexDirection::Column, flex_direction: FlexDirection::Column,
align_content: Some(AlignContent::FlexStart), align_content: Some(AlignContent::FlexStart),
overflow: Point::all(Overflow::Scroll),
size: Size::full(),
background: self
.style
.theme
.settings
.background
.map(|bg| Fill::Color(hsla_from_syntect(bg))),
..Default::default() ..Default::default()
}, },
children.iter().copied(), children.iter().copied(),
@ -98,13 +95,35 @@ impl Element for EditorElement {
request_layout: &mut Self::RequestLayoutState, request_layout: &mut Self::RequestLayoutState,
cx: &mut WindowContext, cx: &mut WindowContext,
) -> Self::PrepaintState { ) -> Self::PrepaintState {
request_layout if self.cursor.y > 0 {
.styled let offset = Point::new(
.iter_mut() px(0.),
.for_each(|(id, styled, bounds)| { request_layout.styled.iter_mut().take(self.cursor.y).fold(
*bounds = cx.layout_bounds(*id); px(0.),
styled.prepaint(None, *bounds, &mut (), cx) |px, (id, _, bounds)| {
*bounds = cx.layout_bounds(*id);
px + bounds.size.height
},
),
);
cx.with_element_offset(offset, |cx| {
request_layout
.styled
.iter_mut()
.skip(self.cursor.y)
.for_each(|(_id, styled, bounds)| styled.prepaint(None, *bounds, &mut (), cx));
}); });
} else {
request_layout
.styled
.iter_mut()
.skip(self.cursor.y)
.for_each(|(id, styled, bounds)| {
*bounds = cx.layout_bounds(*id);
styled.prepaint(None, *bounds, &mut (), cx)
});
}
EditorLayout {} EditorLayout {}
} }
@ -126,41 +145,37 @@ impl Element for EditorElement {
ElementInputHandler::new(bounds, self.editor.clone()), ElementInputHandler::new(bounds, self.editor.clone()),
); );
let scrolled = self.scrolled.clone(); let view = self.editor.clone();
let font_size = self.style.font_size.to_pixels(px(4.)); let font_size = self.style.font_size.to_pixels(px(4.));
cx.on_mouse_event(move |scroll: &ScrollWheelEvent, _dispatch, cx| { cx.on_mouse_event(move |scroll: &ScrollWheelEvent, _dispatch, cx| {
match scroll.delta { log::trace!("{scroll:#?}");
ScrollDelta::Lines(lines) => scrolled.set({ view.update(cx, |editor, cx| match scroll.delta {
ScrollDelta::Lines(lines) => {
let lines_y = lines.y.ceil() as i32; let lines_y = lines.y.ceil() as i32;
scrolled.get().saturating_add_signed(lines_y as isize) editor.cursor.y = editor.cursor.y.saturating_add_signed(lines_y as isize)
}), }
ScrollDelta::Pixels(pix) => scrolled.set({ ScrollDelta::Pixels(pix) => {
let px_y = (pix.y.ceil().0 / font_size.0) as i32; let px_y = (pix.y.ceil().0 / font_size.0) as i32;
scrolled.get().saturating_add_signed(px_y as isize) editor.cursor.y = editor.cursor.y.saturating_add_signed(px_y as isize)
}), }
}; });
}); });
cx.with_text_style( cx.with_text_style(
Some(TextStyleRefinement { Some(TextStyleRefinement {
color: self color: self
.style .style
.hl_theme .theme
.settings .settings
.foreground .foreground
.map(hsla_from_syntect), .map(hsla_from_syntect),
background_color: self
.style
.hl_theme
.settings
.background
.map(hsla_from_syntect),
..Default::default() ..Default::default()
}), }),
|cx| { |cx| {
request_layout request_layout
.styled .styled
.iter_mut() .iter_mut()
.skip(self.cursor.y)
.for_each(|(id, styled, bounds)| { .for_each(|(id, styled, bounds)| {
styled.paint(None, *bounds, &mut (), &mut (), cx); styled.paint(None, *bounds, &mut (), &mut (), cx);
}); });

View file

@ -1,6 +1,6 @@
use std::sync::Arc; use std::sync::Arc;
use funnylog::Drain; use funnylog::{filter::LevelFilter, span, Drain, Level};
use ming::*; use ming::*;
mod buffer; mod buffer;
@ -41,10 +41,14 @@ fn main() {
.env_filter("RUST_LOG") .env_filter("RUST_LOG")
.ignore_error(), .ignore_error(),
); );
funnylog::stdlog::setup(drain.clone()).unwrap(); funnylog::stdlog::setup_with_level(drain.clone(), LevelFilter(Some(Level::Trace))).unwrap();
let logger = Logger::new(drain); let logger = Logger::new(drain);
App::new().run(|cx| { App::new().run(|cx| {
cx.bind_keys([
KeyBinding::new("up", editor::action::CursorUp, Some("Editor")),
KeyBinding::new("down", editor::action::CursorDown, Some("Editor")),
]);
cx.open_window( cx.open_window(
WindowOptions { WindowOptions {
..Default::default() ..Default::default()
@ -54,10 +58,7 @@ fn main() {
let settings = cx.new_model(|_cx| editor::EditorSettings::load_defaults()); let settings = cx.new_model(|_cx| editor::EditorSettings::load_defaults());
cx.new_view(|cx| Nite { cx.new_view(|cx| Nite {
editor: editor::Editor::make( editor: editor::Editor::make(cx, settings, logger.branch(span!("editor"))),
cx,
settings,
),
logger, logger,
}) })
}, },

View file

@ -0,0 +1,24 @@
name "Catppuccin Mocha"
background_color "#1e1e2e"
text_color "#cdd6f4"
highlights {
attribute "#f9e2af"
boolean "#fab387"
comment "#7f849c"
comment.doc "#7f849c"
constant "#fab387"
constructor "#89b4fa"
embedded "#eba0ac"
emphasis "#f38ba8"
emphasis.strong "#f38ba8" font_weight=700
enum "#94e2d5" font_weight=700
function "#89b4fa"
hint "#94e2d5"
keyword "#cba6f7"
link_text "#89b4fa"
link_uri "#89b4fa"
number "#fab387"
}

View file

@ -0,0 +1,40 @@
---
whiskers:
version: 2.0.2
matrix:
- variant: ["", "-no-italics"]
- flavor
- accent
filename: "{{flavor.identifier}}-{{accent}}{{variant}}.kdl"
---
{%set c = flavor.colors-%}
{%set accent = c[accent]-%}
{%if variant == "-no-italics"%}
{%set italic = "font_style=italic"-%}
{%else%}
{%set italic = ""-%}
{%endif%}
name "Catppuccin {{flavor.name}} {%- if variant == "-no-italics" %} (no italics) {%- endif -%}"
background_color "#{{c.base.hex}}"
text_color "#{{c.text.hex}}"
highlights {
attribute "#{{c.yellow.hex}}"
boolean "#{{c.peach.hex}}"
comment "#{{c.overlay1.hex}}" {{italic}}
comment.doc "#{{c.overlay1.hex}}" {{italic}}
constant "#{{c.peach.hex}}"
constructor "#{{c.blue.hex}}"
embedded "#{{c.maroon.hex}}"
emphasis "#{{c.red.hex}}" {{italic}}
emphasis.strong "#{{c.red.hex}}" font_weight=700
enum "#{{c.teal.hex}}" font_weight=700
function "#{{c.blue.hex}}" {{italic}}
hint "#{{c.teal.hex}}" {{italic}}
keyword "#{{c.mauve.hex}}"
link_text "#{{c.blue.hex}}"
link_uri "#{{c.blue.hex}}"
number "#{{c.peach.hex}}"
}