dotfiles

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

Commit: 8ff627af107b29a39006378f2e20c690fdbc69b6
Parent: 04a1ab9d3b20786cd0e461e3435c792fd7d87d81
Author: Randy Palamar
Date:   Mon, 15 Jun 2026 06:19:27 -0600

vis: highlight: use updated style_push API

Diffstat:
M.config/vis/highlight.lua | 152+++++++++++++++++++++++++++----------------------------------------------------
1 file changed, 52 insertions(+), 100 deletions(-)

diff --git a/.config/vis/highlight.lua b/.config/vis/highlight.lua @@ -1,117 +1,69 @@ -local M = {} +local M = { + style_ids = {} +} +local longest_keyword_length = 0 local lpeg_pattern -local get_keywords = function(win, range_or_text) - if not lpeg_pattern then - local lpeg = vis.lpeg - local keywords = M.keywords - - -- TODO: can't this be done better? - local words - for tag, _ in pairs(keywords) do - if words then - words = words + lpeg.P(tag) - else - words = lpeg.P(tag) - end +vis.events.subscribe(vis.events.INIT, function() + local keywords = M.keywords + for tag, style in pairs(keywords) do + M.style_ids[tag] = vis.ui:style_push(style) + if #tag > longest_keyword_length then + longest_keyword_length = #tag end - if not words then return end - local cap = (1 - words)^0 * (lpeg.Cp() * words * lpeg.Cp()) - lpeg_pattern = lpeg.Ct(cap * ((1 - words) * cap)^0) end - local txt = range_or_text - if type(range_or_text) == 'table' then - txt = win.file:content(range_or_text) + local lpeg = vis.lpeg + -- TODO: can't this be done better? + local words + for tag, _ in pairs(keywords) do + if words then + words = words + lpeg.P(tag) + else + words = lpeg.P(tag) + end end + if not words then return end + local cap = (1 - words)^0 * (lpeg.Cp() * words * lpeg.Cp()) + lpeg_pattern = lpeg.Ct(cap * ((1 - words) * cap)^0) +end) - local kws = lpeg_pattern:match(txt) - if not kws then return end - - local i, kwt = 1, {} - repeat - local kw = txt:sub(kws[i], kws[i + 1] - 1) - table.insert(kwt, {kws[i], kws[i + 1] - 1, kw}) - i = i + 2 - until (i > #kws) +local get_keywords = function(data) + local i, kwt, kws = 1, {}, lpeg_pattern:match(data) + if kws then + repeat + local kw = data:sub(kws[i], kws[i + 1] - 1) + table.insert(kwt, {kw, kws[i] - 1, kws[i + 1] - 2}) + i = i + 2 + until (i > #kws) + end return kwt end -local last_data -local last_modified_toks -local wrap_lexer = function(win) - if not M.keywords then return end - if not win.syntax or not vis.lexers.load then return end - - local vlexer = vis.lexers.load(win.syntax, nil, true) - if not vlexer or not vlexer.lex then return end - local old_lex_func = vlexer.lex +local last_data, last_tokens +vis.events.subscribe(vis.events.WIN_HIGHLIGHT, function(win) + local viewport = win.viewport.bytes + if not viewport then return end + local horizon_max = longest_keyword_length + local horizon = viewport.start < horizon_max and viewport.start or horizon_max + local lex_start = viewport.start - horizon + viewport.start = lex_start - -- Append new tags to lexer - for tag, style in pairs(M.keywords) do - local tid = vlexer._TAGS[tag] - if not tid then - -- NOTE: _TAGS needs to be ordered and _TAGS[tag] needs - -- to equal the numerical table index of tag in _TAGS - -- why? ask the scintillua authors ¯\_(ツ)_/¯ - table.insert(vlexer._TAGS, tag) - tid = #vlexer._TAGS - vlexer._TAGS[tag] = tid - assert(tid < win.STYLE_LEXER_MAX) - end - win:style_define(tid, style) + local data = win.file:content(viewport) + local tokens = last_tokens + if last_data ~= data then + tokens = get_keywords(data) + last_tokens = tokens; + last_data = data end - vlexer.lex = function(lexer, data, index) - local tokens = old_lex_func(lexer, data, index) - local new_tokens = {} - local kwt - if last_data ~= data then - kwt = get_keywords(win, data) - if not kwt then return tokens end - last_data = data - else - return last_modified_toks - end - - local i = 1 - for _, kwp in ipairs(kwt) do repeat - if i > #tokens - 1 then break end - local token_type = tokens[i] - local token_start = (tokens[i - 1] or 1) - 1 - local token_end = tokens[i + 1] - local kws = kwp[1] - local kwe = kwp[2] - - if token_end < kws then - table.insert(new_tokens, token_type) - table.insert(new_tokens, token_end) - i = i + 2 - else - -- if kw is within token we need to split - -- the initial part of token off - if kws - 1 > token_start then - table.insert(new_tokens, token_type) - table.insert(new_tokens, kws) - end - table.insert(new_tokens, kwp[3]) - if token_end < kwe then - table.insert(new_tokens, token_end + 1) - i = i + 2 - else - table.insert(new_tokens, kwe + 1) - end - end - until (not token_end or token_end >= kwe) end - -- copy over remaining tokens - for j = i, #tokens, 1 do - table.insert(new_tokens, tokens[j]) + local style_ids = M.style_ids + for _, matches in pairs(tokens) do + local style_id = style_ids[matches[1]] + if style_id then + win:style(style_id, lex_start + matches[2], lex_start + matches[3]) end - last_modified_toks = new_tokens - return new_tokens end -end - -vis.events.subscribe(vis.events.WIN_OPEN, wrap_lexer) +end) return M