-
Notifications
You must be signed in to change notification settings - Fork 0
/
init.lua
175 lines (147 loc) · 3.79 KB
/
init.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
local M = {}
M.patterns = {}
local styleIdStack = {}
local styleIdIterator = function()
local i = 0
local MAX_STYLE_ID = 64
return function()
i = i + 1
if i <= MAX_STYLE_ID then return i end
return nil
end
end
local initStyleIds = function()
styleIdStack = {}
for i in styleIdIterator() do
table.insert(styleIdStack, i)
end
end
initStyleIds()
local pattern_iterator = function(pattern, content)
local init = 1
return function()
local from, ends = string.find(content, pattern, init)
if from == nil then return nil end
init = ends + 1
return from, ends
end
end
-- e.g. pattern = 'foo'
local valid_pattern = function(pattern)
if not pattern then
return false
end
local ok, result, finish = pcall(string.find, '', pattern)
if not ok then
return false
end
return true
end
-- e.g. style = 'fore:red,back:blue,bold'
local valid_style = function(style)
-- TODO improve style validation
if not style then
return false
end
return true
end
local on_win_highlight = function(win)
local content = win.file:content(win.viewport.bytes)
for pattern, data in pairs(M.patterns) do
if data.hideOnInsert and vis.mode == vis.modes.INSERT then
goto continue
end
for from, ends in pattern_iterator(pattern, content) do
local offset = win.viewport.bytes.start
local start = from - 1 + offset
local finish = ends - 1 + offset
if not data.style then
win:style(win.STYLE_CURSOR, start, finish)
else
win:style(data.styleId, start, finish)
end
if ends >= win.viewport.bytes.finish then
break
end
end
::continue::
end
end
local define_styles_for_all_windows = function()
for pattern, data in pairs(M.patterns) do
if not data.style then
goto continue
end
if not data.styleId then
data.styleId = table.remove(styleIdStack, 1)
table.insert(styleIdStack, data.styleId)
end
for win in vis:windows() do
if win:style_define(data.styleId, data.style) then
-- SUCCESS
end
end
::continue::
end
end
local on_win_open = function(win)
define_styles_for_all_windows()
end
local hi_command = function(argv, force, win, selection, range)
local pattern = argv[1]
local style = argv[2]
if not valid_pattern(pattern) then
vis:info('invalid pattern')
return
end
if not valid_style(style) then
-- vis:info('missing style - e.g. fore:red,back:blue,bold')
-- return
-- let's just use default style win.STYLE_CURSOR
end
M.patterns[pattern] = { style = style }
define_styles_for_all_windows()
return true
end
local hi_ls_command = function(argv, force, win, selection, range)
local t = {}
table.insert(t, 'patterns:')
for pattern, data in pairs(M.patterns) do
local pattern_escaped = pattern:gsub('\n', '\\n')
local style_str = ''
if data.style then
style_str = data.style
elseif data.styleId then
style_str = 'id ' .. data.styleId
end
table.insert(t, '\'' .. pattern_escaped .. '\' - ' .. style_str)
end
local s = table.concat(t, '\n')
vis:message(s)
return true
end
local hi_clear_command = function(argv, force, win, selection, range)
M.patterns = {}
initStyleIds()
vis:info 'cleared all patterns'
return true
end
local hi_rm_command = function(argv, force, win, selection, range)
local pattern = argv[1]
if not pattern then return end
local data = M.patterns[pattern]
if data and data.styleId and data.styleId ~= win.STYLE_CURSOR then
-- return styleId for reuse
table.insert(styleIdStack, data.styleId)
end
M.patterns[pattern] = nil
vis:info('pattern \"' .. pattern .. '\" removed')
return true
end
vis.events.subscribe(vis.events.WIN_HIGHLIGHT, on_win_highlight)
vis.events.subscribe(vis.events.WIN_OPEN, on_win_open)
vis:command_register('hi', hi_command)
vis:command_register('hi-ls', hi_ls_command)
vis:command_register('hi-clear', hi_clear_command)
vis:command_register('hi-rm', hi_rm_command)
return M