1- use super :: Chunk ;
1+ use super :: { Chunk , Tag } ;
22use anyhow:: { Context , Result } ;
33use tree_sitter_highlight:: { HighlightConfiguration , HighlightEvent , Highlighter } ;
44
55pub fn highlight (
66 language : tree_sitter:: Language ,
77 highlights_query : & str ,
8- tags : & [ & ' static str ] ,
8+ names : & [ & str ] ,
9+ tags : & [ Tag ] ,
910 input : & [ u8 ] ,
1011) -> Result < Vec < Chunk > > {
1112 let mut highlighter = Highlighter :: new ( ) ;
1213 let mut config = HighlightConfiguration :: new ( language, "" , highlights_query, "" , "" )
1314 . context ( "failed to create highlight configuration" ) ?;
14- config. configure ( tags ) ;
15+ config. configure ( names ) ;
1516
1617 let highlights = highlighter
1718 . highlight ( & config, input, None , |_| None )
1819 . context ( "failed to highlight" ) ?;
1920
2021 let mut chunks: Vec < Chunk > = Vec :: new ( ) ;
21- let mut tag: Option < & ' static str > = None ;
22+ let mut tag: Tag = Tag :: Text ;
2223
2324 for event in highlights {
2425 let event = event. context ( "highlighter failure" ) ?;
2526 match event {
2627 HighlightEvent :: Source { start, end } => {
27- let contents = & input[ start..end] ;
28- let tag_str = tag. unwrap_or ( "" ) ;
29-
28+ let contents = String :: from_utf8_lossy ( & input[ start..end] ) ;
3029 match chunks. last_mut ( ) {
31- Some ( x) if x. 0 == tag_str => {
32- x. 1 . push_str ( & String :: from_utf8_lossy ( contents) ) ;
30+ Some ( x) if x. 0 == tag || contents . trim_ascii ( ) . is_empty ( ) => {
31+ x. 1 . push_str ( & contents) ;
3332 }
34- _ => chunks. push (
35- ( tag_str, String :: from_utf8_lossy ( contents) . to_string ( ) )
36- ) ,
33+ _ => chunks. push ( ( tag, contents. to_string ( ) ) ) ,
3734 }
3835 }
3936 HighlightEvent :: HighlightStart ( s) => {
40- tag = Some ( tags[ s. 0 ] ) ;
37+ tag = tags[ s. 0 ] ;
4138 }
4239 HighlightEvent :: HighlightEnd => {
43- tag = None ;
40+ tag = Tag :: Text ;
4441 }
4542 }
4643 }
4744 Ok ( chunks)
4845}
4946
5047#[ cfg( test) ]
51- pub ( super ) fn test_tags_ok (
48+ pub ( super ) fn test_names_ok (
5249 language : tree_sitter:: Language ,
5350 highlights_query : & str ,
54- tags : & [ & ' static str ] ,
51+ names : & [ & str ] ,
52+ tags : & [ Tag ] ,
5553) {
54+ assert_eq ! ( names. len( ) , tags. len( ) ) ;
5655 let config = HighlightConfiguration :: new ( language, "" , highlights_query, "" , "" ) . unwrap ( ) ;
57- for & tag in tags {
56+ for & tag in names {
5857 assert ! (
5958 config. names( ) . iter( ) . any( |name| name. contains( tag) ) ,
6059 "Invalid tag: {},\n Allowed tags: {:?}" ,
@@ -63,3 +62,39 @@ pub(super) fn test_tags_ok(
6362 ) ;
6463 }
6564}
65+
66+ #[ allow( unused) ]
67+ #[ cfg( test) ]
68+ pub ( super ) fn debug ( language : tree_sitter:: Language , highlights_query : & str , input : & [ u8 ] ) {
69+ let mut highlighter = Highlighter :: new ( ) ;
70+ let mut config = HighlightConfiguration :: new ( language, "" , highlights_query, "" , "" ) . unwrap ( ) ;
71+ let names = config
72+ . names ( )
73+ . iter ( )
74+ . map ( |name| name. to_string ( ) )
75+ . collect :: < Vec < _ > > ( ) ;
76+ config. configure ( & names) ;
77+ let highlights = highlighter
78+ . highlight ( & config, input, None , |_| None )
79+ . unwrap ( ) ;
80+
81+ let mut tag: & str = "" ;
82+ for event in highlights {
83+ match event. unwrap ( ) {
84+ HighlightEvent :: Source { start, end } => {
85+ let contents = & input[ start..end] ;
86+ println ! (
87+ "{}: {:?}" ,
88+ tag,
89+ String :: from_utf8_lossy( contents) . to_string( ) . as_str( )
90+ ) ;
91+ }
92+ HighlightEvent :: HighlightStart ( s) => {
93+ tag = & names[ s. 0 ] ;
94+ }
95+ HighlightEvent :: HighlightEnd => {
96+ tag = "" ;
97+ }
98+ }
99+ }
100+ }
0 commit comments