okami.mom/albedo
git clone https://git.nkp.pet/okami.mom/albedo
0d0b12c
main
1//! Syntax colors for a whole file, looked up by byte offset. 2 3use arborium:: Highlighter ; 4use arborium_highlight::{ FlatToken , spans_to_flat_tokens}; 5use arborium_theme:: highlights; 6use arborium_theme:: theme::{ Color , Theme }; 7 8/// Which grammar colored the file, or why none did. 9pub enum Language { 10Highlighted ( String ), 11/// Named after the file, but not one of the grammars compiled in. 12Unsupported ( String ), 13/// The grammar exists but could not highlight this file. 14Failed ( String ), 15Unknown , 16} 17 18pub struct Colors { 19tokens : Vec <( FlatToken , Color )>, 20pub foreground : Color , 21pub background : Color , 22pub language : Language , 23} 24 25impl Colors { 26/// Highlights all of `source`, so a range starting inside a comment or a 27/// string is colored as it would be in the whole file. 28pub fn new ( source : & str , language : Option < & str >, theme : & Theme ) ->Colors { 29let foreground = theme. foreground . unwrap_or ( Color :: new ( 0 , 0 , 0 )); 30let background = theme. background . unwrap_or ( Color :: new ( 255 , 255 , 255 )); 31let plain = |language|Colors { 32tokens : Vec :: new (), 33 foreground, 34 background, 35 language, 36}; 37let Some ( name) = languageelse { 38return plain ( Language :: Unknown ); 39}; 40let spans =match Highlighter :: new (). highlight_spans ( name, source) { 41Ok ( spans) => spans, 42Err ( arborium:: Error :: UnsupportedLanguage { ..}) =>{ 43return plain ( Language :: Unsupported ( name. to_string ())); 44} 45Err ( error) =>return plain ( Language :: Failed ( error. to_string ())), 46}; 47let tokens =spans_to_flat_tokens ( source, spans) 48. into_iter () 49. filter_map ( |token|tag_color ( theme, token. tag ). map ( |color|( token, color))) 50. collect (); 51Colors { 52 tokens, 53 foreground, 54 background, 55language : Language :: Highlighted ( name. to_string ()), 56} 57} 58 59/// The token covering each byte from `from` on, for a caller walking forward. 60pub fn cursor ( & self , from : usize ) ->Cursor < ' _ > { 61let index =self 62. tokens 63. partition_point ( |( token, _) |( token. end as usize ) <= from); 64Cursor { 65colors : self , 66 index, 67} 68} 69} 70 71pub struct Cursor < ' a > { 72colors : &' a Colors , 73index : usize , 74} 75 76impl Cursor < ' _ > { 77/// The color at byte `offset`; offsets must not decrease between calls. 78pub fn at ( & mut self , offset : usize ) ->Color { 79let tokens =& self . colors . tokens ; 80while self . index < tokens. len () &&( tokens[ self . index ]. 0 . end as usize ) <= offset{ 81self . index +=1 ; 82} 83match tokens. get ( self . index ) { 84Some (( token, color)) if token. start as usize < = offset =>* color, 85 _ =>self . colors . foreground , 86} 87} 88} 89 90/// A child tag with no color of its own takes its parent's, as the theme's CSS would. 91fn tag_color ( theme : & Theme , tag : & str ) ->Option < Color > { 92let index =( 0 ..highlights:: COUNT ). find ( |& index| highlights:: tag ( index) ==Some ( tag)) ?; 93 theme. style ( index). and_then ( |style| style. fg ). or_else ( ||{ 94let parent = highlights:: HIGHLIGHTS [ index]. parent_tag ; 95( !parent. is_empty ()) 96. then ( ||tag_color ( theme, parent)) 97. flatten () 98}) 99}