You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
119 lines
2.8 KiB
Lua
119 lines
2.8 KiB
Lua
local api = vim.api
|
|
local highlighter = require "vim.treesitter.highlighter"
|
|
|
|
local M = {}
|
|
|
|
function M.debounce(fn, debounce_time)
|
|
local timer = vim.loop.new_timer()
|
|
local is_debounce_fn = type(debounce_time) == "function"
|
|
|
|
return function(...)
|
|
timer:stop()
|
|
|
|
local time = debounce_time
|
|
local args = { ... }
|
|
|
|
if is_debounce_fn then
|
|
time = debounce_time()
|
|
end
|
|
|
|
timer:start(
|
|
time,
|
|
0,
|
|
vim.schedule_wrap(function()
|
|
fn(unpack(args))
|
|
end)
|
|
)
|
|
end
|
|
end
|
|
|
|
function M.get_hl_groups_at_position(bufnr, row, col)
|
|
local buf_highlighter = highlighter.active[bufnr]
|
|
|
|
if not buf_highlighter then
|
|
return {}
|
|
end
|
|
|
|
local matches = {}
|
|
|
|
buf_highlighter.tree:for_each_tree(function(tstree, tree)
|
|
if not tstree then
|
|
return
|
|
end
|
|
|
|
local root = tstree:root()
|
|
local root_start_row, _, root_end_row, _ = root:range()
|
|
|
|
-- Only worry about trees within the line range
|
|
if root_start_row > row or root_end_row < row then
|
|
return
|
|
end
|
|
|
|
local query = buf_highlighter:get_query(tree:lang())
|
|
|
|
-- Some injected languages may not have highlight queries.
|
|
if not query:query() then
|
|
return
|
|
end
|
|
|
|
local iter = query:query():iter_captures(root, buf_highlighter.bufnr, row, row + 1)
|
|
|
|
for capture, node, metadata in iter do
|
|
local hl = query.hl_cache[capture]
|
|
|
|
if hl and vim.treesitter.is_in_node_range(node, row, col) then
|
|
local c = query._query.captures[capture] -- name of the capture in the query
|
|
if c ~= nil then
|
|
table.insert(matches, { capture = c, priority = metadata.priority })
|
|
end
|
|
end
|
|
end
|
|
end, true)
|
|
return matches
|
|
end
|
|
|
|
function M.for_each_buf_window(bufnr, fn)
|
|
if not api.nvim_buf_is_loaded(bufnr) then
|
|
return
|
|
end
|
|
|
|
for _, window in ipairs(vim.fn.win_findbuf(bufnr)) do
|
|
fn(window)
|
|
end
|
|
end
|
|
|
|
function M.to_lookup_table(list, key_mapper)
|
|
local result = {}
|
|
|
|
for i, v in ipairs(list) do
|
|
local key = v
|
|
|
|
if key_mapper then
|
|
key = key_mapper(v, i)
|
|
end
|
|
|
|
result[key] = v
|
|
end
|
|
|
|
return result
|
|
end
|
|
|
|
function M.node_contains(node, range)
|
|
local start_row, start_col, end_row, end_col = node:range()
|
|
local start_fits = start_row < range[1] or (start_row == range[1] and start_col <= range[2])
|
|
local end_fits = end_row > range[3] or (end_row == range[3] and end_col >= range[4])
|
|
|
|
return start_fits and end_fits
|
|
end
|
|
|
|
--- Returns a tuple with the position of the last line and last column (0-indexed).
|
|
function M.get_end_pos(bufnr)
|
|
local bufnr = bufnr or api.nvim_get_current_buf()
|
|
local last_row = api.nvim_buf_line_count(bufnr) - 1
|
|
local last_line = api.nvim_buf_get_lines(bufnr, last_row, last_row + 1, true)[1]
|
|
local last_col = last_line and #last_line or 0
|
|
return last_row, last_col
|
|
end
|
|
|
|
return M
|