A simple CPU rendered GUI IDE experience.
ditch rangemap
bendn 9 days ago
parent b1868a2 · commit 69edda4
-rw-r--r--src/text.rs89
-rw-r--r--src/text/semantic_tokens.rs15
2 files changed, 54 insertions, 50 deletions
diff --git a/src/text.rs b/src/text.rs
index 4ec7630..06d3ed6 100644
--- a/src/text.rs
+++ b/src/text.rs
@@ -1,7 +1,6 @@
use std::cmp::{Reverse, min};
use std::collections::BTreeSet;
use std::fmt::{Debug, Display};
-use std::mem::take;
use std::ops::{Deref, Range, RangeBounds};
use std::path::Path;
use std::pin::pin;
@@ -19,7 +18,6 @@ use implicit_fn::implicit_fn;
use lsp_types::{
Location, Position, SemanticTokensLegend, SnippetTextEdit, TextEdit,
};
-use rangemap::RangeMap;
use ropey::{Rope, RopeSlice};
use serde::{Deserialize, Serialize};
use tree_house::Language;
@@ -183,7 +181,7 @@ pub struct TextArea {
#[serde(skip)]
pub tabstops: Option<Snippet>,
pub inlays: BTreeSet<Inlay>,
- pub tokens: RangeMap<u32, TokenD>, // TODO: fixperf
+ pub tokens: Vec<TokenD>, // TODO: fixperf
}
#[derive(Serialize, Deserialize)]
pub struct CellBuffer {
@@ -339,22 +337,29 @@ impl TextArea {
)
}
+ #[inline(always)]
pub fn source_map(
&'_ self,
l: usize,
) -> Option<impl Iterator<Item = Mapping<'_>>> {
let s = self.rope.try_line_to_char(l).ok()?;
let lin = self.rope.get_line(l)?;
- Some(gen move {
- for (char, i) in lin.chars().zip(s..) {
- if let Some(x) = self.inlays.get(&Marking::idx(i as _)) {
- for (i, (c, _)) in x.data.iter().enumerate() {
- yield Mapping::Fake(x, i as u32, x.position, *c);
+ Some(
+ #[inline(always)]
+ gen move {
+ for (char, i) in lin.chars().zip(s..) {
+ if let Some(x) = self.inlays.get(&Marking::idx(i as _))
+ {
+ for (i, (c, _)) in x.data.iter().enumerate() {
+ yield Mapping::Fake(
+ x, i as u32, x.position, *c,
+ );
+ }
}
+ yield Mapping::Char(char, i - s, i);
}
- yield Mapping::Char(char, i - s, i);
- }
- })
+ },
+ )
}
pub fn reverse_source_map_w(
&'_ self,
@@ -437,16 +442,9 @@ impl TextArea {
m.position -= r.len() as u32;
self.inlays.insert(m);
}
- for (mut tr, d) in self
- .tokens
- .overlapping(r.end as _..u32::MAX)
- .map(|(x, y)| (x.clone(), *y))
- .collect::<Vec<_>>()
- {
- self.tokens.remove(tr.clone());
- tr.start -= r.len() as u32;
- tr.end -= r.len() as u32;
- self.tokens.insert(tr, d);
+ for d in self.tokens.iter_mut() {
+ d.range.0 = manip(d.range.0 as _) as _;
+ d.range.1 = manip(d.range.0 as _) as _;
}
Ok(())
}
@@ -477,19 +475,9 @@ impl TextArea {
m.position += with.chars().count() as u32;
self.inlays.insert(m);
}
- for (tr, d) in take(&mut self.tokens)
- .into_iter()
- // .overlapping(c as u32..u32::MAX)
- // .map(|(x, y)| (x.clone(), *y))
- .map(|(tr, d)| {
- (manip(tr.start as _) as u32..manip(tr.end as _) as u32, d)
- })
- // .collect::<Vec<_>>()
- {
- // self.tokens.remove(tr.clone());
- // tr.start += with.chars().count() as u32;
- // tr.end += with.chars().count() as u32;
- self.tokens.insert(tr, d);
+ for d in self.tokens.iter_mut() {
+ d.range.0 = manip(d.range.0 as _) as _;
+ d.range.1 = manip(d.range.1 as _) as _;
}
Ok(())
}
@@ -756,7 +744,7 @@ impl TextArea {
self.vo = y - (self.r / 2);
}
}
-
+ #[cold]
pub fn tree_sit<'c>(&self, path: Option<&Path>, cell: &mut Output) {
let language = path
.and_then(|x| LOADER.language_for_filename(x))
@@ -883,6 +871,8 @@ impl TextArea {
// (self.l().max(r) + r - 1) * c
// ];
let lns = self.vo..self.vo + r;
+ let mut tokens = self.tokens.iter();
+ let mut curr: Option<&TokenD> = tokens.next();
for (l, y) in lns.clone().map(self.source_map(_)).zip(lns) {
for (e, x) in l
.coerce()
@@ -897,13 +887,28 @@ impl TextArea {
cells.get((x + self.ho, y)).unwrap().style = match e {
Mapping::Char(_, _, abspos)
if let Some(leg) = leg =>
- self.tokens
- .get(&(abspos as _))
- .map(|x| x.style(leg))
- .unwrap_or(Style::new(
- crate::FG,
- crate::BG,
- )),
+ {
+ if let Some(curr) = curr
+ && (curr.range.0..curr.range.1)
+ .contains(&(abspos as _))
+ {
+ curr.style(leg)
+ } else {
+ while let Some(c) = curr
+ && c.range.0 < abspos as _
+ {
+ curr = tokens.next();
+ }
+ if let Some(curr) = curr
+ && (curr.range.0..curr.range.1)
+ .contains(&(abspos as _))
+ {
+ curr.style(leg)
+ } else {
+ Style::new(crate::FG, crate::BG)
+ }
+ }
+ }
Mapping::Char(..) =>
Style::new(crate::FG, crate::BG),
Mapping::Fake(Marking { .. }, ..) => Style::new(
diff --git a/src/text/semantic_tokens.rs b/src/text/semantic_tokens.rs
index ff8f9e5..33c1eb5 100644
--- a/src/text/semantic_tokens.rs
+++ b/src/text/semantic_tokens.rs
@@ -102,6 +102,7 @@ use crate::text::TextArea;
Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize,
)]
pub struct TokenD {
+ pub range: (u32, u32),
pub ty: u32,
pub modifiers: u32,
}
@@ -178,14 +179,12 @@ impl TextArea {
}) else {
continue;
};
-
- self.tokens.insert(
- x1..x2,
- TokenD {
- ty: t.token_type,
- modifiers: t.token_modifiers_bitset,
- },
- );
+ self.tokens.push(TokenD {
+ range: (x1, x2),
+ ty: t.token_type,
+ modifiers: t.token_modifiers_bitset,
+ });
}
+ // tokens are sorted by definition
}
}