feat(buffer): re-apply inline extmarks after edits
Problem: inline extmarks (checkbox overlays, strikethrough, header highlights) were cleared during edits and only restored on `:w`, leaving the buffer visually bare while editing. Solution: extract `apply_inline_row()` from `apply_extmarks()` and call it via `reapply_dirty_inline()` on `InsertLeave` and normal-mode `TextChanged`. Insert-mode `TextChangedI` still only clears inline marks on dirty rows to avoid overlay flicker while typing.
This commit is contained in:
parent
ec08ca9645
commit
e71d6cdff6
2 changed files with 88 additions and 42 deletions
|
|
@ -116,6 +116,23 @@ function M.clear_dirty_rows()
|
|||
_dirty_rows = {}
|
||||
end
|
||||
|
||||
---@param bufnr integer
|
||||
---@return nil
|
||||
function M.reapply_dirty_inline(bufnr)
|
||||
if not next(_dirty_rows) then
|
||||
return
|
||||
end
|
||||
local icons = config.get().icons
|
||||
for row in pairs(_dirty_rows) do
|
||||
local m = _meta[row]
|
||||
if m then
|
||||
vim.api.nvim_buf_clear_namespace(bufnr, ns_inline, row - 1, row)
|
||||
apply_inline_row(bufnr, row - 1, m, icons)
|
||||
end
|
||||
end
|
||||
_dirty_rows = {}
|
||||
end
|
||||
|
||||
---@param bufnr integer
|
||||
---@return nil
|
||||
function M.attach_bytes(bufnr)
|
||||
|
|
@ -281,6 +298,55 @@ function M.get_fold()
|
|||
end
|
||||
end
|
||||
|
||||
---@param bufnr integer
|
||||
---@param row integer
|
||||
---@param m pending.LineMeta
|
||||
---@param icons table
|
||||
local function apply_inline_row(bufnr, row, m, icons)
|
||||
if m.type == 'filter' then
|
||||
local line = vim.api.nvim_buf_get_lines(bufnr, row, row + 1, false)[1] or ''
|
||||
vim.api.nvim_buf_set_extmark(bufnr, ns_inline, row, 0, {
|
||||
end_col = #line,
|
||||
hl_group = 'PendingFilter',
|
||||
})
|
||||
elseif m.type == 'task' then
|
||||
if m.status == 'done' then
|
||||
local line = vim.api.nvim_buf_get_lines(bufnr, row, row + 1, false)[1] or ''
|
||||
local col_start = line:find('/%d+/') and select(2, line:find('/%d+/')) or 0
|
||||
vim.api.nvim_buf_set_extmark(bufnr, ns_inline, row, col_start, {
|
||||
end_col = #line,
|
||||
hl_group = 'PendingDone',
|
||||
})
|
||||
end
|
||||
local line = vim.api.nvim_buf_get_lines(bufnr, row, row + 1, false)[1] or ''
|
||||
local bracket_col = (line:find('%[') or 1) - 1
|
||||
local icon, icon_hl
|
||||
if m.status == 'done' then
|
||||
icon, icon_hl = icons.done, 'PendingDone'
|
||||
elseif m.priority and m.priority > 0 then
|
||||
icon, icon_hl = icons.priority, 'PendingPriority'
|
||||
else
|
||||
icon, icon_hl = icons.pending, 'Normal'
|
||||
end
|
||||
vim.api.nvim_buf_set_extmark(bufnr, ns_inline, row, bracket_col, {
|
||||
virt_text = { { '[' .. icon .. ']', icon_hl } },
|
||||
virt_text_pos = 'overlay',
|
||||
priority = 100,
|
||||
})
|
||||
elseif m.type == 'header' then
|
||||
local line = vim.api.nvim_buf_get_lines(bufnr, row, row + 1, false)[1] or ''
|
||||
vim.api.nvim_buf_set_extmark(bufnr, ns_inline, row, 0, {
|
||||
end_col = #line,
|
||||
hl_group = 'PendingHeader',
|
||||
})
|
||||
vim.api.nvim_buf_set_extmark(bufnr, ns_inline, row, 0, {
|
||||
virt_text = { { icons.category .. ' ', 'PendingHeader' } },
|
||||
virt_text_pos = 'overlay',
|
||||
priority = 100,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
---@param bufnr integer
|
||||
---@param line_meta pending.LineMeta[]
|
||||
local function apply_extmarks(bufnr, line_meta)
|
||||
|
|
@ -289,13 +355,7 @@ local function apply_extmarks(bufnr, line_meta)
|
|||
vim.api.nvim_buf_clear_namespace(bufnr, ns_inline, 0, -1)
|
||||
for i, m in ipairs(line_meta) do
|
||||
local row = i - 1
|
||||
if m.type == 'filter' then
|
||||
local line = vim.api.nvim_buf_get_lines(bufnr, row, row + 1, false)[1] or ''
|
||||
vim.api.nvim_buf_set_extmark(bufnr, ns_inline, row, 0, {
|
||||
end_col = #line,
|
||||
hl_group = 'PendingFilter',
|
||||
})
|
||||
elseif m.type == 'task' then
|
||||
if m.type == 'task' then
|
||||
local due_hl = m.overdue and 'PendingOverdue' or 'PendingDue'
|
||||
local virt_parts = {}
|
||||
if m.show_category and m.category then
|
||||
|
|
@ -316,41 +376,8 @@ local function apply_extmarks(bufnr, line_meta)
|
|||
virt_text_pos = 'eol',
|
||||
})
|
||||
end
|
||||
if m.status == 'done' then
|
||||
local line = vim.api.nvim_buf_get_lines(bufnr, row, row + 1, false)[1] or ''
|
||||
local col_start = line:find('/%d+/') and select(2, line:find('/%d+/')) or 0
|
||||
vim.api.nvim_buf_set_extmark(bufnr, ns_inline, row, col_start, {
|
||||
end_col = #line,
|
||||
hl_group = 'PendingDone',
|
||||
})
|
||||
end
|
||||
local line = vim.api.nvim_buf_get_lines(bufnr, row, row + 1, false)[1] or ''
|
||||
local bracket_col = (line:find('%[') or 1) - 1
|
||||
local icon, icon_hl
|
||||
if m.status == 'done' then
|
||||
icon, icon_hl = icons.done, 'PendingDone'
|
||||
elseif m.priority and m.priority > 0 then
|
||||
icon, icon_hl = icons.priority, 'PendingPriority'
|
||||
else
|
||||
icon, icon_hl = icons.pending, 'Normal'
|
||||
end
|
||||
vim.api.nvim_buf_set_extmark(bufnr, ns_inline, row, bracket_col, {
|
||||
virt_text = { { '[' .. icon .. ']', icon_hl } },
|
||||
virt_text_pos = 'overlay',
|
||||
priority = 100,
|
||||
})
|
||||
elseif m.type == 'header' then
|
||||
local line = vim.api.nvim_buf_get_lines(bufnr, row, row + 1, false)[1] or ''
|
||||
vim.api.nvim_buf_set_extmark(bufnr, ns_inline, row, 0, {
|
||||
end_col = #line,
|
||||
hl_group = 'PendingHeader',
|
||||
})
|
||||
vim.api.nvim_buf_set_extmark(bufnr, ns_inline, row, 0, {
|
||||
virt_text = { { icons.category .. ' ', 'PendingHeader' } },
|
||||
virt_text_pos = 'overlay',
|
||||
priority = 100,
|
||||
})
|
||||
end
|
||||
apply_inline_row(bufnr, row, m, icons)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -251,7 +251,7 @@ function M._setup_autocmds(bufnr)
|
|||
end
|
||||
end,
|
||||
})
|
||||
vim.api.nvim_create_autocmd({ 'TextChanged', 'TextChangedI' }, {
|
||||
vim.api.nvim_create_autocmd('TextChangedI', {
|
||||
group = group,
|
||||
buffer = bufnr,
|
||||
callback = function()
|
||||
|
|
@ -263,6 +263,25 @@ function M._setup_autocmds(bufnr)
|
|||
end
|
||||
end,
|
||||
})
|
||||
vim.api.nvim_create_autocmd('TextChanged', {
|
||||
group = group,
|
||||
buffer = bufnr,
|
||||
callback = function()
|
||||
if not vim.bo[bufnr].modified then
|
||||
return
|
||||
end
|
||||
buffer.reapply_dirty_inline(bufnr)
|
||||
end,
|
||||
})
|
||||
vim.api.nvim_create_autocmd('InsertLeave', {
|
||||
group = group,
|
||||
buffer = bufnr,
|
||||
callback = function()
|
||||
if vim.bo[bufnr].modified then
|
||||
buffer.reapply_dirty_inline(bufnr)
|
||||
end
|
||||
end,
|
||||
})
|
||||
vim.api.nvim_create_autocmd('WinClosed', {
|
||||
group = group,
|
||||
callback = function(ev)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue