Skip to content

Commit

Permalink
Implement syntax highlighting cache in editor example
Browse files Browse the repository at this point in the history
  • Loading branch information
hecrj committed Sep 17, 2023
1 parent 2897986 commit 790c0da
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 25 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
67 changes: 42 additions & 25 deletions examples/editor/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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;
Expand All @@ -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;

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.parser = parsing::ParseState::new(&syntax);
self.stack = parsing::ScopeStack::new();
self.current_line = 0;
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 {
Expand All @@ -158,18 +178,15 @@ 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
} else {
Some((
range,
Highlight(
highlighter
.style_mod_for_stack(&self.stack.scopes),
highlighter.style_mod_for_stack(&stack.scopes),
),
))
}
Expand Down

0 comments on commit 790c0da

Please sign in to comment.