Template repo for tiny cross-platform apps that can be modified on phone, tablet or computer.
1local my_utf8 = require 'my_utf8'
2
3local colorize = {}
4
5local I = {}
6colorize.internal = I
7
8-- State transitions while colorizing a single line.
9-- Just for comments and strings.
10-- Limitation: each fragment gets a uniform color so we can only change color
11-- at word boundaries.
12local Next_state = {
13 normal={
14 {prefix='--[[', target='block_comment'}, -- only single-line for now
15 {prefix='--', target='comment'},
16 {prefix='"', target='dstring'},
17 {prefix="'", target='sstring'},
18 {prefix='[[', target='block_string'}, -- only single line for now
19 },
20 dstring={
21 {suffix='"', target='normal'},
22 },
23 sstring={
24 {suffix="'", target='normal'},
25 },
26 block_string={
27 {suffix=']]', target='normal'},
28 },
29 block_comment={
30 {suffix=']]', target='normal'},
31 },
32 -- comments are a sink
33}
34
35local Comment_color = {0, 0, 1}
36local String_color = {0, 0.5, 0.5}
37
38local Colors = {
39 normal=Foreground_color,
40 comment=Comment_color,
41 sstring=String_color,
42 dstring=String_color,
43 block_string=String_color,
44 block_comment=Comment_color,
45}
46
47function colorize.configure(comment_color, string_color)
48 Colors.comment = comment_color
49 Colors.block_comment = comment_color
50 Colors.sstring = string_color
51 Colors.dstring = string_color
52 Colors.block_string = string_color
53end
54
55function colorize.reset()
56 Colors.comment = Comment_color
57 Colors.block_comment = Comment_color
58 Colors.sstring = String_color
59 Colors.dstring = String_color
60 Colors.block_string = String_color
61end
62
63-- This part doesn't scale. We parse the entire file on every frame.
64-- Carousel is intended for small buffers that can be edited comfortably on
65-- a phone.
66function colorize.all(editor)
67 editor.colors = {}
68 local current_state = 'normal'
69 for line_index, line in ipairs(editor.lines) do
70 editor.colors[line_index] = {}
71 for pos in my_utf8.chars(line.data) do
72 local offset = my_utf8.offset(line.data, pos)
73 local prefix_match = false
74 if Next_state[current_state] then
75 for _, cand in ipairs(Next_state[current_state]) do
76 if cand.prefix and I.prefix_match(line.data, offset, cand.prefix) then
77 current_state = cand.target
78 prefix_match = true
79 break
80 end
81 end
82 end
83 editor.colors[line_index][pos] = Colors[current_state]
84 if not prefix_match and Next_state[current_state] then
85 for _, cand in ipairs(Next_state[current_state]) do
86 if cand.suffix and I.suffix_match(line.data, offset, cand.suffix) then
87 current_state = cand.target
88 break
89 end
90 end
91 end
92 end
93 if current_state == 'comment' then current_state = 'normal' end -- comments end on newline
94 end
95end
96
97function I.prefix_match(str, offset, prefix)
98 return str:sub(offset, offset+#prefix-1) == prefix
99end
100
101function I.suffix_match(str, offset, suffix)
102 return str:sub(offset-#suffix+1, offset) == suffix
103end
104
105return colorize