local my_utf8 = require 'my_utf8' local colorize = {} local I = {} colorize.internal = I -- State transitions while colorizing a single line. -- Just for comments and strings. -- Limitation: each fragment gets a uniform color so we can only change color -- at word boundaries. local Next_state = { normal={ {prefix='--[[', target='block_comment'}, -- only single-line for now {prefix='--', target='comment'}, {prefix='"', target='dstring'}, {prefix="'", target='sstring'}, {prefix='[[', target='block_string'}, -- only single line for now }, dstring={ {suffix='"', target='normal'}, }, sstring={ {suffix="'", target='normal'}, }, block_string={ {suffix=']]', target='normal'}, }, block_comment={ {suffix=']]', target='normal'}, }, -- comments are a sink } local Comment_color = {0, 0, 1} local String_color = {0, 0.5, 0.5} local Colors = { normal=Foreground_color, comment=Comment_color, sstring=String_color, dstring=String_color, block_string=String_color, block_comment=Comment_color, } function colorize.configure(comment_color, string_color) Colors.comment = comment_color Colors.block_comment = comment_color Colors.sstring = string_color Colors.dstring = string_color Colors.block_string = string_color end function colorize.reset() Colors.comment = Comment_color Colors.block_comment = Comment_color Colors.sstring = String_color Colors.dstring = String_color Colors.block_string = String_color end -- This part doesn't scale. We parse the entire file on every frame. -- Carousel is intended for small buffers that can be edited comfortably on -- a phone. function colorize.all(editor) editor.colors = {} local current_state = 'normal' for line_index, line in ipairs(editor.lines) do editor.colors[line_index] = {} for pos in my_utf8.chars(line.data) do local offset = my_utf8.offset(line.data, pos) local prefix_match = false if Next_state[current_state] then for _, cand in ipairs(Next_state[current_state]) do if cand.prefix and I.prefix_match(line.data, offset, cand.prefix) then current_state = cand.target prefix_match = true break end end end editor.colors[line_index][pos] = Colors[current_state] if not prefix_match and Next_state[current_state] then for _, cand in ipairs(Next_state[current_state]) do if cand.suffix and I.suffix_match(line.data, offset, cand.suffix) then current_state = cand.target break end end end end if current_state == 'comment' then current_state = 'normal' end -- comments end on newline end end function I.prefix_match(str, offset, prefix) return str:sub(offset, offset+#prefix-1) == prefix end function I.suffix_match(str, offset, suffix) return str:sub(offset-#suffix+1, offset) == suffix end return colorize