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 = {}
|
_dirty_rows = {}
|
||||||
end
|
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
|
---@param bufnr integer
|
||||||
---@return nil
|
---@return nil
|
||||||
function M.attach_bytes(bufnr)
|
function M.attach_bytes(bufnr)
|
||||||
|
|
@ -281,6 +298,55 @@ function M.get_fold()
|
||||||
end
|
end
|
||||||
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 bufnr integer
|
||||||
---@param line_meta pending.LineMeta[]
|
---@param line_meta pending.LineMeta[]
|
||||||
local function apply_extmarks(bufnr, line_meta)
|
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)
|
vim.api.nvim_buf_clear_namespace(bufnr, ns_inline, 0, -1)
|
||||||
for i, m in ipairs(line_meta) do
|
for i, m in ipairs(line_meta) do
|
||||||
local row = i - 1
|
local row = i - 1
|
||||||
if m.type == 'filter' then
|
if m.type == 'task' 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
|
|
||||||
local due_hl = m.overdue and 'PendingOverdue' or 'PendingDue'
|
local due_hl = m.overdue and 'PendingOverdue' or 'PendingDue'
|
||||||
local virt_parts = {}
|
local virt_parts = {}
|
||||||
if m.show_category and m.category then
|
if m.show_category and m.category then
|
||||||
|
|
@ -316,41 +376,8 @@ local function apply_extmarks(bufnr, line_meta)
|
||||||
virt_text_pos = 'eol',
|
virt_text_pos = 'eol',
|
||||||
})
|
})
|
||||||
end
|
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
|
end
|
||||||
|
apply_inline_row(bufnr, row, m, icons)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -251,7 +251,7 @@ function M._setup_autocmds(bufnr)
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
vim.api.nvim_create_autocmd({ 'TextChanged', 'TextChangedI' }, {
|
vim.api.nvim_create_autocmd('TextChangedI', {
|
||||||
group = group,
|
group = group,
|
||||||
buffer = bufnr,
|
buffer = bufnr,
|
||||||
callback = function()
|
callback = function()
|
||||||
|
|
@ -263,6 +263,25 @@ function M._setup_autocmds(bufnr)
|
||||||
end
|
end
|
||||||
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', {
|
vim.api.nvim_create_autocmd('WinClosed', {
|
||||||
group = group,
|
group = group,
|
||||||
callback = function(ev)
|
callback = function(ev)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue