better extmark inclusivity
All checks were successful
NeoVim tests / code-quality (push) Successful in 1m21s

This commit is contained in:
2025-06-17 23:37:16 -06:00
parent 28714fb51b
commit 103270a241
4 changed files with 52 additions and 17 deletions

View File

@@ -382,6 +382,8 @@ function Range:save_to_extmark()
end_col = 0
end
local id = vim.api.nvim_buf_set_extmark(r.start.bufnr, NS, r.start.lnum - 1, r.start.col - 1, {
right_gravity = false,
end_right_gravity = true,
end_row = end_row,
end_col = end_col,
})

View File

@@ -28,7 +28,6 @@ M.h = setmetatable({}, {
}
end,
__index = function(_, name)
-- vim.print('dynamic hl ' .. name)
return function(attributes, children)
return M.h('text', vim.tbl_deep_extend('force', { hl = name }, attributes), children)
end
@@ -324,6 +323,13 @@ function Renderer:_reconcile() -- {{{
id = extmark.id,
end_row = extmark.stop[1],
end_col = extmark.stop[2],
-- If we change the text starting from the beginning (where the extmark
-- is), we don't want the extmark to move to the right.
right_gravity = false,
-- If we change the text starting from the end (where the end extmark
-- is), we don't want the extmark to move to stay stationary: we want
-- it to move to the right.
end_right_gravity = true,
}, extmark.opts)
)
end
@@ -385,7 +391,7 @@ function Renderer:_on_text_changed()
local end_row0, end_col0 = details.end_row, details.end_col
if start_row0 == end_row0 and start_col0 == end_col0 then
-- Invalid extmark
on_change ''
else
local lines = vim.fn.getregion(
{ self.bufnr, start_row0 + 1, start_col0 + 1 },
@@ -405,9 +411,11 @@ end
---
--- @private (private for now)
--- @param pos0 [number; number]
--- @param mode string?
--- @return { extmark: u.renderer.RendererExtmark; tag: u.renderer.Tag; }[]
function Renderer:get_pos_infos(pos0) -- {{{
function Renderer:get_pos_infos(pos0, mode) -- {{{
local cursor_line0, cursor_col0 = pos0[1], pos0[2]
if not mode then mode = vim.api.nvim_get_mode().mode end
-- The cursor (block) occupies **two** extmark spaces: one for it's left
-- edge, and one for it's right. We need to do our own intersection test,
@@ -437,10 +445,23 @@ function Renderer:get_pos_infos(pos0) -- {{{
--- @param ext u.renderer.RendererExtmark
:filter(function(ext)
if ext.stop[1] ~= nil and ext.stop[2] ~= nil then
return cursor_line0 >= ext.start[1]
and cursor_col0 >= ext.start[2]
and cursor_line0 <= ext.stop[1]
and cursor_col0 < ext.stop[2]
-- 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 (
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]
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])
)
else
return true
end