Implement syntax highlighting cache in editor example
This commit is contained in:
parent
2897986f2d
commit
790c0dabcf
2 changed files with 46 additions and 25 deletions
|
|
@ -155,3 +155,7 @@ winit = { git = "https://github.com/iced-rs/winit.git", rev = "c52db2045d0a2f1b8
|
||||||
[patch.crates-io.cosmic-text]
|
[patch.crates-io.cosmic-text]
|
||||||
git = "https://github.com/hecrj/cosmic-text.git"
|
git = "https://github.com/hecrj/cosmic-text.git"
|
||||||
rev = "cb83458e7d0b84ef37c5beb72dda5046d7d343a6"
|
rev = "cb83458e7d0b84ef37c5beb72dda5046d7d343a6"
|
||||||
|
|
||||||
|
[patch.crates-io.rangemap]
|
||||||
|
git = "https://github.com/hecrj/rangemap.git"
|
||||||
|
branch = "fix/partial-eq"
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ mod highlighter {
|
||||||
|
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use syntect::highlighting;
|
use syntect::highlighting;
|
||||||
use syntect::parsing;
|
use syntect::parsing::{self, SyntaxReference};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Hash)]
|
#[derive(Debug, Clone, Hash)]
|
||||||
pub struct Settings {
|
pub struct Settings {
|
||||||
|
|
@ -91,13 +91,14 @@ mod highlighter {
|
||||||
|
|
||||||
pub struct Highlighter {
|
pub struct Highlighter {
|
||||||
syntaxes: parsing::SyntaxSet,
|
syntaxes: parsing::SyntaxSet,
|
||||||
parser: parsing::ParseState,
|
syntax: SyntaxReference,
|
||||||
stack: parsing::ScopeStack,
|
caches: Vec<(parsing::ParseState, parsing::ScopeStack)>,
|
||||||
theme: highlighting::Theme,
|
theme: highlighting::Theme,
|
||||||
token: String,
|
|
||||||
current_line: usize,
|
current_line: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const LINES_PER_SNAPSHOT: usize = 50;
|
||||||
|
|
||||||
impl highlighter::Highlighter for Highlighter {
|
impl highlighter::Highlighter for Highlighter {
|
||||||
type Settings = Settings;
|
type Settings = Settings;
|
||||||
type Highlight = Highlight;
|
type Highlight = Highlight;
|
||||||
|
|
@ -121,34 +122,53 @@ mod highlighter {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
Highlighter {
|
Highlighter {
|
||||||
|
syntax: syntax.clone(),
|
||||||
syntaxes,
|
syntaxes,
|
||||||
parser,
|
caches: vec![(parser, stack)],
|
||||||
stack,
|
|
||||||
theme,
|
theme,
|
||||||
token: settings.token.clone(),
|
|
||||||
current_line: 0,
|
current_line: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change_line(&mut self, _line: usize) {
|
fn change_line(&mut self, line: usize) {
|
||||||
// TODO: Caching
|
let snapshot = line / LINES_PER_SNAPSHOT;
|
||||||
let syntax = self
|
|
||||||
.syntaxes
|
|
||||||
.find_syntax_by_token(&self.token)
|
|
||||||
.unwrap_or_else(|| self.syntaxes.find_syntax_plain_text());
|
|
||||||
|
|
||||||
self.parser = parsing::ParseState::new(&syntax);
|
if snapshot <= self.caches.len() {
|
||||||
self.stack = parsing::ScopeStack::new();
|
self.caches.truncate(snapshot);
|
||||||
self.current_line = 0;
|
self.current_line = snapshot * LINES_PER_SNAPSHOT;
|
||||||
|
} else {
|
||||||
|
self.caches.truncate(1);
|
||||||
|
self.current_line = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (parser, stack) =
|
||||||
|
self.caches.last().cloned().unwrap_or_else(|| {
|
||||||
|
(
|
||||||
|
parsing::ParseState::new(&self.syntax),
|
||||||
|
parsing::ScopeStack::new(),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
self.caches.push((parser, stack));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn highlight_line(&mut self, line: &str) -> Self::Iterator<'_> {
|
fn highlight_line(&mut self, line: &str) -> Self::Iterator<'_> {
|
||||||
|
if self.current_line / LINES_PER_SNAPSHOT >= self.caches.len() {
|
||||||
|
let (parser, stack) =
|
||||||
|
self.caches.last().expect("Caches must not be empty");
|
||||||
|
|
||||||
|
self.caches.push((parser.clone(), stack.clone()));
|
||||||
|
}
|
||||||
|
|
||||||
self.current_line += 1;
|
self.current_line += 1;
|
||||||
|
|
||||||
let ops = self
|
let (parser, stack) =
|
||||||
.parser
|
self.caches.last_mut().expect("Caches must not be empty");
|
||||||
.parse_line(line, &self.syntaxes)
|
|
||||||
.unwrap_or_default();
|
let ops =
|
||||||
|
parser.parse_line(line, &self.syntaxes).unwrap_or_default();
|
||||||
|
|
||||||
|
let highlighter = highlighting::Highlighter::new(&self.theme);
|
||||||
|
|
||||||
Box::new(
|
Box::new(
|
||||||
ScopeRangeIterator {
|
ScopeRangeIterator {
|
||||||
|
|
@ -158,9 +178,7 @@ mod highlighter {
|
||||||
last_str_index: 0,
|
last_str_index: 0,
|
||||||
}
|
}
|
||||||
.filter_map(move |(range, scope)| {
|
.filter_map(move |(range, scope)| {
|
||||||
let highlighter =
|
let _ = stack.apply(&scope);
|
||||||
highlighting::Highlighter::new(&self.theme);
|
|
||||||
let _ = self.stack.apply(&scope);
|
|
||||||
|
|
||||||
if range.is_empty() {
|
if range.is_empty() {
|
||||||
None
|
None
|
||||||
|
|
@ -168,8 +186,7 @@ mod highlighter {
|
||||||
Some((
|
Some((
|
||||||
range,
|
range,
|
||||||
Highlight(
|
Highlight(
|
||||||
highlighter
|
highlighter.style_mod_for_stack(&stack.scopes),
|
||||||
.style_mod_for_stack(&self.stack.scopes),
|
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue