@@ -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}
0 commit comments