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]
|
||||
git = "https://github.com/hecrj/cosmic-text.git"
|
||||
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 syntect::highlighting;
|
||||
use syntect::parsing;
|
||||
use syntect::parsing::{self, SyntaxReference};
|
||||
|
||||
#[derive(Debug, Clone, Hash)]
|
||||
pub struct Settings {
|
||||
|
|
@ -91,13 +91,14 @@ mod highlighter {
|
|||
|
||||
pub struct Highlighter {
|
||||
syntaxes: parsing::SyntaxSet,
|
||||
parser: parsing::ParseState,
|
||||
stack: parsing::ScopeStack,
|
||||
syntax: SyntaxReference,
|
||||
caches: Vec<(parsing::ParseState, parsing::ScopeStack)>,
|
||||
theme: highlighting::Theme,
|
||||
token: String,
|
||||
current_line: usize,
|
||||
}
|
||||
|
||||
const LINES_PER_SNAPSHOT: usize = 50;
|
||||
|
||||
impl highlighter::Highlighter for Highlighter {
|
||||
type Settings = Settings;
|
||||
type Highlight = Highlight;
|
||||
|
|
@ -121,34 +122,53 @@ mod highlighter {
|
|||
.unwrap();
|
||||
|
||||
Highlighter {
|
||||
syntax: syntax.clone(),
|
||||
syntaxes,
|
||||
parser,
|
||||
stack,
|
||||
caches: vec![(parser, stack)],
|
||||
theme,
|
||||
token: settings.token.clone(),
|
||||
current_line: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn change_line(&mut self, _line: usize) {
|
||||
// TODO: Caching
|
||||
let syntax = self
|
||||
.syntaxes
|
||||
.find_syntax_by_token(&self.token)
|
||||
.unwrap_or_else(|| self.syntaxes.find_syntax_plain_text());
|
||||
fn change_line(&mut self, line: usize) {
|
||||
let snapshot = line / LINES_PER_SNAPSHOT;
|
||||
|
||||
self.parser = parsing::ParseState::new(&syntax);
|
||||
self.stack = parsing::ScopeStack::new();
|
||||
self.current_line = 0;
|
||||
if snapshot <= self.caches.len() {
|
||||
self.caches.truncate(snapshot);
|
||||
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<'_> {
|
||||
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;
|
||||
|
||||
let ops = self
|
||||
.parser
|
||||
.parse_line(line, &self.syntaxes)
|
||||
.unwrap_or_default();
|
||||
let (parser, stack) =
|
||||
self.caches.last_mut().expect("Caches must not be empty");
|
||||
|
||||
let ops =
|
||||
parser.parse_line(line, &self.syntaxes).unwrap_or_default();
|
||||
|
||||
let highlighter = highlighting::Highlighter::new(&self.theme);
|
||||
|
||||
Box::new(
|
||||
ScopeRangeIterator {
|
||||
|
|
@ -158,9 +178,7 @@ mod highlighter {
|
|||
last_str_index: 0,
|
||||
}
|
||||
.filter_map(move |(range, scope)| {
|
||||
let highlighter =
|
||||
highlighting::Highlighter::new(&self.theme);
|
||||
let _ = self.stack.apply(&scope);
|
||||
let _ = stack.apply(&scope);
|
||||
|
||||
if range.is_empty() {
|
||||
None
|
||||
|
|
@ -168,8 +186,7 @@ mod highlighter {
|
|||
Some((
|
||||
range,
|
||||
Highlight(
|
||||
highlighter
|
||||
.style_mod_for_stack(&self.stack.scopes),
|
||||
highlighter.style_mod_for_stack(&stack.scopes),
|
||||
),
|
||||
))
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue