From 1258674a1efa640f555b7e01bba92d0a52f5b085 Mon Sep 17 00:00:00 2001 From: Barrett Ruth Date: Mon, 9 Mar 2026 00:17:14 -0400 Subject: [PATCH] fix(buffer): infer task status from line text in `reapply_dirty_inline` Problem: `on_bytes` inserts bare `{ type = 'task' }` meta entries with no `status` field for any new lines (paste, undo, native edits). When meta positions also shift incorrectly (e.g. `P` paste above), existing meta with the wrong status ends up on the wrong row. This causes done tasks to lose their `PendingDone` highlight and pending tasks to appear greyed out. Solution: always re-infer `status` from the actual buffer line text for dirty task rows before applying extmarks. The checkbox character (`[x]`, `[>]`, `[=]`, `[ ]`) is the source of truth, with fallback to the existing meta status if the line doesn't match a task pattern. --- lua/pending/buffer.lua | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/lua/pending/buffer.lua b/lua/pending/buffer.lua index c543c7d..250ed8e 100644 --- a/lua/pending/buffer.lua +++ b/lua/pending/buffer.lua @@ -182,6 +182,23 @@ local function apply_inline_row(bufnr, row, m, icons) end end +---@param line string +---@return string? +local function infer_status(line) + local ch = line:match('^/%d+/- %[(.)%]') or line:match('^- %[(.)%]') + if not ch then + return nil + end + if ch == 'x' then + return 'done' + elseif ch == '>' then + return 'wip' + elseif ch == '=' then + return 'blocked' + end + return 'pending' +end + ---@param bufnr integer ---@return nil function M.reapply_dirty_inline(bufnr) @@ -191,6 +208,10 @@ function M.reapply_dirty_inline(bufnr) local icons = config.get().icons for row in pairs(_dirty_rows) do local m = _meta[row] + if m and m.type == 'task' then + local line = vim.api.nvim_buf_get_lines(bufnr, row - 1, row, false)[1] or '' + m.status = infer_status(line) or m.status + end if m then vim.api.nvim_buf_clear_namespace(bufnr, ns_inline, row - 1, row) apply_inline_row(bufnr, row - 1, m, icons)