i treesittered
This commit is contained in:
parent
638a9a112b
commit
7424dc67b7
9 changed files with 219 additions and 148 deletions
97
Cargo.lock
generated
97
Cargo.lock
generated
|
@ -500,6 +500,10 @@ dependencies = [
|
||||||
"wayland-client",
|
"wayland-client",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "careless"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "castaway"
|
name = "castaway"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
|
@ -1651,6 +1655,22 @@ dependencies = [
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inkjet"
|
||||||
|
version = "0.10.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cdd9fd670f1a42725a90e7a97f5e6a777fc56f9031c1ee0ebcea8f91a6bb9c2f"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"cc",
|
||||||
|
"once_cell",
|
||||||
|
"serde",
|
||||||
|
"thiserror",
|
||||||
|
"toml",
|
||||||
|
"tree-sitter",
|
||||||
|
"tree-sitter-highlight",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "inout"
|
name = "inout"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
|
@ -2166,13 +2186,13 @@ name = "nite"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"careless",
|
||||||
"funnylog",
|
"funnylog",
|
||||||
|
"inkjet",
|
||||||
"kaydle",
|
"kaydle",
|
||||||
"log",
|
"log",
|
||||||
"ming",
|
"ming",
|
||||||
"serde",
|
"serde",
|
||||||
"tree-sitter-highlight",
|
|
||||||
"tree-sitter-rust",
|
|
||||||
"widestring",
|
"widestring",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2689,7 +2709,7 @@ version = "3.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284"
|
checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"toml_edit",
|
"toml_edit 0.21.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3140,6 +3160,15 @@ dependencies = [
|
||||||
"syn 2.0.63",
|
"syn 2.0.63",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_spanned"
|
||||||
|
version = "0.6.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha1"
|
name = "sha1"
|
||||||
version = "0.10.6"
|
version = "0.10.6"
|
||||||
|
@ -3592,11 +3621,26 @@ dependencies = [
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.8.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"toml_edit 0.22.12",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_datetime"
|
name = "toml_datetime"
|
||||||
version = "0.6.5"
|
version = "0.6.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
|
checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_edit"
|
name = "toml_edit"
|
||||||
|
@ -3606,7 +3650,20 @@ checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"toml_datetime",
|
"toml_datetime",
|
||||||
"winnow",
|
"winnow 0.5.40",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_edit"
|
||||||
|
version = "0.22.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"winnow 0.6.8",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3653,9 +3710,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tree-sitter"
|
name = "tree-sitter"
|
||||||
version = "0.22.6"
|
version = "0.20.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "df7cc499ceadd4dcdf7ec6d4cbc34ece92c3fa07821e287aedecd4416c516dca"
|
checksum = "e747b1f9b7b931ed39a548c1fae149101497de3c1fc8d9e18c62c1a66c683d3d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"regex",
|
"regex",
|
||||||
|
@ -3663,26 +3720,15 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tree-sitter-highlight"
|
name = "tree-sitter-highlight"
|
||||||
version = "0.22.6"
|
version = "0.20.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "eaca0fe34fa96eec6aaa8e63308dbe1bafe65a6317487c287f93938959b21907"
|
checksum = "042342584c5a7a0b833d9fc4e2bdab3f9868ddc6c4b339a1e01451c6720868bc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
|
||||||
"regex",
|
"regex",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tree-sitter",
|
"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"
|
||||||
|
@ -4250,6 +4296,15 @@ dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winnow"
|
||||||
|
version = "0.6.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wio"
|
name = "wio"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
|
@ -4471,7 +4526,3 @@ dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[patch.unused]]
|
|
||||||
name = "careless"
|
|
||||||
version = "0.1.0"
|
|
||||||
|
|
|
@ -9,10 +9,10 @@ ming.workspace = true
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
widestring = "1.1.0"
|
widestring = "1.1.0"
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
tree-sitter-highlight = "0.22.6"
|
|
||||||
tree-sitter-rust = "0.21.2"
|
|
||||||
serde = { workspace = true, features = ["derive"] }
|
serde = { workspace = true, features = ["derive"] }
|
||||||
kaydle = "0.2.0"
|
kaydle = "0.2.0"
|
||||||
|
inkjet = { version = "0.10.5", features = ["language-rust", "language-toml", "language-zig"], default-features = false }
|
||||||
|
careless = { git = "https://codeberg.org/minky/careless", version = "0.1.0" }
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
|
|
|
@ -109,6 +109,7 @@ pub trait IntoElement: Sized {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FluentBuilder for crate::TextRun {}
|
||||||
impl<T: IntoElement> FluentBuilder for T {}
|
impl<T: IntoElement> FluentBuilder for T {}
|
||||||
|
|
||||||
/// An object that can be drawn to the screen. This is the trait that distinguishes `Views` from
|
/// An object that can be drawn to the screen. This is the trait that distinguishes `Views` from
|
||||||
|
|
|
@ -656,6 +656,8 @@ impl<'de> serde::Deserialize<'de> for FontWeight {
|
||||||
.map_err(|()| E::custom("expected a font weight value (e.g. 'normal' or 'bold')"))
|
.map_err(|()| E::custom("expected a font weight value (e.g. 'normal' or 'bold')"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deserializer.deserialize_any(Visitor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,13 @@ pub trait FluentBuilder {
|
||||||
f(self)
|
f(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Imperatively modify self with the given closure.
|
||||||
|
fn apply(mut self, f: impl FnOnce(&mut Self)) -> Self where Self: Sized {
|
||||||
|
f(&mut self);
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Conditionally modify self with the given closure.
|
/// Conditionally modify self with the given closure.
|
||||||
fn when(self, condition: bool, then: impl FnOnce(Self) -> Self) -> Self
|
fn when(self, condition: bool, then: impl FnOnce(Self) -> Self) -> Self
|
||||||
where
|
where
|
||||||
|
|
148
src/buffer.rs
148
src/buffer.rs
|
@ -1,7 +1,10 @@
|
||||||
|
use careless::prelude::*;
|
||||||
|
use inkjet::tree_sitter_highlight::{Error, HighlightEvent, Highlighter};
|
||||||
use std::{ops::Range, path::PathBuf};
|
use std::{ops::Range, path::PathBuf};
|
||||||
use tree_sitter_highlight::{HighlightConfiguration, Highlighter};
|
|
||||||
use widestring::Utf16String;
|
use widestring::Utf16String;
|
||||||
|
|
||||||
|
use crate::editor::Theme;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub struct Buffer {
|
pub struct Buffer {
|
||||||
|
@ -31,71 +34,43 @@ impl Buffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn styled(
|
pub fn styled(&self, default_style: &TextStyle, theme: &Theme) -> Vec<StyledText> {
|
||||||
&self,
|
|
||||||
default_style: &TextStyle,
|
|
||||||
theme: &crate::editor::Theme,
|
|
||||||
syntax_set: &SyntaxSet,
|
|
||||||
) -> Vec<StyledText> {
|
|
||||||
let text = self.text.to_string();
|
let text = self.text.to_string();
|
||||||
|
|
||||||
if let Some(syntax) = self
|
if let Some(language) = self
|
||||||
.path
|
.path
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|path| path.extension())
|
.and_then(|path| path.extension())
|
||||||
.and_then(|extension| {
|
.and_then(|extension| {
|
||||||
Some(
|
inkjet::Language::from_token(extension.to_str()?).map(|lang| lang.config())
|
||||||
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 hl = Highlighter::new();
|
||||||
let hler = Highlighter::new(theme);
|
let mut lines = vec![];
|
||||||
let mut hl = HighlightState::new(&hler, ScopeStack::new());
|
|
||||||
|
|
||||||
text.lines()
|
for line in text.lines() {
|
||||||
.flat_map(|line| {
|
// damnation
|
||||||
parse.parse_line(line, &syntax_set).map(|parsed| {
|
match hl
|
||||||
StyledText::new(Arc::from(line)).with_highlights(
|
.highlight(language, line.as_bytes(), None, |lang| {
|
||||||
default_style,
|
inkjet::Language::from_token(lang).map(|lang| lang.config())
|
||||||
RangedHighlightIterator::new(&mut hl, &parsed, line, &hler).map(
|
|
||||||
move |(style, _text, range)| {
|
|
||||||
(
|
|
||||||
range,
|
|
||||||
HighlightStyle {
|
|
||||||
color: Some(hsla_from_syntect(style.foreground)),
|
|
||||||
background_color: None,
|
|
||||||
font_style: style
|
|
||||||
.font_style
|
|
||||||
.contains(SFontStyle::ITALIC)
|
|
||||||
.then(|| FontStyle::Italic),
|
|
||||||
underline: style
|
|
||||||
.font_style
|
|
||||||
.contains(SFontStyle::UNDERLINE)
|
|
||||||
.then(|| UnderlineStyle::default()),
|
|
||||||
font_weight: style
|
|
||||||
.font_style
|
|
||||||
.contains(SFontStyle::BOLD)
|
|
||||||
.then(|| FontWeight::BOLD),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
})
|
.and_then(|hls| {
|
||||||
.collect()
|
Ok(StyledText::new(Arc::from(line)).with_runs(
|
||||||
|
MingHighlighter::new(hls, default_style, theme).try_to_collect()?,
|
||||||
|
))
|
||||||
|
}) {
|
||||||
|
Ok(styled) => lines.push(styled),
|
||||||
|
Err(error) => {
|
||||||
|
log::error!("highlight error: {error}");
|
||||||
|
|
||||||
|
lines.push(StyledText::new(Arc::from(line)));
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lines
|
||||||
} else {
|
} else {
|
||||||
text.lines()
|
text.lines()
|
||||||
.map(|line| StyledText::new(Arc::from(line)))
|
.map(|line| StyledText::new(Arc::from(line)))
|
||||||
|
@ -104,12 +79,57 @@ impl Buffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hsla_from_syntect(color: Color) -> Hsla {
|
pub struct MingHighlighter<'a, I> {
|
||||||
Rgba {
|
iter: I,
|
||||||
r: color.r as f32 / 255.0,
|
default_style: &'a TextStyle,
|
||||||
g: color.g as f32 / 255.0,
|
theme: &'a Theme,
|
||||||
b: color.b as f32 / 255.0,
|
current_hl_idx: Option<usize>,
|
||||||
a: color.a as f32 / 255.0,
|
current_span: Option<Range<usize>>,
|
||||||
}
|
}
|
||||||
.into()
|
|
||||||
|
impl<'a, I> MingHighlighter<'a, I> {
|
||||||
|
pub fn new(iter: I, default_style: &'a TextStyle, theme: &'a Theme) -> Self {
|
||||||
|
Self {
|
||||||
|
iter,
|
||||||
|
default_style,
|
||||||
|
theme,
|
||||||
|
current_hl_idx: None,
|
||||||
|
current_span: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Iterator<Item = Result<HighlightEvent, Error>>> Iterator for MingHighlighter<'_, I> {
|
||||||
|
type Item = Result<TextRun, Error>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
use careless::prelude::*;
|
||||||
|
|
||||||
|
TryOption::into(
|
||||||
|
try {
|
||||||
|
match self.iter.try_next()? {
|
||||||
|
HighlightEvent::Source { start, end } => {
|
||||||
|
self.current_span = Some(start..end);
|
||||||
|
|
||||||
|
self.default_style.to_run(end - start).apply(|run| {
|
||||||
|
if let Some(hl) = self
|
||||||
|
.current_hl_idx
|
||||||
|
.and_then(|idx| self.theme.highlight_indices.get(idx))
|
||||||
|
{
|
||||||
|
hl.apply_to_run(run)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
HighlightEvent::HighlightStart(hl_idx) => {
|
||||||
|
self.current_hl_idx = Some(hl_idx.0);
|
||||||
|
self.try_next()?
|
||||||
|
}
|
||||||
|
HighlightEvent::HighlightEnd => {
|
||||||
|
self.current_hl_idx = None;
|
||||||
|
self.try_next()?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ pub struct EditorSettings {
|
||||||
style: EditorStyle,
|
style: EditorStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Debug, Deserialize)]
|
||||||
pub struct Highlight {
|
pub struct Highlight {
|
||||||
pub color: Option<Rgba>,
|
pub color: Option<Rgba>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
@ -20,17 +20,41 @@ pub struct Highlight {
|
||||||
pub weight: Option<FontWeight>,
|
pub weight: Option<FontWeight>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
impl Highlight {
|
||||||
|
pub fn apply_to_run(&self, run: &mut TextRun) {
|
||||||
|
if let Some(color) = self.color {
|
||||||
|
run.color = color.into();
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(style) = self.style {
|
||||||
|
run.font.style = style;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(weight) = self.weight {
|
||||||
|
run.font.weight = weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
pub struct Theme {
|
pub struct Theme {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub background_color: Rgba,
|
pub background_color: Rgba,
|
||||||
pub text_color: Rgba,
|
pub text_color: Rgba,
|
||||||
pub highlights: HashMap<String, Highlight>,
|
pub highlights: HashMap<String, Highlight>,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub highlight_indices: Vec<Highlight>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Theme {
|
impl Theme {
|
||||||
pub fn load(text: &str) -> Result<Self, kaydle::serde::de::Error> {
|
pub fn load(text: &str) -> Result<Self, kaydle::serde::de::Error> {
|
||||||
kaydle::serde::from_str(text)
|
kaydle::serde::from_str(text).map(|mut me: Self| {
|
||||||
|
me.highlight_indices = inkjet::constants::HIGHLIGHT_NAMES.iter().flat_map(|hl| {
|
||||||
|
me.highlights.get(*hl).cloned()
|
||||||
|
}).collect();
|
||||||
|
|
||||||
|
me
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,6 +85,7 @@ pub struct Editor {
|
||||||
buf: Model<crate::buffer::Buffer>,
|
buf: Model<crate::buffer::Buffer>,
|
||||||
settings: Model<EditorSettings>,
|
settings: Model<EditorSettings>,
|
||||||
cursor: Point<usize>,
|
cursor: Point<usize>,
|
||||||
|
scroll: Point<Pixels>,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,6 +107,7 @@ impl Editor {
|
||||||
settings,
|
settings,
|
||||||
logger,
|
logger,
|
||||||
cursor: Point::default(),
|
cursor: Point::default(),
|
||||||
|
scroll: Point::default()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,10 +133,10 @@ impl Render for Editor {
|
||||||
me.cursor.y = me.cursor.y.saturating_sub(1);
|
me.cursor.y = me.cursor.y.saturating_sub(1);
|
||||||
funnylog::trace!(me.logger, ?me.cursor, "up");
|
funnylog::trace!(me.logger, ?me.cursor, "up");
|
||||||
}))
|
}))
|
||||||
|
.overflow_hidden()
|
||||||
.child(element::EditorElement::new(
|
.child(element::EditorElement::new(
|
||||||
cx.view(),
|
cx.view(),
|
||||||
self.settings.read(cx).style.clone(),
|
self.settings.read(cx).style.clone(),
|
||||||
self.cursor,
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,15 @@
|
||||||
use crate::buffer::hsla_from_syntect;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
|
||||||
pub struct EditorElement {
|
pub struct EditorElement {
|
||||||
editor: View<Editor>,
|
editor: View<Editor>,
|
||||||
style: EditorStyle,
|
style: EditorStyle,
|
||||||
cursor: Point<usize>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EditorElement {
|
impl EditorElement {
|
||||||
pub fn new(viewref: &View<Editor>, style: EditorStyle, cursor: Point<usize>) -> Self {
|
pub fn new(viewref: &View<Editor>, style: EditorStyle) -> Self {
|
||||||
Self {
|
Self {
|
||||||
editor: viewref.clone(),
|
editor: viewref.clone(),
|
||||||
style,
|
style,
|
||||||
cursor,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,14 +61,9 @@ 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),
|
overflow: Point::all(Overflow::Hidden),
|
||||||
size: Size::full(),
|
size: Size::full(),
|
||||||
background: self
|
background: Some(Fill::Color(self.style.theme.background_color.into())),
|
||||||
.style
|
|
||||||
.theme
|
|
||||||
.settings
|
|
||||||
.background
|
|
||||||
.map(|bg| Fill::Color(hsla_from_syntect(bg))),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
children.iter().copied(),
|
children.iter().copied(),
|
||||||
|
@ -95,35 +85,12 @@ impl Element for EditorElement {
|
||||||
request_layout: &mut Self::RequestLayoutState,
|
request_layout: &mut Self::RequestLayoutState,
|
||||||
cx: &mut WindowContext,
|
cx: &mut WindowContext,
|
||||||
) -> Self::PrepaintState {
|
) -> Self::PrepaintState {
|
||||||
if self.cursor.y > 0 {
|
cx.with_element_offset(self.editor.read(cx).scroll, |cx| {
|
||||||
let offset = Point::new(
|
|
||||||
px(0.),
|
|
||||||
request_layout.styled.iter_mut().take(self.cursor.y).fold(
|
|
||||||
px(0.),
|
|
||||||
|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
|
request_layout
|
||||||
.styled
|
.styled
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.skip(self.cursor.y)
|
.for_each(|(_id, styled, bounds)| styled.prepaint(None, *bounds, &mut (), cx));
|
||||||
.for_each(|(id, styled, bounds)| {
|
});
|
||||||
*bounds = cx.layout_bounds(*id);
|
|
||||||
styled.prepaint(None, *bounds, &mut (), cx)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorLayout {}
|
EditorLayout {}
|
||||||
}
|
}
|
||||||
|
@ -151,8 +118,7 @@ impl Element for EditorElement {
|
||||||
log::trace!("{scroll:#?}");
|
log::trace!("{scroll:#?}");
|
||||||
view.update(cx, |editor, cx| match scroll.delta {
|
view.update(cx, |editor, cx| match scroll.delta {
|
||||||
ScrollDelta::Lines(lines) => {
|
ScrollDelta::Lines(lines) => {
|
||||||
let lines_y = lines.y.ceil() as i32;
|
|
||||||
editor.cursor.y = editor.cursor.y.saturating_add_signed(lines_y as isize)
|
|
||||||
}
|
}
|
||||||
ScrollDelta::Pixels(pix) => {
|
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;
|
||||||
|
@ -163,22 +129,18 @@ impl Element for EditorElement {
|
||||||
|
|
||||||
cx.with_text_style(
|
cx.with_text_style(
|
||||||
Some(TextStyleRefinement {
|
Some(TextStyleRefinement {
|
||||||
color: self
|
color: Some(self.style.theme.text_color.into()),
|
||||||
.style
|
|
||||||
.theme
|
|
||||||
.settings
|
|
||||||
.foreground
|
|
||||||
.map(hsla_from_syntect),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
|cx| {
|
|cx| {
|
||||||
request_layout
|
cx.with_element_offset(self.editor.read(cx).scroll, |cx| {
|
||||||
.styled
|
request_layout
|
||||||
.iter_mut()
|
.styled
|
||||||
.skip(self.cursor.y)
|
.iter_mut()
|
||||||
.for_each(|(id, styled, bounds)| {
|
.for_each(|(_id, styled, bounds)| {
|
||||||
styled.paint(None, *bounds, &mut (), &mut (), cx);
|
styled.paint(None, *bounds, &mut (), &mut (), cx)
|
||||||
});
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
|
#![feature(try_blocks)]
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use funnylog::{filter::LevelFilter, span, Drain, Level};
|
use funnylog::{filter::LevelFilter, span, Drain, Level};
|
||||||
use ming::*;
|
use ming::{*, prelude::*};
|
||||||
|
|
||||||
mod buffer;
|
mod buffer;
|
||||||
mod editor;
|
mod editor;
|
||||||
|
|
Loading…
Reference in a new issue