forked from mars/breed
More efficient scope style lookups
This commit is contained in:
parent
b351dbbcbb
commit
814d4b116b
|
@ -150,8 +150,11 @@ impl Buffer {
|
|||
let mut parser = self.parser.clone();
|
||||
let mut line_buf = String::new();
|
||||
let mut stack = ScopeStack::new();
|
||||
let mut style_stack = Vec::<Style>::new();
|
||||
let mut styled_buf = Vec::new();
|
||||
|
||||
let mut style_stack = Vec::<Style>::new();
|
||||
style_stack.push(Default::default());
|
||||
|
||||
for line in self.text.lines() {
|
||||
// display line to a pre-allocated buffer for fast parsing
|
||||
line_buf.clear();
|
||||
|
@ -169,9 +172,10 @@ impl Buffer {
|
|||
stack
|
||||
.apply_with_hook(&op, |op, _scopes| match op {
|
||||
BasicScopeStackOp::Push(scope) => {
|
||||
let scope = scope.build_string();
|
||||
let style = styles.get_scope(&scope);
|
||||
style_stack.push(style);
|
||||
let style = styles.get_syntect_scope(&scope);
|
||||
let mut top_style = style_stack.last().unwrap().clone();
|
||||
top_style.apply(style);
|
||||
style_stack.push(top_style);
|
||||
}
|
||||
BasicScopeStackOp::Pop => {
|
||||
style_stack.pop();
|
||||
|
|
52
src/theme.rs
52
src/theme.rs
|
@ -21,6 +21,7 @@ use std::{collections::HashMap, fmt::Display};
|
|||
|
||||
use crossterm::style::Color;
|
||||
use crossterm::QueueableCommand;
|
||||
use syntect::parsing::Scope;
|
||||
use toml::{map::Map, Value};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
|
@ -34,6 +35,9 @@ pub struct StyleStore {
|
|||
/// Maps named scopes to indices.
|
||||
scopes: HashMap<String, usize>,
|
||||
|
||||
/// Maps syntect scopes to indices.
|
||||
syntect_scopes: HashMap<Scope, usize>,
|
||||
|
||||
/// The style data store.
|
||||
styles: Vec<Style>,
|
||||
}
|
||||
|
@ -45,41 +49,59 @@ impl StyleStore {
|
|||
theme,
|
||||
generation: 0,
|
||||
scopes: HashMap::new(),
|
||||
syntect_scopes: HashMap::new(),
|
||||
styles: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a scope to this store and returns its index. Reuses indices for existing scopes.
|
||||
pub fn add_scope(&mut self, scope: &str) -> usize {
|
||||
let style = self.theme.get_scope_style(scope);
|
||||
|
||||
if let Some(style_idx) = self.scopes.get(scope).copied() {
|
||||
let old_style = self
|
||||
.styles
|
||||
.get_mut(style_idx)
|
||||
.expect("StyleStore index is out-of-bounds");
|
||||
let _ = std::mem::replace(old_style, style);
|
||||
style_idx
|
||||
if let Some(style_idx) = self.scopes.get(scope) {
|
||||
*style_idx
|
||||
} else {
|
||||
let style_idx = self.styles.len();
|
||||
let style = self.theme.get_scope_style(scope);
|
||||
self.styles.push(style);
|
||||
self.scopes.insert(scope.to_string(), style_idx);
|
||||
|
||||
if let Ok(scope) = Scope::new(scope) {
|
||||
self.syntect_scopes.insert(scope, style_idx);
|
||||
}
|
||||
|
||||
style_idx
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the style for a scope by name.
|
||||
pub fn get_scope(&mut self, scope: &str) -> Style {
|
||||
pub fn get_scope(&mut self, scope: &str) -> &Style {
|
||||
let idx = self.add_scope(scope);
|
||||
self.get_style(idx)
|
||||
}
|
||||
|
||||
/// Adds a Syntect [Scope] and returns its index. Resues indices for existing scopes.
|
||||
pub fn add_syntect_scope(&mut self, scope: &Scope) -> usize {
|
||||
if let Some(style_idx) = self.syntect_scopes.get(scope) {
|
||||
*style_idx
|
||||
} else {
|
||||
let style_idx = self.styles.len();
|
||||
let scope_str = scope.build_string();
|
||||
let style = self.theme.get_scope_style(&scope_str);
|
||||
self.styles.push(style);
|
||||
self.scopes.insert(scope_str, style_idx);
|
||||
self.syntect_scopes.insert(*scope, style_idx);
|
||||
style_idx
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the style for a Syntect [Scope].
|
||||
pub fn get_syntect_scope(&mut self, scope: &Scope) -> &Style {
|
||||
let idx = self.add_syntect_scope(scope);
|
||||
self.get_style(idx)
|
||||
}
|
||||
|
||||
/// Gets the style for a scope index. Panics if out-of-bounds.
|
||||
pub fn get_style(&self, index: usize) -> Style {
|
||||
self.styles
|
||||
.get(index)
|
||||
.expect("StyleStore is out-of-bounds")
|
||||
.to_owned()
|
||||
pub fn get_style(&self, index: usize) -> &Style {
|
||||
self.styles.get(index).expect("StyleStore is out-of-bounds")
|
||||
}
|
||||
|
||||
/// The current generation of the store. Increments every update.
|
||||
|
|
Reference in New Issue