Skip to content

Commit 7fe13c0

Browse files
authored
Merge pull request #569 from alexpasmantier/refactor/convenience-highlight-from-previous-state
refactor: add convenience `HighlightLines::from_state` constructor
2 parents fd1a925 + b2811ce commit 7fe13c0

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

src/easy.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,25 @@ impl<'a> HighlightLines<'a> {
8484
HighlightIterator::new(&mut self.highlight_state, &ops[..], line, &self.highlighter);
8585
Ok(iter.collect())
8686
}
87+
88+
/// This starts again from a previous state, useful for highlighting a file incrementally for
89+
/// which you've cached the highlight and parse state.
90+
pub fn from_state(
91+
theme: &'a Theme,
92+
highlight_state: HighlightState,
93+
parse_state: ParseState,
94+
) -> HighlightLines<'a> {
95+
HighlightLines {
96+
highlighter: Highlighter::new(theme),
97+
parse_state,
98+
highlight_state,
99+
}
100+
}
101+
102+
/// Returns the current highlight and parse states, useful for caching and incremental highlighting.
103+
pub fn state(self) -> (HighlightState, ParseState) {
104+
(self.highlight_state, self.parse_state)
105+
}
87106
}
88107

89108
/// Convenience struct containing everything you need to highlight a file
@@ -357,4 +376,38 @@ mod tests {
357376
assert_eq!(all_ops.count(), iterated_ops.len() - 1); // -1 because we want to ignore the NOOP
358377
}
359378
}
379+
380+
#[cfg(all(feature = "default-syntaxes", feature = "default-themes"))]
381+
#[test]
382+
fn can_start_again_from_previous_state() {
383+
let ss = SyntaxSet::load_defaults_nonewlines();
384+
let ts = ThemeSet::load_defaults();
385+
let mut highlighter = HighlightLines::new(
386+
ss.find_syntax_by_extension("py").unwrap(),
387+
&ts.themes["base16-ocean.dark"],
388+
);
389+
390+
let lines = ["\"\"\"", "def foo():", "\"\"\""];
391+
392+
let highlighted_first_line = highlighter
393+
.highlight_line(lines[0], &ss)
394+
.expect("#[cfg(test)]");
395+
396+
let (highlight_state, parse_state) = highlighter.state();
397+
398+
let mut other_highlighter = HighlightLines::from_state(
399+
&ts.themes["base16-ocean.dark"],
400+
highlight_state,
401+
parse_state,
402+
);
403+
404+
let highlighted_second_line = other_highlighter
405+
.highlight_line(lines[1], &ss)
406+
.expect("#[cfg(test)]");
407+
408+
// Check that the second line is highlighted correctly (i.e. as a docstring)
409+
// using the first line's previous state
410+
assert!(highlighted_second_line.len() == 1);
411+
assert!(highlighted_second_line[0].0 == highlighted_first_line[0].0);
412+
}
360413
}

tests/snapshots/public_api__public_api.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@ impl<'a> core::panic::unwind_safe::RefUnwindSafe for syntect::easy::HighlightFil
2626
impl<'a> core::panic::unwind_safe::UnwindSafe for syntect::easy::HighlightFile<'a>
2727
pub struct syntect::easy::HighlightLines<'a>
2828
impl<'a> syntect::easy::HighlightLines<'a>
29+
pub fn syntect::easy::HighlightLines<'a>::from_state(theme: &'a syntect::highlighting::Theme, highlight_state: syntect::highlighting::HighlightState, parse_state: syntect::parsing::ParseState) -> syntect::easy::HighlightLines<'a>
2930
pub fn syntect::easy::HighlightLines<'a>::highlight<'b>(&mut self, line: &'b str, syntax_set: &syntect::parsing::SyntaxSet) -> alloc::vec::Vec<(syntect::highlighting::Style, &'b str)>
3031
pub fn syntect::easy::HighlightLines<'a>::highlight_line<'b>(&mut self, line: &'b str, syntax_set: &syntect::parsing::SyntaxSet) -> core::result::Result<alloc::vec::Vec<(syntect::highlighting::Style, &'b str)>, syntect::Error>
3132
pub fn syntect::easy::HighlightLines<'a>::new(syntax: &syntect::parsing::SyntaxReference, theme: &'a syntect::highlighting::Theme) -> syntect::easy::HighlightLines<'a>
33+
pub fn syntect::easy::HighlightLines<'a>::state(self) -> (syntect::highlighting::HighlightState, syntect::parsing::ParseState)
3234
impl<'a> !core::marker::Send for syntect::easy::HighlightLines<'a>
3335
impl<'a> !core::marker::Sync for syntect::easy::HighlightLines<'a>
3436
impl<'a> core::marker::Unpin for syntect::easy::HighlightLines<'a>

0 commit comments

Comments
 (0)