Merge branch 'LuaLS'

This commit is contained in:
HiPhish 2023-11-23 23:29:27 +01:00
commit a2da59bdac
15 changed files with 369 additions and 54 deletions

View file

@ -27,3 +27,11 @@ following criteria:
If there are many test cases or if the code becomes too verbose feel free to
create multiple test files.
In addition to the queries and test file(s), please consider adding the type
annotations in `lua/rainbow-delimiters.types.lua` if you are adding queries
for a new language. You will need to update:
- `@class rainbow_delimiters.config.strategies`
- `@class rainbow_delimiters.config.queries`
- `@alias rainbow_delimiters.language`

View file

@ -50,7 +50,7 @@ Configuration is done by setting entries in the Vim script dictionary
\ 'RainbowDelimiterGreen',
\ 'RainbowDelimiterViolet',
\ 'RainbowDelimiterCyan',
\ ],
\ ],
\ }
The equivalent code in Lua:
@ -60,6 +60,7 @@ The equivalent code in Lua:
-- This module contains a number of default definitions
local rainbow_delimiters = require 'rainbow-delimiters'
---@type rainbow_delimiters.config
vim.g.rainbow_delimiters = {
strategy = {
[''] = rainbow_delimiters.strategy['global'],
@ -87,7 +88,7 @@ same parameters as `g:rainbow-delimiters`.
.. code:: lua
require('rainbow-delimiters.setup').setup {
strategy = {
strategy = {
-- ...
},
query = {

View file

@ -108,6 +108,7 @@ Alternatively, the same configuration in Lua:
-- This module contains a number of default definitions
local rainbow_delimiters = require 'rainbow-delimiters'
---@type rainbow_delimiters.config
vim.g.rainbow_delimiters = {
strategy = {
[''] = rainbow_delimiters.strategy['global'],
@ -423,9 +424,9 @@ object-oriented terminology we would say that a strategy table must implement
the strategy protocol.
>
strategy = {
on_attach = function(bufnr: number, settings: table),
on_detach = function(bufnr: string),
on_reset = function(bufnr: number, settings: table),
on_attach = function(bufnr: integer, settings: table),
on_detach = function(bufnr: integer),
on_reset = function(bufnr: integer, settings: table),
}
<

View file

@ -18,7 +18,7 @@
local lib = require 'rainbow-delimiters.lib'
---Disable rainbow delimiters for a given buffer.
---@param bufnr number Buffer number, zero for current buffer.
---@param bufnr integer Buffer number, zero for current buffer.
local function disable(bufnr)
if not bufnr or bufnr == 0 then bufnr = vim.api.nvim_get_current_buf() end
lib.detach(bufnr)
@ -26,13 +26,15 @@ local function disable(bufnr)
end
---Enable rainbow delimiters for a given buffer.
---@param bufnr number Buffer number, zero for current buffer.
---@param bufnr integer Buffer number, zero for current buffer.
local function enable(bufnr)
if not bufnr or bufnr == 0 then bufnr = vim.api.nvim_get_current_buf() end
lib.buffers[bufnr] = nil
lib.attach(bufnr)
end
---Toggle rainbow delimiters for a given buffer.
---@param bufnr integer Buffer number, zero for current buffer.
local function toggle(bufnr)
if not bufnr or bufnr == 0 then bufnr = vim.api.nvim_get_current_buf() end
if lib.buffers[bufnr] then
@ -47,8 +49,11 @@ local M = {
hlgroup_at = lib.hlgroup_at,
---Available default highlight strategies
strategy = {
---Global highlighting strategy
['global'] = require 'rainbow-delimiters.strategy.global',
---Local highlighting strategy
['local'] = require 'rainbow-delimiters.strategy.local',
---Empty highlighting strategy for testing
['noop'] = require 'rainbow-delimiters.strategy.no-op',
},
enable = enable,

View file

@ -0,0 +1,229 @@
---@meta
--# Utility Library #--
---Strategy to use for highlighting with rainbow-delimiters
---Must implement `on_attach`, `on_detach` and `on_reset`
---@class rainbow_delimiters.strategy
---`on_attach`: setup the highlighting on attach
---@field on_attach fun(bufnr: integer, settings: rainbow_delimiters.buffer_settings)
---`on_detach`: remove any unneccesary remaining setup on detach
---@field on_detach fun(bufnr: integer)
---`on_reset`: update the highlighting on reset
---@field on_reset fun(bufnr: integer, settings: rainbow_delimiters.buffer_settings)
---@class (exact) rainbow_delimiters.buffer_settings
---@field strategy rainbow_delimiters.strategy
---@field parser LanguageTree
---@field lang string
--# Config #--
---Configuration table for rainbow-delimiters
---@class (exact) rainbow_delimiters.config
---Strategy to use for highlighting
---@field strategy rainbow_delimiters.config.strategies?
---Query to use for highlighting
---@field query rainbow_delimiters.config.queries?
---Highlight colors
---@field highlight string[]?
---Whitelist for languages to highlight
---@field whitelist rainbow_delimiters.language[]?
---Blacklist for languages not to highlight
---@field blacklist rainbow_delimiters.language[]?
---Logging with log file and log level
---@field log rainbow_delimiters.logging?
---@class rainbow_delimiters.config.strategies
---@field [''] (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field astro (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field bash (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field c (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field c_sharp (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field clojure (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field commonlisp (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field cpp (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field css (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field cuda (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field cue (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field dart (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field elixir (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field elm (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field fennel (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field fish (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field go (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field haskell (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field hcl (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field html (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field janet_simple (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field java (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field javascript (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field json (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field json5 (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field jsonc (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field jsonnet (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field julia (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field kotlin (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field latex (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field lua (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field luadoc (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field make (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field markdown (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field nim (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field nix (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field perl (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field php (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field python (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field query (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field r (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field racket (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field regex (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field rst (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field ruby (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field rust (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field scheme (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field scss (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field sql (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field templ (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field toml (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field tsx (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field typescript (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field verilog (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field vim (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field vimdoc (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field vue (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field yaml (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@field zig (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---User defined language, not part of rainbow_delimiters support
---@field [string] (rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?)?
---@class rainbow_delimiters.config.queries
---@field [''] ('rainbow-delimiters' | string)?
---@field astro ('rainbow-delimiters' | string)?
---@field bash ('rainbow-delimiters' | string)?
---@field c ('rainbow-delimiters' | string)?
---@field c_sharp ('rainbow-delimiters' | string)?
---@field clojure ('rainbow-delimiters' | string)?
---@field commonlisp ('rainbow-delimiters' | string)?
---@field cpp ('rainbow-delimiters' | string)?
---@field css ('rainbow-delimiters' | string)?
---@field cuda ('rainbow-delimiters' | string)?
---@field cue ('rainbow-delimiters' | string)?
---@field dart ('rainbow-delimiters' | string)?
---@field elixir ('rainbow-delimiters' | string)?
---@field elm ('rainbow-delimiters' | string)?
---@field fennel ('rainbow-delimiters' | string)?
---@field fish ('rainbow-delimiters' | string)?
---@field go ('rainbow-delimiters' | string)?
---@field haskell ('rainbow-delimiters' | string)?
---@field hcl ('rainbow-delimiters' | string)?
---@field html ('rainbow-delimiters' | string)?
---@field janet_simple ('rainbow-delimiters' | string)?
---@field java ('rainbow-delimiters' | string)?
---@field javascript ('rainbow-delimiters' | 'rainbow-parens' | 'rainbow-delimiters-react' | string)?
---@field json ('rainbow-delimiters' | string)?
---@field json5 ('rainbow-delimiters' | string)?
---@field jsonc ('rainbow-delimiters' | string)?
---@field jsonnet ('rainbow-delimiters' | string)?
---@field julia ('rainbow-delimiters' | string)?
---@field kotlin ('rainbow-delimiters' | string)?
---@field latex ('rainbow-delimiters' | 'rainbow-blocks' | string)?
---@field lua ('rainbow-delimiters' | 'rainbow-blocks' | string)?
---@field luadoc ('rainbow-delimiters' | string)?
---@field make ('rainbow-delimiters' | string)?
---@field markdown ('rainbow-delimiters' | string)?
---@field nim ('rainbow-delimiters' | string)?
---@field nix ('rainbow-delimiters' | string)?
---@field perl ('rainbow-delimiters' | string)?
---@field php ('rainbow-delimiters' | string)?
---@field python ('rainbow-delimiters' | string)?
---@field query ('rainbow-delimiters' | string)?
---@field r ('rainbow-delimiters' | string)?
---@field racket ('rainbow-delimiters' | string)?
---@field regex ('rainbow-delimiters' | string)?
---@field rst ('rainbow-delimiters' | string)?
---@field ruby ('rainbow-delimiters' | string)?
---@field rust ('rainbow-delimiters' | string)?
---@field scheme ('rainbow-delimiters' | string)?
---@field scss ('rainbow-delimiters' | string)?
---@field sql ('rainbow-delimiters' | string)?
---@field templ ('rainbow-delimiters' | string)?
---@field toml ('rainbow-delimiters' | string)?
---@field tsx ('rainbow-delimiters' | 'rainbow-parens' | string)?
---@field typescript ('rainbow-delimiters' | 'rainbow-parens' | string)?
---@field verilog ('rainbow-delimiters' | 'rainbow-blocks' | string)?
---@field vim ('rainbow-delimiters' | string)?
---@field vimdoc ('rainbow-delimiters' | string)?
---@field vue ('rainbow-delimiters' | string)?
---@field yaml ('rainbow-delimiters' | string)?
---@field zig ('rainbow-delimiters' | string)?
---User defined language, not part of rainbow_delimiters support
---@field [string] string?
---@alias rainbow_delimiters.language
---| 'astro'
---| 'bash'
---| 'c'
---| 'c_sharp'
---| 'clojure'
---| 'commonlisp'
---| 'cpp'
---| 'css'
---| 'cuda'
---| 'cue'
---| 'dart'
---| 'elixir'
---| 'elm'
---| 'fennel'
---| 'fish'
---| 'go'
---| 'haskell'
---| 'hcl'
---| 'html'
---| 'janet_simple'
---| 'java'
---| 'javascript'
---| 'json'
---| 'json5'
---| 'jsonc'
---| 'jsonnet'
---| 'julia'
---| 'kotlin'
---| 'latex'
---| 'lua'
---| 'luadoc'
---| 'make'
---| 'markdown'
---| 'nim'
---| 'nix'
---| 'perl'
---| 'php'
---| 'python'
---| 'query'
---| 'r'
---| 'racket'
---| 'regex'
---| 'rst'
---| 'ruby'
---| 'rust'
---| 'scheme'
---| 'scss'
---| 'sql'
---| 'templ'
---| 'toml'
---| 'tsx'
---| 'typescript'
---| 'verilog'
---| 'vim'
---| 'vimdoc'
---| 'vue'
---| 'yaml'
---| 'zig'
---User defined language, not part of rainbow_delimiters support
---| string
---@class (exact) rainbow_delimiters.logging
---@field file ('rainbow_delimiters.log' | string)?
---@field level integer

View file

@ -15,6 +15,7 @@
--]]
---Default plugin configuration.
---@type rainbow_delimiters.config
local M = {
---Query names by file type
query = {

View file

@ -31,6 +31,8 @@ local schema = {
---Check whether there is a parser installed for the given language.
---@param lang string
---@return boolean
local function check_parser_installed(lang)
local success = pcall(vim.treesitter.language.inspect, lang)
return success
@ -41,6 +43,8 @@ end
---This is not a 100% reliable check; we only test the type of the argument and
---whether the table has the correct fields, but not what the callback
---functions actually do.
---@param strategy rainbow_delimiters.strategy | fun(): rainbow_delimiters.strategy?
---@return boolean
local function check_strategy(strategy)
if type(strategy) == 'function' then
local finfo = debug.getinfo(strategy)
@ -62,14 +66,20 @@ local function check_strategy(strategy)
end
---Check whether the given query is defined for the given language.
---@param lang string
---@param name string
---@return boolean
local function check_query(lang, name)
local query = vim.treesitter.query.get(lang, name)
return query ~= nil
end
---@param settings rainbow_delimiters.logging
local function check_logging(settings)
local level, file = settings.level, settings.file
if level then
-- Note: although the log level is an integer, Lua 5.1 only has the
-- number type
if type(level) ~= 'number' then
error('The log level must be a number', 'See :h vim.log.levels for valid log levels.')
else
@ -102,7 +112,7 @@ end
function M.check()
local settings = vim.g.rainbow_delimiters
local settings = vim.g.rainbow_delimiters --[[@as rainbow_delimiters.config]]
if not settings then
return
info("No custom configuration; see :h rb-delimiters-setup for information.")

View file

@ -55,6 +55,7 @@ M.nsids = setmetatable({}, {
---is a table of information about that buffer (e.g. language, strategy,
---query). This also makes sure we keep track of all parsers in active use to
---prevent them from being garbage-collected.
---@type table<integer, rainbow_delimiters.buffer_settings | false>
M.buffers = {}
@ -78,11 +79,10 @@ function M.get_query(lang)
end
---Apply highlighting to a single node.
---@param bufnr number Buffer which contains the node
---@param bufnr integer Buffer which contains the node
---@param lang string Language of the node (to group HL into namespaces)
---@param node table Node to highlight
---@param hlgroup string Name of the highlight group to apply.
---@return nil
function M.highlight(bufnr, lang, node, hlgroup)
-- range of the capture, zero-indexed
local startRow, startCol, endRow, endCol = node:range()
@ -103,7 +103,7 @@ end
---Get the appropriate highlight group for the given level of nesting.
---@param i number One-based index into the highlight groups
---@param i integer One-based index into the highlight groups
---@return string hlgroup Name of the highlight groups
function M.hlgroup_at(i)
local hlgroups = config.highlight
@ -113,8 +113,10 @@ end
---Clears the reserved Rainbow namespace.
---
---@param bufnr number Number of the buffer for which to clear the namespace
---@return nil
---@param bufnr integer Number of the buffer for which to clear the namespace
---@param lang string
---@param line_start integer?
---@param line_end integer?
function M.clear_namespace(bufnr, lang, line_start, line_end)
local nsid = M.nsids[lang]
if vim.api.nvim_buf_is_valid(bufnr) then
@ -123,6 +125,7 @@ function M.clear_namespace(bufnr, lang, line_start, line_end)
end
---Start rainbow highlighting for the given buffer
---@param bufnr integer
function M.attach(bufnr)
-- Rainbow delimiters was explicitly disabled for this buffer
if M.buffers[bufnr] == false then return end
@ -175,10 +178,12 @@ function M.attach(bufnr)
if not strategy or strategy == vim.NIL then return end
parser:register_cbs {
---@param bnr integer
on_detach = function(bnr)
if not M.buffers[bnr] then return end
M.detach(bufnr)
end,
---@param child LanguageTree
on_child_removed = function(child)
M.clear_namespace(bufnr, child:lang())
end,
@ -201,6 +206,7 @@ function M.attach(bufnr)
end
---Start rainbow highlighting for the given buffer
---@param bufnr integer
function M.detach(bufnr)
log.trace('Detaching from buffer %d.', bufnr)
if not M.buffers[bufnr] then

View file

@ -30,6 +30,7 @@ end
---Dynamically determines the module from which the log function was called.
---If it was called from somewhere else return the name of the plugin.
---@return string
local function get_module()
local module = debug.getinfo(4, 'S').source:match('^.+rainbow%-delimiters/(.+).lua$')
if not module then
@ -38,6 +39,11 @@ local function get_module()
return module:gsub('/', '.')
end
---@param file file*
---@param level integer
---@param module string
---@param message any
---@param ... any
local function write_log(file, level, module, message, ...)
local msg
local timestamp = date('%FT%H:%M%z')
@ -50,6 +56,9 @@ local function write_log(file, level, module, message, ...)
file:write(string.format('%s %s %s %s\n', timestamp, level, module, msg))
end
---@param level integer
---@param message any
---@param ... any
local function log(level, message, ...)
if level < config.log.level then return end

View file

@ -3,7 +3,7 @@ local M = {}
---Apply the given configuration to the rainbow-delimiter settings. Will
---overwrite existing settings.
---
---@param opts table Settings, same format as `vim.g.rainbow_delimiters`
---@param opts rainbow_delimiters.config Settings, same format as `vim.g.rainbow_delimiters`
function M.setup(opts)
vim.g.rainbow_delimiters = opts
end

View file

@ -17,18 +17,22 @@
---Helper library for stack-like tables.
local M = {}
---@class Stack
---@field public size fun(self: Stack): number
---@class (exact) Stack
---@field public size fun(self: Stack): integer
---@field public peek fun(self: Stack): any
---@field public push fun(self: Stack, item: any): Stack
---@field public pop fun(self: Stack): any
---@field public iter fun(self: Stack): (fun(i: number, item: any): number, any), Stack, number
---@field private content any[]
---@field public iter fun(self: Stack): ((fun(i: integer, item: any): integer?, any), Stack, integer)
---@field package content any[]
---The stack metatable.
local mt = {}
---The actual iterator implementation, hidden behind the iter-method.
---@param stack Stack
---@param i integer
---@return integer?
---@return any
local function iter_stack(stack, i)
if i <= 1 then return end
return i - 1, stack.content[i - 1]
@ -39,7 +43,7 @@ end
local function stack_tostring(stack)
local items = {}
for _, item in ipairs(stack.content) do
items[#items+1] = tostring(item)
items[#items + 1] = tostring(item)
end
return string.format('[%s]', table.concat(items, ', '))
end
@ -48,7 +52,8 @@ end
---[ Methods ]-----------------------------------------------------------------
---Returns the current number of items in the stack.
---@return number size Current size of the stack
---@param self Stack
---@return integer size Current size of the stack
local function size(self)
return #self.content
end
@ -57,9 +62,9 @@ end
---returns the current index (one-based, counting from the bottom) and the
---current item.
---@param self Stack The stack instance
---@return fun(i: number, stack: Stack): number, any
---@return fun(i: integer, stack: Stack): integer?, any
---@return Stack
---@return number
---@return integer
local function iter(self)
return iter_stack, self, self:size() + 1
end
@ -98,12 +103,12 @@ end
function M.new(items)
---@type Stack
local result = {
content = {}, ---@type any[]
size = size, ---@type fun(self: Stack): number
iter = iter,
push = push, ---@type fun(self: Stack, item: any): Stack
pop = pop, ---@type fun(self: Stack): any
peek = peek, ---@type fun(self: Stack): any
content = {},
size = size,
iter = iter,
push = push,
pop = pop,
peek = peek,
}
setmetatable(result, mt)
for _, item in ipairs(items or {}) do result:push(item) end

View file

@ -27,8 +27,8 @@ local M = {}
---Changes are range objects and come in two variants: one with four entries and
---one with six entries. We only want the four-entry variant. See
---`:h TSNode:range()`
---@param change number[]
---@return number[]
---@param change integer[]
---@return integer[]
local function normalize_change(change)
local result
if #change == 4 then
@ -41,11 +41,10 @@ local function normalize_change(change)
return result
end
---@param bufnr number
---@param bufnr integer
---@param lang string
---@param matches Stack
---@param level number
---@return nil
---@param level integer
local function highlight_matches(bufnr, lang, matches, level)
local hlgroup = lib.hlgroup_at(level)
for _, match in matches:iter() do
@ -65,11 +64,10 @@ local function new_match_record()
end
---Update highlights for a range. Called every time text is changed.
---@param bufnr number Buffer number
---@param bufnr integer Buffer number
---@param changes table List of node ranges in which the changes occurred
---@param tree TSTree TS tree
---@param lang string Language
---@return nil
local function update_range(bufnr, changes, tree, lang)
log.debug('Updated range with changes %s', vim.inspect(changes))
@ -142,9 +140,8 @@ local function update_range(bufnr, changes, tree, lang)
end
---Update highlights for every tree in given buffer.
---@param bufnr number # Buffer number
---@param bufnr integer # Buffer number
---@param parser LanguageTree
---@return nil
local function full_update(bufnr, parser)
log.debug('Performing full updated on buffer %d', bufnr)
local function callback(tree, sub_parser)
@ -157,10 +154,9 @@ end
---Sets up all the callbacks and performs an initial highlighting
---@param bufnr number # Buffer number
---@param bufnr integer # Buffer number
---@param parser LanguageTree
---@param start_parent_lang string? # Parent language or nil
---@return nil
local function setup_parser(bufnr, parser, start_parent_lang)
log.debug('Setting up parser for buffer %d', bufnr)
@ -171,6 +167,8 @@ local function setup_parser(bufnr, parser, start_parent_lang)
if not lib.get_query(lang) then return end
p:register_cbs {
---@param changes table
---@param tree TSTree
on_changedtree = function(changes, tree)
log.trace('Changed tree in buffer %d with languages %s', bufnr, lang)
-- HACK: As of Neovim v0.9.1 there is no way of unregistering a
@ -239,6 +237,7 @@ local function setup_parser(bufnr, parser, start_parent_lang)
end,
-- New languages can be added into the text at some later time, e.g.
-- code snippets in Markdown
---@param child LanguageTree
on_child_added = function(child)
setup_parser(bufnr, child, lang)
end,
@ -250,20 +249,28 @@ local function setup_parser(bufnr, parser, start_parent_lang)
end
---on_attach implementation for the global strategy
---@param bufnr integer
---@param settings rainbow_delimiters.buffer_settings
function M.on_attach(bufnr, settings)
log.trace('global strategy on_attach')
local parser = settings.parser
setup_parser(bufnr, parser, nil)
end
---on_detach implementation for the global strategy
---@param _bufnr integer
function M.on_detach(_bufnr)
end
---on_reset implementation for the global strategy
---@param bufnr integer
---@param settings rainbow_delimiters.buffer_settings
function M.on_reset(bufnr, settings)
log.trace('global strategy on_reset')
full_update(bufnr, settings.parser)
end
return M
return M --[[@as rainbow_delimiters.strategy]]
-- vim:tw=79:ts=4:sw=4:noet:

View file

@ -45,11 +45,15 @@ local M = {}
local match_trees = {}
---Reusable autogroup for events in this strategy.
---@type number
---@type integer
local augroup = api.nvim_create_augroup('TSRainbowLocalCursor', {})
---Highlights a single match with the given highlight group
---@param bufnr integer
---@param lang string
---@param match table
---@param hlgroup string
local function highlight_match(bufnr, lang, match, hlgroup)
for _, delimiter in match.delimiter:iter() do lib.highlight(bufnr, lang, delimiter, hlgroup) end
end
@ -57,9 +61,9 @@ end
---Highlights all matches and their children on the stack of matches. All
---matches must be on the same level of the match tree.
---
---@param bufnr number Number of the buffer
---@param bufnr integer Number of the buffer
---@param matches Stack Stack of matches
---@param level number Level of the matches
---@param level integer Level of the matches
local function highlight_matches(bufnr, lang, matches, level)
local hlgroup = lib.hlgroup_at(level)
for _, match in matches:iter() do
@ -70,6 +74,13 @@ end
---Finds a match (and its level) in the match tree whose container node is the
---given container node.
---@param matches Stack
---@param container TSNode
---@param level integer
---@return table
---@return integer
---If no match is found, return nil.
---@overload fun(matches: Stack, container: TSNode, level: integer)
local function find_container(matches, container, level)
for _, match in matches:iter() do
if match.container == container then return match, level end
@ -79,7 +90,7 @@ local function find_container(matches, container, level)
end
--- Create a new empty match_record with an optionally set container
---@param container TSNode?
---@param container TSNode
---@return table
local function new_match_record(container)
return {
@ -91,7 +102,7 @@ end
---Assembles the match tree, usually called after the document tree has
---changed.
---@param bufnr number Buffer number
---@param bufnr integer Buffer number
---@param changes table List of node ranges in which the changes occurred
---@param tree TSTree TS tree
---@param lang string Language
@ -164,6 +175,9 @@ local function build_match_tree(bufnr, changes, tree, lang)
return matches
end
---@param bufnr integer
---@param tree TSTree
---@param lang string
local function update_local(bufnr, tree, lang)
if not lib.enabled_for(lang) then return end
local query = lib.get_query(lang)
@ -220,6 +234,8 @@ end
---Callback function to re-highlight the buffer according to the current cursor
---position.
---@param bufnr integer
---@param parser LanguageTree
local function local_rainbow(bufnr, parser)
parser:for_each_tree(function(tree, sub_parser)
update_local(bufnr, tree, sub_parser:lang())
@ -227,9 +243,8 @@ local function local_rainbow(bufnr, parser)
end
---Sets up all the callbacks and performs an initial highlighting
---@param bufnr number # Buffer number
---@param bufnr integer # Buffer number
---@param parser LanguageTree
---@return nil
local function setup_parser(bufnr, parser)
log.debug('Setting up parser for buffer %d', bufnr)
util.for_each_child(nil, parser:lang(), parser, function(p, lang, _parent_lang)
@ -238,6 +253,8 @@ local function setup_parser(bufnr, parser)
-- nil-reference error
if not lib.get_query(lang) then return end
p:register_cbs {
---@param _changes table
---@param tree TSTree
on_changedtree = function(_changes, tree)
-- HACK: As of Neovim v0.9.1 there is no way of unregistering a
-- callback, so we use this check to abort
@ -257,6 +274,7 @@ local function setup_parser(bufnr, parser)
end,
-- New languages can be added into the text at some later time, e.g.
-- code snippets in Markdown
---@param child LanguageTree
on_child_added = function(child)
setup_parser(bufnr, child)
end,
@ -265,6 +283,9 @@ local function setup_parser(bufnr, parser)
end)
end
---on_attach implementation for the local strategy
---@param bufnr integer
---@param settings rainbow_delimiters.buffer_settings
function M.on_attach(bufnr, settings)
local parser = settings.parser
setup_parser(bufnr, parser)
@ -293,6 +314,8 @@ function M.on_attach(bufnr, settings)
local_rainbow(bufnr, parser)
end
---on_detach implementation for the local strategy
---@param bufnr integer
function M.on_detach(bufnr)
-- Uninstall autocommand and delete cached match tree
api.nvim_clear_autocmds {
@ -302,11 +325,14 @@ function M.on_detach(bufnr)
match_trees[bufnr] = nil
end
---on_reset implementation for the local strategy
---@param bufnr integer
---@param settings rainbow_delimiters.buffer_settings
function M.on_reset(bufnr, settings)
local parser = settings.parser
local_rainbow(bufnr, parser)
end
return M
return M --[[@as rainbow_delimiters.strategy]]
-- vim:tw=79:ts=4:sw=4:noet:

View file

@ -17,15 +17,23 @@
---A dummy strategy which does nothing; can be used in testing.
local M = {}
M.on_attach = function()
---on_attach implementation for the noop strategy
---@param _bufnr integer
---@param _settings rainbow_delimiters.buffer_settings
M.on_attach = function(_bufnr, _settings)
end
M.on_detach = function()
---on_detach implementation for the noop strategy
---@param _bufnr integer
M.on_detach = function(_bufnr)
end
M.on_reset = function()
---on_reset implementation for the noop strategy
---@param _bufnr integer
---@param _settings rainbow_delimiters.buffer_settings
M.on_reset = function(_bufnr, _settings)
end
return M
return M --[[@as rainbow_delimiters.strategy]]
-- vim:tw=79:ts=4:sw=4:noet:

View file

@ -28,8 +28,7 @@ local M = {}
---@param parent_lang string? # Parent language or nil
---@param lang string
---@param language_tree LanguageTree
---@param thunk fun(p: LanguageTree, lang: string, parent_lang: string?): nil
---@return nil
---@param thunk fun(p: LanguageTree, lang: string, parent_lang: string?)
function M.for_each_child(parent_lang, lang, language_tree, thunk)
thunk(language_tree, lang, parent_lang)
local children = language_tree:children()