dotfiles

personal dotfiles
git clone anongit@rnpnr.xyz:dotfiles.git
Log | Files | Refs | Feed | Submodules

highlight.lua (1716B)


      1 local M = {
      2 	style_ids = {}
      3 }
      4 
      5 local longest_keyword_length = 0
      6 local lpeg_pattern
      7 vis.events.subscribe(vis.events.INIT, function()
      8 	local keywords = M.keywords
      9 	for tag, style in pairs(keywords) do
     10 		M.style_ids[tag] = vis.ui:style_push(style)
     11 		if #tag > longest_keyword_length then
     12 			longest_keyword_length = #tag
     13 		end
     14 	end
     15 
     16 	local lpeg = vis.lpeg
     17 	-- TODO: can't this be done better?
     18 	local words
     19 	for tag, _ in pairs(keywords) do
     20 		if words then
     21 			words = words + lpeg.P(tag)
     22 		else
     23 			words = lpeg.P(tag)
     24 		end
     25 	end
     26 	if not words then return end
     27 	local cap = (1 - words)^0 * (lpeg.Cp() * words * lpeg.Cp())
     28 	lpeg_pattern = lpeg.Ct(cap * ((1 - words) * cap)^0)
     29 end)
     30 
     31 local get_keywords = function(data)
     32 	local i, kwt, kws = 1, {}, lpeg_pattern:match(data)
     33 	if kws then
     34 		repeat
     35 			local kw = data:sub(kws[i], kws[i + 1] - 1)
     36 			table.insert(kwt, {kw, kws[i] - 1, kws[i + 1] - 2})
     37 			i = i + 2
     38 		until (i > #kws)
     39 	end
     40 	return kwt
     41 end
     42 
     43 local last_data, last_tokens
     44 vis.events.subscribe(vis.events.WIN_HIGHLIGHT, function(win)
     45 	local viewport = win.viewport.bytes
     46 	if not viewport then return end
     47 	local horizon_max = longest_keyword_length
     48 	local horizon     = viewport.start < horizon_max and viewport.start or horizon_max
     49 	local lex_start   = viewport.start - horizon
     50 	viewport.start    = lex_start
     51 
     52 	local data   = win.file:content(viewport)
     53 	local tokens = last_tokens
     54 	if last_data ~= data then
     55 		tokens      = get_keywords(data)
     56 		last_tokens = tokens;
     57 		last_data   = data
     58 	end
     59 
     60 	local style_ids = M.style_ids
     61 	for _, matches in pairs(tokens) do
     62 		local style_id = style_ids[matches[1]]
     63 		if style_id then
     64 			win:style(style_id, lex_start + matches[2], lex_start + matches[3])
     65 		end
     66 	end
     67 end)
     68 
     69 return M