mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 03:18:16 +00:00

Revert "refactor(treesitter): delegate region calculation to treesitter (#22553)"
This reverts commit 276b647fdb
.
147 lines
3.3 KiB
Lua
147 lines
3.3 KiB
Lua
local api = vim.api
|
|
|
|
local M = {}
|
|
|
|
---@alias Range4 {[1]: integer, [2]: integer, [3]: integer, [4]: integer}
|
|
---@alias Range6 {[1]: integer, [2]: integer, [3]: integer, [4]: integer, [5]: integer, [6]: integer}
|
|
|
|
---@private
|
|
---@param a_row integer
|
|
---@param a_col integer
|
|
---@param b_row integer
|
|
---@param b_col integer
|
|
---@return integer
|
|
--- 1: a > b
|
|
--- 0: a == b
|
|
--- -1: a < b
|
|
local function cmp_pos(a_row, a_col, b_row, b_col)
|
|
if a_row == b_row then
|
|
if a_col > b_col then
|
|
return 1
|
|
elseif a_col < b_col then
|
|
return -1
|
|
else
|
|
return 0
|
|
end
|
|
elseif a_row > b_row then
|
|
return 1
|
|
end
|
|
|
|
return -1
|
|
end
|
|
|
|
M.cmp_pos = {
|
|
lt = function(...)
|
|
return cmp_pos(...) == -1
|
|
end,
|
|
le = function(...)
|
|
return cmp_pos(...) ~= 1
|
|
end,
|
|
gt = function(...)
|
|
return cmp_pos(...) == 1
|
|
end,
|
|
ge = function(...)
|
|
return cmp_pos(...) ~= -1
|
|
end,
|
|
eq = function(...)
|
|
return cmp_pos(...) == 0
|
|
end,
|
|
ne = function(...)
|
|
return cmp_pos(...) ~= 0
|
|
end,
|
|
}
|
|
|
|
setmetatable(M.cmp_pos, { __call = cmp_pos })
|
|
|
|
---@private
|
|
---Check if a variable is a valid range object
|
|
---@param r any
|
|
---@return boolean
|
|
function M.validate(r)
|
|
if type(r) ~= 'table' or #r ~= 6 and #r ~= 4 then
|
|
return false
|
|
end
|
|
|
|
for _, e in
|
|
ipairs(r --[[@as any[] ]])
|
|
do
|
|
if type(e) ~= 'number' then
|
|
return false
|
|
end
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
---@private
|
|
---@param r1 Range4|Range6
|
|
---@param r2 Range4|Range6
|
|
---@return boolean
|
|
function M.intercepts(r1, r2)
|
|
local off_1 = #r1 == 6 and 1 or 0
|
|
local off_2 = #r1 == 6 and 1 or 0
|
|
|
|
local srow_1, scol_1, erow_1, ecol_1 = r1[1], r1[2], r1[3 + off_1], r1[4 + off_1]
|
|
local srow_2, scol_2, erow_2, ecol_2 = r2[1], r2[2], r2[3 + off_2], r2[4 + off_2]
|
|
|
|
-- r1 is above r2
|
|
if M.cmp_pos.le(erow_1, ecol_1, srow_2, scol_2) then
|
|
return false
|
|
end
|
|
|
|
-- r1 is below r2
|
|
if M.cmp_pos.ge(srow_1, scol_1, erow_2, ecol_2) then
|
|
return false
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
---@private
|
|
---@param r1 Range4|Range6
|
|
---@param r2 Range4|Range6
|
|
---@return boolean whether r1 contains r2
|
|
function M.contains(r1, r2)
|
|
local off_1 = #r1 == 6 and 1 or 0
|
|
local off_2 = #r1 == 6 and 1 or 0
|
|
|
|
local srow_1, scol_1, erow_1, ecol_1 = r1[1], r1[2], r1[3 + off_1], r1[4 + off_1]
|
|
local srow_2, scol_2, erow_2, ecol_2 = r2[1], r2[2], r2[3 + off_2], r2[4 + off_2]
|
|
|
|
-- start doesn't fit
|
|
if M.cmp_pos.gt(srow_1, scol_1, srow_2, scol_2) then
|
|
return false
|
|
end
|
|
|
|
-- end doesn't fit
|
|
if M.cmp_pos.lt(erow_1, ecol_1, erow_2, ecol_2) then
|
|
return false
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
---@private
|
|
---@param source integer|string
|
|
---@param range Range4
|
|
---@return Range6
|
|
function M.add_bytes(source, range)
|
|
local start_row, start_col, end_row, end_col = range[1], range[2], range[3], range[4]
|
|
local start_byte = 0
|
|
local end_byte = 0
|
|
-- TODO(vigoux): proper byte computation here, and account for EOL ?
|
|
if type(source) == 'number' then
|
|
-- Easy case, this is a buffer parser
|
|
start_byte = api.nvim_buf_get_offset(source, start_row) + start_col
|
|
end_byte = api.nvim_buf_get_offset(source, end_row) + end_col
|
|
elseif type(source) == 'string' then
|
|
-- string parser, single `\n` delimited string
|
|
start_byte = vim.fn.byteidx(source, start_col)
|
|
end_byte = vim.fn.byteidx(source, end_col)
|
|
end
|
|
|
|
return { start_row, start_col, start_byte, end_row, end_col, end_byte }
|
|
end
|
|
|
|
return M
|