86 lines
2.0 KiB
Lua
86 lines
2.0 KiB
Lua
|
local core = require "core"
|
||
|
local syntax = require "core.syntax"
|
||
|
local config = require "core.config"
|
||
|
local tokenizer = require "core.tokenizer"
|
||
|
local Object = require "core.object"
|
||
|
|
||
|
|
||
|
local Highlighter = Object:extend()
|
||
|
|
||
|
|
||
|
function Highlighter:new(doc)
|
||
|
self.doc = doc
|
||
|
self:reset_syntax()
|
||
|
|
||
|
-- init incremental syntax highlighting
|
||
|
core.add_thread(function()
|
||
|
while true do
|
||
|
if self.last_valid_line > self.max_wanted_line then
|
||
|
self.max_wanted_line = 0
|
||
|
coroutine.yield(1 / config.fps)
|
||
|
|
||
|
else
|
||
|
local max = math.min(self.last_valid_line + 40, self.max_wanted_line)
|
||
|
|
||
|
for i = self.last_valid_line, max do
|
||
|
local state = (i > 1) and self.lines[i - 1].state
|
||
|
local line = self.lines[i]
|
||
|
if not (line and line.init_state == state) then
|
||
|
self.lines[i] = self:tokenize_line(i, state)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
self.last_valid_line = max + 1
|
||
|
core.redraw = true
|
||
|
coroutine.yield()
|
||
|
end
|
||
|
end
|
||
|
end, self)
|
||
|
end
|
||
|
|
||
|
|
||
|
function Highlighter:reset_syntax()
|
||
|
local syn = syntax.get(self.doc.filename or "")
|
||
|
if self.syntax ~= syn then
|
||
|
self.syntax = syn
|
||
|
self.lines = {}
|
||
|
self.last_valid_line = 1
|
||
|
self.max_wanted_line = 0
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
function Highlighter:invalidate(idx)
|
||
|
self.last_valid_line = idx
|
||
|
end
|
||
|
|
||
|
|
||
|
function Highlighter:tokenize_line(idx, state)
|
||
|
local line = {}
|
||
|
line.init_state = state
|
||
|
line.text = self.doc.lines[idx]
|
||
|
line.tokens, line.state = tokenizer.tokenize(self.syntax, line.text, state)
|
||
|
return line
|
||
|
end
|
||
|
|
||
|
|
||
|
function Highlighter:get_line(idx)
|
||
|
local line = self.lines[idx]
|
||
|
if not line or line.text ~= self.doc.lines[idx] then
|
||
|
local prev = self.lines[idx - 1]
|
||
|
line = self:tokenize_line(idx, prev and prev.state)
|
||
|
self.lines[idx] = line
|
||
|
self.last_valid_line = math.min(self.last_valid_line, idx)
|
||
|
end
|
||
|
self.max_wanted_line = math.max(self.max_wanted_line, idx)
|
||
|
return line
|
||
|
end
|
||
|
|
||
|
|
||
|
function Highlighter:each_token(idx)
|
||
|
return tokenizer.each_token(self:get_line(idx).tokens)
|
||
|
end
|
||
|
|
||
|
|
||
|
return Highlighter
|