feat: complete task editing coverage
Problem: the task editing surface had gaps — category and recurrence had no keymaps, `:Pending edit` required knowing the task ID, tasks couldn't be reordered with a keymap, priority was binary (0/1), and `wip`/`blocked` states were documented but unimplemented. Solution: fill every cell so every property is editable in every way. - `gc`/`gr` keymaps for category select and recurrence prompt - cursor-aware `:Pending edit` (omit ID to use task under cursor) - `J`/`K` keymaps to reorder tasks within a category - multi-level priorities (`max_priority` config, `g!` cycles 0→1→2→3→0) - `+!!`/`+!!!` tokens in `:Pending edit`, `:Pending add`, `parse.body()` - `PendingPriority2`/`PendingPriority3` highlight groups - `gw`/`gb` keymaps toggle `wip`/`blocked` status - `>`/`=` state chars in buffer rendering and diff parsing - `PendingWip`/`PendingBlocked` highlight groups - sort order: wip → pending → blocked → done - `wip`/`blocked` filter predicates and icons
This commit is contained in:
parent
073541424e
commit
6c3869b3c4
9 changed files with 498 additions and 101 deletions
|
|
@ -41,9 +41,32 @@ local function format_due(due)
|
|||
return formatted
|
||||
end
|
||||
|
||||
---@type table<string, integer>
|
||||
local status_rank = { wip = 0, pending = 1, blocked = 2, done = 3 }
|
||||
|
||||
---@param task pending.Task
|
||||
---@return string
|
||||
local function state_char(task)
|
||||
if task.status == 'done' then
|
||||
return 'x'
|
||||
elseif task.status == 'wip' then
|
||||
return '>'
|
||||
elseif task.status == 'blocked' then
|
||||
return '='
|
||||
elseif task.priority > 0 then
|
||||
return '!'
|
||||
end
|
||||
return ' '
|
||||
end
|
||||
|
||||
---@param tasks pending.Task[]
|
||||
local function sort_tasks(tasks)
|
||||
table.sort(tasks, function(a, b)
|
||||
local ra = status_rank[a.status] or 1
|
||||
local rb = status_rank[b.status] or 1
|
||||
if ra ~= rb then
|
||||
return ra < rb
|
||||
end
|
||||
if a.priority ~= b.priority then
|
||||
return a.priority > b.priority
|
||||
end
|
||||
|
|
@ -57,6 +80,11 @@ end
|
|||
---@param tasks pending.Task[]
|
||||
local function sort_tasks_priority(tasks)
|
||||
table.sort(tasks, function(a, b)
|
||||
local ra = status_rank[a.status] or 1
|
||||
local rb = status_rank[b.status] or 1
|
||||
if ra ~= rb then
|
||||
return ra < rb
|
||||
end
|
||||
if a.priority ~= b.priority then
|
||||
return a.priority > b.priority
|
||||
end
|
||||
|
|
@ -95,7 +123,7 @@ function M.category_view(tasks)
|
|||
by_cat[cat] = {}
|
||||
done_by_cat[cat] = {}
|
||||
end
|
||||
if task.status == 'done' then
|
||||
if task.status == 'done' or task.status == 'deleted' then
|
||||
table.insert(done_by_cat[cat], task)
|
||||
else
|
||||
table.insert(by_cat[cat], task)
|
||||
|
|
@ -146,7 +174,7 @@ function M.category_view(tasks)
|
|||
|
||||
for _, task in ipairs(all) do
|
||||
local prefix = '/' .. task.id .. '/'
|
||||
local state = task.status == 'done' and 'x' or (task.priority > 0 and '!' or ' ')
|
||||
local state = state_char(task)
|
||||
local line = prefix .. '- [' .. state .. '] ' .. task.description
|
||||
table.insert(lines, line)
|
||||
table.insert(meta, {
|
||||
|
|
@ -157,7 +185,7 @@ function M.category_view(tasks)
|
|||
status = task.status,
|
||||
category = cat,
|
||||
priority = task.priority,
|
||||
overdue = task.status == 'pending' and task.due ~= nil and parse.is_overdue(task.due)
|
||||
overdue = task.status ~= 'done' and task.due ~= nil and parse.is_overdue(task.due)
|
||||
or nil,
|
||||
recur = task.recur,
|
||||
})
|
||||
|
|
@ -209,7 +237,7 @@ function M.priority_view(tasks)
|
|||
status = task.status,
|
||||
category = task.category,
|
||||
priority = task.priority,
|
||||
overdue = task.status == 'pending' and task.due ~= nil and parse.is_overdue(task.due) or nil,
|
||||
overdue = task.status ~= 'done' and task.due ~= nil and parse.is_overdue(task.due) or nil,
|
||||
show_category = true,
|
||||
recur = task.recur,
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue