change to pepegsitter
This commit is contained in:
parent
1346d8ddbf
commit
0e48b78f1a
18 changed files with 217 additions and 185 deletions
80
Cargo.lock
generated
80
Cargo.lock
generated
|
@ -1649,22 +1649,6 @@ dependencies = [
|
|||
"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]]
|
||||
name = "inout"
|
||||
version = "0.1.3"
|
||||
|
@ -2203,12 +2187,13 @@ dependencies = [
|
|||
"anyhow",
|
||||
"careless",
|
||||
"funnylog",
|
||||
"inkjet",
|
||||
"kdl",
|
||||
"log",
|
||||
"miette",
|
||||
"ming",
|
||||
"pepegsitter",
|
||||
"serde",
|
||||
"tree-sitter-highlight",
|
||||
"widestring",
|
||||
]
|
||||
|
||||
|
@ -2560,6 +2545,17 @@ dependencies = [
|
|||
"hmac",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pepegsitter"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "215b00db1f5bfe7f8f1a3edb0e1ac9c4a42ffc4e50afd929c1e6a6f36d620cca"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"tree-sitter",
|
||||
"tree-sitter-highlight",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.3.1"
|
||||
|
@ -2718,7 +2714,7 @@ version = "3.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284"
|
||||
dependencies = [
|
||||
"toml_edit 0.21.1",
|
||||
"toml_edit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3160,15 +3156,6 @@ dependencies = [
|
|||
"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]]
|
||||
name = "sha1"
|
||||
version = "0.10.6"
|
||||
|
@ -3676,26 +3663,11 @@ dependencies = [
|
|||
"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]]
|
||||
name = "toml_datetime"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
|
@ -3705,20 +3677,7 @@ checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1"
|
|||
dependencies = [
|
||||
"indexmap",
|
||||
"toml_datetime",
|
||||
"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",
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4351,15 +4310,6 @@ dependencies = [
|
|||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.6.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wio"
|
||||
version = "0.2.2"
|
||||
|
|
|
@ -10,10 +10,11 @@ anyhow.workspace = true
|
|||
widestring = "1.1.0"
|
||||
log.workspace = true
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
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" }
|
||||
kdl = { version = "4.6.0", default-features = false }
|
||||
miette = { workspace = true, features = ["fancy"] }
|
||||
pepegsitter = { version = "0.2.2", features = ["tree-sitter-highlight"] }
|
||||
tree-sitter-highlight = "0.20.1"
|
||||
|
||||
[workspace]
|
||||
members = [
|
||||
|
|
|
@ -11,17 +11,21 @@ use std::{
|
|||
|
||||
use anyhow::{anyhow, Result};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use futures::{channel::oneshot, future::{LocalBoxFuture, FutureExt}, Future};
|
||||
use futures::{
|
||||
channel::oneshot,
|
||||
future::{FutureExt, LocalBoxFuture},
|
||||
Future,
|
||||
};
|
||||
use slotmap::SlotMap;
|
||||
use time::UtcOffset;
|
||||
|
||||
pub use async_context::*;
|
||||
use collections::{FxHashMap, FxHashSet, VecDeque};
|
||||
pub use entity_map::*;
|
||||
use util::http::{self, HttpClient};
|
||||
pub use model_context::*;
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub use test_context::*;
|
||||
use util::http::{self, HttpClient};
|
||||
use util::ResultExt;
|
||||
|
||||
use crate::{
|
||||
|
|
|
@ -13,8 +13,8 @@ use image::{ImageBuffer, ImageError};
|
|||
#[cfg(target_os = "macos")]
|
||||
use media::core_video::CVImageBuffer;
|
||||
|
||||
use util::http;
|
||||
use thiserror::Error;
|
||||
use util::http;
|
||||
use util::ResultExt;
|
||||
|
||||
/// A source of image content.
|
||||
|
|
|
@ -14,8 +14,8 @@ use crate::{
|
|||
use collections::VecDeque;
|
||||
use refineable::Refineable as _;
|
||||
use std::{cell::RefCell, ops::Range, rc::Rc};
|
||||
use util::sum_tree::{self, Bias, SumTree};
|
||||
use taffy::style::Overflow;
|
||||
use util::sum_tree::{self, Bias, SumTree};
|
||||
|
||||
/// Construct a new list element
|
||||
pub fn list(state: ListState) -> List {
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use crate::{AppContext, PlatformDispatcher};
|
||||
use futures::FutureExt;
|
||||
use std::{
|
||||
future::Future,
|
||||
fmt::Debug,
|
||||
future::Future,
|
||||
marker::PhantomData,
|
||||
mem,
|
||||
num::NonZeroUsize,
|
||||
|
@ -14,7 +15,6 @@ use std::{
|
|||
task::{Context, Poll},
|
||||
time::Duration,
|
||||
};
|
||||
use futures::FutureExt;
|
||||
use tokio::sync::mpsc;
|
||||
use util::TryFutureExt;
|
||||
use waker_fn::waker_fn;
|
||||
|
|
|
@ -111,11 +111,11 @@ impl<T: Clone + Debug + Default> Point<T> {
|
|||
}
|
||||
|
||||
/// Splats a `value` across both `x` and `y`
|
||||
pub const fn all(value: T) -> Self where T: Copy {
|
||||
Self {
|
||||
x: value,
|
||||
y: value
|
||||
}
|
||||
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.
|
||||
|
|
|
@ -125,18 +125,17 @@ pub use element::*;
|
|||
pub use elements::*;
|
||||
pub use executor::*;
|
||||
pub use geometry::*;
|
||||
pub use ming_macros::{register_action, test, IntoElement, Render};
|
||||
pub use input::*;
|
||||
pub use interactive::*;
|
||||
use key_dispatch::*;
|
||||
pub use keymap::*;
|
||||
pub use ming_macros::{register_action, test, IntoElement, Render};
|
||||
pub use platform::*;
|
||||
pub use refineable::*;
|
||||
pub use scene::*;
|
||||
use seal::Sealed;
|
||||
pub use shared_string::*;
|
||||
pub use shared_uri::*;
|
||||
pub use tokio::time::Sleep as Timer;
|
||||
pub use style::*;
|
||||
pub use styled::*;
|
||||
pub use subscription::*;
|
||||
|
@ -145,6 +144,7 @@ pub use taffy::{AvailableSpace, LayoutId};
|
|||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub use test::*;
|
||||
pub use text_system::*;
|
||||
pub use tokio::time::Sleep as Timer;
|
||||
pub use util::arc_cow::ArcCow;
|
||||
pub use view::*;
|
||||
pub use window::*;
|
||||
|
|
|
@ -58,10 +58,10 @@ pub(crate) use cosmic_text::*;
|
|||
pub(crate) use linux::*;
|
||||
#[cfg(target_os = "macos")]
|
||||
pub(crate) use mac::*;
|
||||
pub use util::semver::SemanticVersion;
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub(crate) use test::*;
|
||||
use time::UtcOffset;
|
||||
pub use util::semver::SemanticVersion;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub(crate) use windows::*;
|
||||
|
||||
|
|
|
@ -17,9 +17,9 @@ use copypasta::{ClipboardContext, ClipboardProvider};
|
|||
use futures::channel::oneshot::{self, Receiver};
|
||||
use itertools::Itertools;
|
||||
use parking_lot::RwLock;
|
||||
use util::semver::SemanticVersion;
|
||||
use smallvec::SmallVec;
|
||||
use time::UtcOffset;
|
||||
use util::semver::SemanticVersion;
|
||||
use windows::{
|
||||
core::*,
|
||||
Wdk::System::SystemServices::*,
|
||||
|
|
|
@ -652,8 +652,9 @@ impl<'de> serde::Deserialize<'de> for FontWeight {
|
|||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
v.parse()
|
||||
.map_err(|()| E::custom("expected a font weight value (e.g. 'normal' or 'bold')"))
|
||||
v.parse().map_err(|()| {
|
||||
E::custom("expected a font weight value (e.g. 'normal' or 'bold')")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,9 +15,12 @@ pub trait FluentBuilder {
|
|||
{
|
||||
f(self)
|
||||
}
|
||||
|
||||
|
||||
/// Imperatively modify self with the given closure.
|
||||
fn apply(mut self, f: impl FnOnce(&mut Self)) -> Self where Self: Sized {
|
||||
fn apply(mut self, f: impl FnOnce(&mut Self)) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
f(&mut self);
|
||||
|
||||
self
|
||||
|
|
|
@ -3,17 +3,18 @@ use proc_macro2::{Ident, Span, TokenStream};
|
|||
use quote::{format_ident, quote, ToTokens};
|
||||
use std::mem;
|
||||
use syn::{
|
||||
parse2, parse_quote, punctuated::Punctuated, spanned::Spanned as _, Expr,
|
||||
FnArg, ItemFn, Lit, Meta, PatLit as ExprLit, Token, Type,
|
||||
parse2, parse_quote, punctuated::Punctuated, spanned::Spanned as _, Expr, FnArg, ItemFn, Lit,
|
||||
Meta, PatLit as ExprLit, Token, Type,
|
||||
};
|
||||
|
||||
pub fn test(args: TS, function: TS) -> TS {
|
||||
test_impl(args.into(), function.into()).map_or_else(|e| e.into_compile_error().into(), |ts| ts.into())
|
||||
test_impl(args.into(), function.into())
|
||||
.map_or_else(|e| e.into_compile_error().into(), |ts| ts.into())
|
||||
}
|
||||
|
||||
fn test_impl(args: TokenStream, function: TokenStream) -> syn::Result<TokenStream> {
|
||||
let Meta::List(args) = parse2(args)? else {
|
||||
return Err(syn::Error::new(Span::call_site(), "invalid attr"))
|
||||
return Err(syn::Error::new(Span::call_site(), "invalid attr"));
|
||||
};
|
||||
let mut max_retries = 0;
|
||||
let mut num_iterations = 1;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
pub mod arc_cow;
|
||||
pub mod http;
|
||||
pub mod fs;
|
||||
pub mod http;
|
||||
pub mod paths;
|
||||
pub mod serde;
|
||||
pub mod semver;
|
||||
pub mod serde;
|
||||
pub mod sum_tree;
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub mod test;
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
use careless::prelude::*;
|
||||
use inkjet::tree_sitter_highlight::{Error, HighlightEvent, Highlighter};
|
||||
use funnylog::warn;
|
||||
use std::{ops::Range, path::PathBuf};
|
||||
use tree_sitter_highlight::{Error, HighlightConfiguration, HighlightEvent, Highlighter};
|
||||
use widestring::Utf16String;
|
||||
|
||||
use crate::editor::Theme;
|
||||
use crate::editor::{Highlight, Theme};
|
||||
use crate::vim::Mode;
|
||||
|
||||
use super::*;
|
||||
|
@ -15,7 +16,7 @@ pub struct Buffer {
|
|||
pub selected: Option<Range<usize>>,
|
||||
pub name: SharedString,
|
||||
pub modified: bool,
|
||||
pub mode: Mode
|
||||
pub mode: Mode,
|
||||
}
|
||||
|
||||
impl Buffer {
|
||||
|
@ -28,7 +29,7 @@ impl Buffer {
|
|||
marked: None,
|
||||
selected: None,
|
||||
modified: false,
|
||||
mode: Mode::default()
|
||||
mode: Mode::default(),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -40,33 +41,35 @@ impl Buffer {
|
|||
selected: None,
|
||||
name: SharedString::from_static("<scratch>"),
|
||||
modified: false,
|
||||
mode: Mode::default()
|
||||
mode: Mode::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn styled(&self, default_style: &TextStyle, theme: &Theme) -> Vec<StyledText> {
|
||||
let text = self.text.to_string();
|
||||
|
||||
if let Some(language) = self
|
||||
if let Some(mut language) = self
|
||||
.path
|
||||
.as_ref()
|
||||
.and_then(|path| path.extension())
|
||||
.and_then(|extension| {
|
||||
inkjet::Language::from_token(extension.to_str()?).map(|lang| lang.config())
|
||||
Language::from_token(extension.to_str()?).map(|lang| lang.config())
|
||||
})
|
||||
{
|
||||
let (indices, highlights): (Vec<&str>, Vec<&Highlight>) =
|
||||
theme.highlights.iter().map(|(name, hl)| (name.as_str(), hl)).unzip();
|
||||
language.configure(&indices);
|
||||
let mut hl = Highlighter::new();
|
||||
let mut lines = vec![];
|
||||
|
||||
for line in text.lines() {
|
||||
// damnation
|
||||
match hl
|
||||
.highlight(language, line.as_bytes(), None, |lang| {
|
||||
inkjet::Language::from_token(lang).map(|lang| lang.config())
|
||||
})
|
||||
.highlight(&language, line.as_bytes(), None, |lang| None)
|
||||
.and_then(|hls| {
|
||||
Ok(StyledText::new(Arc::from(line)).with_runs(
|
||||
MingHighlighter::new(hls, default_style, theme).try_to_collect()?,
|
||||
MingHighlighter::new(hls, default_style, &highlights)
|
||||
.try_to_collect()?,
|
||||
))
|
||||
}) {
|
||||
Ok(styled) => lines.push(styled),
|
||||
|
@ -92,17 +95,17 @@ impl Buffer {
|
|||
pub struct MingHighlighter<'a, I> {
|
||||
iter: I,
|
||||
default_style: &'a TextStyle,
|
||||
theme: &'a Theme,
|
||||
highlights: &'a [&'a Highlight],
|
||||
current_hl_idx: Option<usize>,
|
||||
current_span: Option<Range<usize>>,
|
||||
}
|
||||
|
||||
impl<'a, I> MingHighlighter<'a, I> {
|
||||
pub fn new(iter: I, default_style: &'a TextStyle, theme: &'a Theme) -> Self {
|
||||
pub fn new(iter: I, default_style: &'a TextStyle, highlights: &'a [&'a Highlight]) -> Self {
|
||||
Self {
|
||||
iter,
|
||||
default_style,
|
||||
theme,
|
||||
highlights,
|
||||
current_hl_idx: None,
|
||||
current_span: None,
|
||||
}
|
||||
|
@ -122,9 +125,8 @@ impl<I: Iterator<Item = Result<HighlightEvent, Error>>> Iterator for MingHighlig
|
|||
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))
|
||||
if let Some(hl) =
|
||||
self.current_hl_idx.and_then(|idx| self.highlights.get(idx))
|
||||
{
|
||||
hl.apply_to_run(run)
|
||||
}
|
||||
|
@ -143,3 +145,24 @@ impl<I: Iterator<Item = Result<HighlightEvent, Error>>> Iterator for MingHighlig
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Language {
|
||||
Rust,
|
||||
Toml,
|
||||
}
|
||||
|
||||
impl Language {
|
||||
pub fn from_token(token: &str) -> Option<Self> {
|
||||
Some(match token {
|
||||
"rs" | "rust" => Self::Rust,
|
||||
"toml" => Self::Toml,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
pub fn config(&self) -> HighlightConfiguration {
|
||||
match self {
|
||||
Self::Rust => pepegsitter::rust::highlight(),
|
||||
Self::Toml => pepegsitter::toml::highlight(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ pub struct Theme {
|
|||
pub name: String,
|
||||
pub background_color: Rgba,
|
||||
pub text_color: Rgba,
|
||||
pub highlight_indices: Vec<Highlight>,
|
||||
pub highlights: Vec<(String, Highlight)>,
|
||||
}
|
||||
|
||||
fn rgba_from_kdl(value: &KdlValue) -> miette::Result<Rgba> {
|
||||
|
@ -103,18 +103,12 @@ impl Theme {
|
|||
}
|
||||
|
||||
pub fn from_kdl_document(document: KdlDocument) -> miette::Result<Self> {
|
||||
let highlight_indices = match document.get("highlights").and_then(|node| node.children()) {
|
||||
Some(doc) => {
|
||||
let mut indices = vec![];
|
||||
|
||||
for name in inkjet::constants::HIGHLIGHT_NAMES {
|
||||
let Some(node) = doc.get(*name) else { continue };
|
||||
|
||||
indices.push(Highlight::from_kdl_node(node)?);
|
||||
}
|
||||
|
||||
indices
|
||||
}
|
||||
let highlights = match document.get("highlights").and_then(|node| node.children()) {
|
||||
Some(doc) => doc
|
||||
.nodes()
|
||||
.iter()
|
||||
.map(|node| Highlight::from_kdl_node(node).map(|hl| (node.name().to_string(), hl)))
|
||||
.try_to_collect()?,
|
||||
None => Default::default(),
|
||||
};
|
||||
|
||||
|
@ -133,7 +127,7 @@ impl Theme {
|
|||
.get_arg("text_color")
|
||||
.context("no background_color attr")
|
||||
.and_then(rgba_from_kdl)?,
|
||||
highlight_indices,
|
||||
highlights,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -198,7 +192,6 @@ impl Editor {
|
|||
let buf = self.buf.read(cx);
|
||||
|
||||
div()
|
||||
.debug()
|
||||
.flex()
|
||||
.flex_row()
|
||||
.justify_between()
|
||||
|
@ -233,16 +226,15 @@ impl Editor {
|
|||
impl Render for Editor {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
cx.focus(&self.focus_handle);
|
||||
let styled = {
|
||||
// -1 read...
|
||||
let style = &self.settings.read(cx).style;
|
||||
|
||||
div()
|
||||
.font_family(style.font_family.clone())
|
||||
.text_color(style.theme.text_color)
|
||||
};
|
||||
div()
|
||||
.map(|div| {
|
||||
let style = &self.settings.read(cx).style;
|
||||
|
||||
styled.key_context("Editor")
|
||||
div.font_family(style.font_family.clone())
|
||||
.text_color(style.theme.text_color)
|
||||
})
|
||||
.key_context("Editor")
|
||||
.on_action(cx.listener(|me, event: &action::CursorDown, cx| {
|
||||
me.cursor.y = me.cursor.y.saturating_add(1).min(
|
||||
me.buf
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::fmt::write;
|
||||
use std::{any::TypeId, fmt::write};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
@ -122,6 +122,7 @@ impl Element for EditorElement {
|
|||
) {
|
||||
let focus_handle = self.editor.focus_handle(cx);
|
||||
let key_context = self.editor.read(cx).key_context(cx);
|
||||
|
||||
cx.set_focus_handle(&focus_handle);
|
||||
cx.set_key_context(key_context);
|
||||
cx.handle_input(
|
||||
|
@ -129,68 +130,124 @@ impl Element for EditorElement {
|
|||
ElementInputHandler::new(bounds, self.editor.clone()),
|
||||
);
|
||||
|
||||
let view = self.editor.clone();
|
||||
let font_size = self.style.font_size.to_pixels(px(4.));
|
||||
let hb = prepaint.hb.clone();
|
||||
let styled_bounds: Arc<[Bounds<Pixels>]> = Arc::from(
|
||||
request_layout
|
||||
.styled
|
||||
.iter()
|
||||
.map(|(_, _, b)| *b)
|
||||
.collect::<Vec<Bounds<Pixels>>>(),
|
||||
);
|
||||
|
||||
let styled_bounds = request_layout
|
||||
.styled
|
||||
.iter()
|
||||
.map(|(_, _, b)| *b)
|
||||
.collect::<Vec<_>>();
|
||||
cx.on_action(TypeId::of::<action::CursorUp>(), {
|
||||
let view = self.editor.clone();
|
||||
let styled_bounds = styled_bounds.clone();
|
||||
|
||||
cx.on_mouse_event(move |scroll: &ScrollWheelEvent, dispatch, cx| {
|
||||
if !dispatch.bubble() || !hb.is_hovered(cx) {
|
||||
return;
|
||||
}
|
||||
|
||||
view.update(cx, |editor, cx| {
|
||||
let prev_editor_scroll = editor.scroll;
|
||||
let change = match scroll.delta {
|
||||
ScrollDelta::Lines(pnt) => {
|
||||
let mut lines = pnt.y.abs();
|
||||
let mut do_scroll = px(0.);
|
||||
|
||||
for bounds in styled_bounds.iter() {
|
||||
if lines <= 1. {
|
||||
do_scroll += px(bounds.size.height.0 * lines);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
do_scroll += bounds.size.height;
|
||||
lines -= 1.;
|
||||
}
|
||||
|
||||
point(px(0.), do_scroll * pnt.y.signum())
|
||||
move |_event, _dispatch, cx| {
|
||||
view.update(cx, |editor, cx| {
|
||||
if editor.cursor.y == 0 {
|
||||
return;
|
||||
}
|
||||
ScrollDelta::Pixels(pix) => pix,
|
||||
};
|
||||
|
||||
editor.scroll = (editor.scroll + change).clamp(
|
||||
&point(bounds.size.width, bounds.size.height).negate(),
|
||||
&Point::default(),
|
||||
);
|
||||
editor.cursor.y = editor.cursor.y.saturating_sub(1);
|
||||
|
||||
let prev_ruler = editor.ruler;
|
||||
let next_ruler = (editor.scroll.y.0 / bounds.size.height.0 * 100.).abs().floor() as u8;
|
||||
let line_bounds = styled_bounds
|
||||
.iter()
|
||||
.take(editor.cursor.y)
|
||||
.fold(px(0.), |px, bounds| px + bounds.size.height);
|
||||
|
||||
if prev_ruler != next_ruler {
|
||||
editor.ruler = next_ruler;
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
log::trace!(
|
||||
"[{prev_editor_scroll:#?} -> {:#?}] [{prev_ruler}% -> {next_ruler}%] {scroll:#?}",
|
||||
editor.scroll
|
||||
);
|
||||
if line_bounds > bounds.size.height {
|
||||
editor.scroll.y = -line_bounds;
|
||||
}
|
||||
});
|
||||
|
||||
cx.stop_propagation();
|
||||
}
|
||||
});
|
||||
|
||||
if !change.is_zero() {
|
||||
cx.refresh();
|
||||
cx.on_action(TypeId::of::<action::CursorDown>(), {
|
||||
let view = self.editor.clone();
|
||||
let styled_bounds = styled_bounds.clone();
|
||||
|
||||
move |_event, _dispatch, cx| {
|
||||
view.update(cx, |editor, cx| {
|
||||
if editor.cursor.y == editor.buf.read(cx).text.chars().filter(|char| *char == '\n').count() {
|
||||
return;
|
||||
}
|
||||
|
||||
editor.cursor.y += 1;
|
||||
|
||||
let line_bounds = styled_bounds
|
||||
.iter()
|
||||
.take(editor.cursor.y)
|
||||
.fold(px(0.), |px, bounds| px + bounds.size.height);
|
||||
|
||||
if line_bounds > bounds.size.height {
|
||||
editor.scroll.y = -line_bounds;
|
||||
}
|
||||
});
|
||||
|
||||
cx.stop_propagation();
|
||||
}
|
||||
});
|
||||
|
||||
cx.on_mouse_event({
|
||||
let view = self.editor.clone();
|
||||
let hb = prepaint.hb.clone();
|
||||
let styled_bounds = styled_bounds.clone();
|
||||
|
||||
move |scroll: &ScrollWheelEvent, dispatch, cx| {
|
||||
if !dispatch.bubble() || !hb.is_hovered(cx) {
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
view.update(cx, |editor, cx| {
|
||||
let prev_editor_scroll = editor.scroll;
|
||||
let change = match scroll.delta {
|
||||
ScrollDelta::Lines(pnt) => {
|
||||
let mut lines = pnt.y.abs();
|
||||
let mut do_scroll = px(0.);
|
||||
|
||||
for bounds in styled_bounds.iter() {
|
||||
if lines <= 1. {
|
||||
do_scroll += px(bounds.size.height.0 * lines);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
do_scroll += bounds.size.height;
|
||||
lines -= 1.;
|
||||
}
|
||||
|
||||
point(px(0.), do_scroll * pnt.y.signum())
|
||||
}
|
||||
ScrollDelta::Pixels(pix) => pix,
|
||||
};
|
||||
|
||||
editor.scroll = (editor.scroll + change).clamp(
|
||||
&point(bounds.size.width, bounds.size.height).negate(),
|
||||
&Point::default(),
|
||||
);
|
||||
|
||||
let prev_ruler = editor.ruler;
|
||||
let next_ruler = (editor.scroll.y.0 / bounds.size.height.0 * 100.).abs().floor() as u8;
|
||||
|
||||
if prev_ruler != next_ruler {
|
||||
editor.ruler = next_ruler;
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
log::trace!(
|
||||
"[{prev_editor_scroll:#?} -> {:#?}] [{prev_ruler}% -> {next_ruler}%] {scroll:#?}",
|
||||
editor.scroll
|
||||
);
|
||||
|
||||
cx.stop_propagation();
|
||||
|
||||
if !change.is_zero() {
|
||||
cx.refresh();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
cx.with_text_style(
|
||||
|
|
|
@ -3,5 +3,5 @@ pub enum Mode {
|
|||
#[default]
|
||||
Normal,
|
||||
Insert,
|
||||
Visual
|
||||
Visual,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue