WIP
Some checks failed
NeoVim tests / code-quality (push) Failing after 1m29s

This commit is contained in:
2025-07-17 23:18:28 -06:00
parent 23708652e5
commit fdc8f0f2d9
5 changed files with 206 additions and 24 deletions

View File

@@ -100,13 +100,25 @@ function Range.from_extmark(bufnr, extmark)
local start = Pos.new(bufnr, start_row0 + 1, start_col0 + 1)
local stop = details and Pos.new(bufnr, details.end_row + 1, details.end_col)
-- Check for invalid extmark range:
if stop and stop < start then return Range.new(stop) end
if stop ~= nil then
-- Check for invalid extmark range:
if stop < start then return Range.new(stop) end
if stop and stop.col == 0 then
mode = 'V'
stop = stop:must_next(-1)
stop.col = Pos.MAX_COL
-- Check for stop-mark past the end of the buffer:
local buf_max_lines = vim.api.nvim_buf_line_count(bufnr)
if stop.lnum > buf_max_lines then
mode = 'V'
stop.lnum = buf_max_lines
stop.col = Pos.MAX_COL
end
-- A stop mark at position 0 means it is at the end of the last line.
-- Move it back.
if stop.col == 0 then
mode = 'V'
stop = stop:must_next(-1)
stop.col = Pos.MAX_COL
end
end
return Range.new(start, stop, mode)

View File

@@ -394,14 +394,28 @@ function Renderer:_on_text_changed()
local start_row0, start_col0, details = unpack(extmark)
local end_row0, end_col0 = details.end_row, details.end_col
local buf_max_line0 = math.max(1, vim.api.nvim_buf_line_count(self.bufnr) - 1)
if end_row0 > buf_max_line0 then
end_row0 = buf_max_line0
local last_line = vim.api.nvim_buf_get_lines(self.bufnr, end_row0, end_row0 + 1, false)[1] or ''
end_col0 = last_line:len()
end
if end_col0 == 0 then
end_row0 = end_row0 - 1
local last_line = vim.api.nvim_buf_get_lines(self.bufnr, end_row0, end_row0 + 1, false)[1] or ''
end_col0 = last_line:len()
end
if start_row0 == end_row0 and start_col0 == end_col0 then
on_change ''
else
local lines = vim.fn.getregion(
{ self.bufnr, start_row0 + 1, start_col0 + 1 },
{ self.bufnr, end_row0 + 1, end_col0 },
{ type = 'v' }
)
local pos1 = { self.bufnr, start_row0 + 1, start_col0 + 1 }
local pos2 = { self.bufnr, end_row0 + 1, end_col0 }
local ok, lines = pcall(vim.fn.getregion, pos1, pos2, { type = 'v' })
if not ok then
vim.print { pos1 = pos1, pos2 = pos2 }
error(lines)
end
local text = table.concat(lines, '\n')
on_change(text)
end
@@ -409,6 +423,65 @@ function Renderer:_on_text_changed()
end
end
function Renderer:_debug()
local prev_w = vim.api.nvim_get_current_win()
vim.cmd.vnew()
local info_bufnr = vim.api.nvim_get_current_buf()
vim.bo.bufhidden = 'delete'
vim.bo.buflisted = false
vim.bo.buftype = 'nowrite'
local ids = {}
local function cleanup()
for _, id in ipairs(ids) do
vim.api.nvim_del_autocmd(id)
end
vim.api.nvim_buf_delete(info_bufnr, { force = true })
end
table.insert(
ids,
vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, {
callback = function()
local l, c = unpack(vim.api.nvim_win_get_cursor(0))
l = l - 1 -- make it actually 0-based
local info = {
cursor = {
pos = { l, c },
tags = self:get_pos_infos { l, c },
},
extmarks = self.curr.extmarks,
raw_intersecting = vim.api.nvim_buf_get_extmarks(
self.bufnr,
self.ns,
{ l, c },
{ l, c },
{ details = true, overlap = true }
),
}
vim.api.nvim_buf_set_lines(info_bufnr, 0, -1, true, vim.split(vim.inspect(info), '\n'))
end,
})
)
table.insert(
ids,
vim.api.nvim_create_autocmd('WinClosed', {
pattern = tostring(vim.api.nvim_get_current_win()),
callback = cleanup,
})
)
table.insert(
ids,
vim.api.nvim_create_autocmd('WinClosed', {
pattern = tostring(prev_w),
callback = cleanup,
})
)
vim.api.nvim_set_current_win(prev_w)
end
--- Returns pairs of extmarks and tags associate with said extmarks. The
--- returned tags/extmarks are sorted smallest (innermost) to largest
--- (outermost).
@@ -425,7 +498,7 @@ function Renderer:get_pos_infos(pos0, mode) -- {{{
-- edge, and one for it's right. We need to do our own intersection test,
-- because the NeoVim API is over-inclusive in what it returns:
--- @type u.renderer.RendererExtmark[]
local intersecting_extmarks = vim
local mapped_extmarks = vim
.iter(
vim.api.nvim_buf_get_extmarks(
self.bufnr,
@@ -446,26 +519,43 @@ function Renderer:get_pos_infos(pos0, mode) -- {{{
end
return { id = id, start = start, stop = stop, opts = details }
end)
:totable()
local intersecting_extmarks = vim
.iter(mapped_extmarks)
--- @param ext u.renderer.RendererExtmark
:filter(function(ext)
if ext.stop[1] ~= nil and ext.stop[2] ~= nil then
-- If we've "ciw" and "collapsed" an extmark onto the cursor,
-- the cursor pos will equal the exmark's start AND end. In this
-- case, we want to include the extmark.
return (
if
cursor_line0 == ext.start[1]
and cursor_col0 == ext.start[2]
and cursor_line0 == ext.stop[1]
and cursor_col0 == ext.stop[2]
)
or (
cursor_line0 >= ext.start[1]
and cursor_col0 >= ext.start[2]
then
return true
end
return
-- START: line check
cursor_line0 >= ext.start[1]
-- START: column check
and (cursor_line0 ~= ext.start[1] or cursor_col0 >= ext.start[2])
-- STOP: line check
and cursor_line0 <= ext.stop[1]
-- In insert mode, the cursor is "thin", so <= to compensate:
-- In normal mode, the cursor is "wide", so < to compensate:
and (mode == 'i' and cursor_col0 <= ext.stop[2] or cursor_col0 < ext.stop[2])
)
-- STOP: column check
and (
cursor_line0 ~= ext.stop[1]
or (
mode == 'i'
-- In insert mode, the cursor is "thin", so <= to compensate:
and cursor_col0 <= ext.stop[2]
-- In normal mode, the cursor is "wide", so < to compensate:
or cursor_col0 < ext.stop[2]
)
)
else
return true
end