Cache syntax highlighting results
This commit is contained in:
parent
f85223b376
commit
1e1164f4b2
2 changed files with 73 additions and 18 deletions
|
|
@ -1,12 +1,32 @@
|
||||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
|
||||||
use cosmic_text::{Attrs, AttrsList, Color, Family, FontSystem, Style, SwashCache,
|
use cosmic_text::{
|
||||||
TextAction, TextBuffer, TextMetrics, Weight};
|
Attrs,
|
||||||
|
AttrsList,
|
||||||
|
Color,
|
||||||
|
Family,
|
||||||
|
FontSystem,
|
||||||
|
Style,
|
||||||
|
SwashCache,
|
||||||
|
TextAction,
|
||||||
|
TextBuffer,
|
||||||
|
TextMetrics,
|
||||||
|
Weight
|
||||||
|
};
|
||||||
use orbclient::{EventOption, Renderer, Window, WindowFlag};
|
use orbclient::{EventOption, Renderer, Window, WindowFlag};
|
||||||
use std::{env, fs, process, time::Instant};
|
use std::{env, fs, process, time::Instant};
|
||||||
use syntect::easy::HighlightLines;
|
use syntect::highlighting::{
|
||||||
use syntect::parsing::SyntaxSet;
|
FontStyle,
|
||||||
use syntect::highlighting::{ThemeSet, FontStyle, Style as SyntectStyle};
|
Highlighter,
|
||||||
|
HighlightState,
|
||||||
|
RangedHighlightIterator,
|
||||||
|
ThemeSet,
|
||||||
|
};
|
||||||
|
use syntect::parsing::{
|
||||||
|
ParseState,
|
||||||
|
ScopeStack,
|
||||||
|
SyntaxSet,
|
||||||
|
};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
|
|
@ -74,6 +94,7 @@ fn main() {
|
||||||
let ps = SyntaxSet::load_defaults_nonewlines();
|
let ps = SyntaxSet::load_defaults_nonewlines();
|
||||||
let ts = ThemeSet::load_defaults();
|
let ts = ThemeSet::load_defaults();
|
||||||
let theme = &ts.themes["base16-eighties.dark"];
|
let theme = &ts.themes["base16-eighties.dark"];
|
||||||
|
let highlighter = Highlighter::new(theme);
|
||||||
|
|
||||||
if let Some(background) = theme.settings.background {
|
if let Some(background) = theme.settings.background {
|
||||||
bg_color = orbclient::Color::rgba(
|
bg_color = orbclient::Color::rgba(
|
||||||
|
|
@ -109,7 +130,8 @@ fn main() {
|
||||||
|
|
||||||
let mut swash_cache = SwashCache::new(&font_system);
|
let mut swash_cache = SwashCache::new(&font_system);
|
||||||
|
|
||||||
//TODO: make window not async?
|
let mut syntax_cache = Vec::<(ParseState, HighlightState)>::new();
|
||||||
|
|
||||||
let mut rehighlight = true;
|
let mut rehighlight = true;
|
||||||
let mut mouse_x = -1;
|
let mut mouse_x = -1;
|
||||||
let mut mouse_y = -1;
|
let mut mouse_y = -1;
|
||||||
|
|
@ -118,20 +140,34 @@ fn main() {
|
||||||
if rehighlight {
|
if rehighlight {
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
|
|
||||||
let mut h = HighlightLines::new(syntax, &theme);
|
for line_i in 0..buffer.lines.len() {
|
||||||
for line in buffer.lines.iter_mut() {
|
let line = &mut buffer.lines[line_i];
|
||||||
let ranges: Vec<(SyntectStyle, &str)> = h.highlight_line(
|
if ! line.is_reset() && line_i < syntax_cache.len() {
|
||||||
line.text(),
|
continue;
|
||||||
&ps
|
}
|
||||||
).unwrap();
|
|
||||||
|
let (mut parse_state, mut highlight_state) = if line_i > 0 && line_i <= syntax_cache.len() {
|
||||||
|
syntax_cache[line_i - 1].clone()
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
ParseState::new(syntax),
|
||||||
|
HighlightState::new(&highlighter, ScopeStack::new())
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
let ops = parse_state.parse_line(line.text(), &ps).unwrap();
|
||||||
|
let ranges = RangedHighlightIterator::new(
|
||||||
|
&mut highlight_state,
|
||||||
|
&ops,
|
||||||
|
line.text(),
|
||||||
|
&highlighter,
|
||||||
|
);
|
||||||
|
|
||||||
let mut start = 0;
|
|
||||||
let mut attrs_list = AttrsList::new(attrs);
|
let mut attrs_list = AttrsList::new(attrs);
|
||||||
for (style, string) in ranges.iter() {
|
for (style, _, range) in ranges {
|
||||||
let end = start + string.len();
|
|
||||||
attrs_list.add_span(
|
attrs_list.add_span(
|
||||||
start,
|
range.start,
|
||||||
end,
|
range.end,
|
||||||
attrs
|
attrs
|
||||||
.color(Color::rgba(
|
.color(Color::rgba(
|
||||||
style.foreground.r,
|
style.foreground.r,
|
||||||
|
|
@ -152,15 +188,30 @@ fn main() {
|
||||||
})
|
})
|
||||||
//TODO: underline
|
//TODO: underline
|
||||||
);
|
);
|
||||||
start = end;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if attrs_list != line.attrs_list {
|
if attrs_list != line.attrs_list {
|
||||||
line.attrs_list = attrs_list;
|
line.attrs_list = attrs_list;
|
||||||
line.reset();
|
line.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: efficiently do syntax highlighting without having to shape whole buffer
|
||||||
|
line.shape(&font_system);
|
||||||
|
|
||||||
|
let cache_item = (parse_state.clone(), highlight_state.clone());
|
||||||
|
if line_i < syntax_cache.len() {
|
||||||
|
if syntax_cache[line_i] != cache_item {
|
||||||
|
syntax_cache[line_i] = cache_item;
|
||||||
|
if line_i + 1 < buffer.lines.len() {
|
||||||
|
buffer.lines[line_i + 1].reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
syntax_cache.push(cache_item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buffer.redraw = true;
|
||||||
rehighlight = false;
|
rehighlight = false;
|
||||||
|
|
||||||
log::info!("Syntax highlighted in {:?}", now.elapsed());
|
log::info!("Syntax highlighted in {:?}", now.elapsed());
|
||||||
|
|
|
||||||
|
|
@ -201,6 +201,10 @@ impl<'a> TextBufferLine<'a> {
|
||||||
self.layout_opt = None;
|
self.layout_opt = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_reset(&self) -> bool {
|
||||||
|
self.shape_opt.is_none()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn shape(&mut self, font_system: &'a FontSystem<'a>) -> &ShapeLine {
|
pub fn shape(&mut self, font_system: &'a FontSystem<'a>) -> &ShapeLine {
|
||||||
if self.shape_opt.is_none() {
|
if self.shape_opt.is_none() {
|
||||||
self.shape_opt = Some(ShapeLine::new(font_system, &self.text, &self.attrs_list));
|
self.shape_opt = Some(ShapeLine::new(font_system, &self.text, &self.attrs_list));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue