feat: add cancelled task status with configurable state chars

Problem: the task lifecycle only has `pending`, `wip`, `blocked`, and
`done`. There is no way to mark a task as abandoned. Additionally,
state characters (`>`, `=`) are hardcoded rather than reading from
`config.icons`, so customizing them has no effect on rendering or
parsing.

Solution: add a `cancelled` status with default state char `c`, `g/`
keymap, `PendingCancelled` highlight, filter predicate, and archive
support. Unify state chars by making `state_char()`, `parse_buffer()`,
and `infer_status()` read from `config.icons`. Change defaults to
mnemonic chars: `w` (wip), `b` (blocked), `c` (cancelled).
This commit is contained in:
Barrett Ruth 2026-03-12 20:15:35 -04:00
parent 4a37cb64e4
commit 7aeef7420b
Signed by: barrett
GPG key ID: A6C96C9349D2FC81
9 changed files with 109 additions and 45 deletions

View file

@ -43,14 +43,17 @@ function M.parse_buffer(lines)
table.insert(result, { type = 'blank', lnum = i })
elseif id or body then
local stripped = body:match('^- %[.?%] (.*)$') or body
local state_char = body:match('^- %[(.-)%]') or ' '
local priority = state_char == '!' and 1 or 0
local icons = config.get().icons
local state_char = body:match('^- %[(.-)%]') or icons.pending
local priority = state_char == icons.priority and 1 or 0
local status
if state_char == 'x' then
if state_char == icons.done then
status = 'done'
elseif state_char == '>' then
elseif state_char == icons.cancelled then
status = 'cancelled'
elseif state_char == icons.wip then
status = 'wip'
elseif state_char == '=' then
elseif state_char == icons.blocked then
status = 'blocked'
else
status = 'pending'
@ -177,7 +180,7 @@ function M.apply(lines, s, hidden_ids)
end
if entry.status and task.status ~= entry.status then
task.status = entry.status
if entry.status == 'done' then
if entry.status == 'done' or entry.status == 'cancelled' then
task['end'] = now
else
task['end'] = nil