pending.nvim/lua/pending/config.lua
Barrett Ruth 7c3ba31c43
feat: add cancelled task status with configurable state chars (#158)
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).
2026-03-12 20:55:21 -04:00

234 lines
5.6 KiB
Lua

---@class pending.FoldingConfig
---@field foldtext? string|false
---@class pending.ResolvedFolding
---@field enabled boolean
---@field foldtext string|false
---@class pending.Icons
---@field pending string
---@field done string
---@field priority string
---@field wip string
---@field blocked string
---@field cancelled string
---@field due string
---@field recur string
---@field category string
---@class pending.GcalConfig
---@field remote_delete? boolean
---@field credentials_path? string
---@field client_id? string
---@field client_secret? string
---@class pending.GtasksConfig
---@field remote_delete? boolean
---@field credentials_path? string
---@field client_id? string
---@field client_secret? string
---@class pending.S3Config
---@field bucket string
---@field key? string
---@field profile? string
---@field region? string
---@class pending.ForgeInstanceConfig
---@field icon? string
---@field issue_format? string
---@field instances? string[]
---@field shorthand? string
---@class pending.ForgeConfig
---@field close? boolean
---@field validate? boolean
---@field warn_missing_cli? boolean
---@field github? pending.ForgeInstanceConfig
---@field gitlab? pending.ForgeInstanceConfig
---@field codeberg? pending.ForgeInstanceConfig
---@field [string] pending.ForgeInstanceConfig
---@class pending.SyncConfig
---@field remote_delete? boolean
---@field gcal? pending.GcalConfig
---@field gtasks? pending.GtasksConfig
---@field s3? pending.S3Config
---@class pending.Keymaps
---@field close? string|false
---@field toggle? string|false
---@field view? string|false
---@field priority? string|false
---@field date? string|false
---@field undo? string|false
---@field filter? string|false
---@field open_line? string|false
---@field open_line_above? string|false
---@field a_task? string|false
---@field i_task? string|false
---@field a_category? string|false
---@field i_category? string|false
---@field next_header? string|false
---@field prev_header? string|false
---@field next_task? string|false
---@field prev_task? string|false
---@field category? string|false
---@field recur? string|false
---@field move_down? string|false
---@field move_up? string|false
---@field wip? string|false
---@field blocked? string|false
---@field priority_up_visual? string|false
---@field priority_down_visual? string|false
---@field cancelled? string|false
---@class pending.CategoryViewConfig
---@field order? string[]
---@field folding? boolean|pending.FoldingConfig
---@class pending.QueueViewConfig
---@field sort? string[]
---@class pending.ViewConfig
---@field default? 'category'|'priority'
---@field eol_format? string
---@field category? pending.CategoryViewConfig
---@field queue? pending.QueueViewConfig
---@class pending.Config
---@field data_path string
---@field default_category string
---@field date_format string
---@field category_syntax string
---@field date_syntax string
---@field recur_syntax string
---@field someday_date string
---@field input_date_formats? string[]
---@field drawer_height? integer
---@field debug? boolean
---@field keymaps pending.Keymaps
---@field view pending.ViewConfig
---@field max_priority? integer
---@field sync? pending.SyncConfig
---@field forge? pending.ForgeConfig
---@field icons pending.Icons
---@class pending.config
local M = {}
---@type pending.Config
local defaults = {
data_path = vim.fn.stdpath('data') .. '/pending/tasks.json',
default_category = 'Todo',
date_format = '%b %d',
category_syntax = 'cat',
date_syntax = 'due',
recur_syntax = 'rec',
someday_date = '9999-12-30',
max_priority = 3,
view = {
default = 'category',
eol_format = '%c %r %d',
category = {
order = {},
folding = true,
},
queue = {
sort = { 'status', 'priority', 'due', 'order', 'id' },
},
},
keymaps = {
close = 'q',
toggle = '<CR>',
view = '<Tab>',
priority = 'g!',
date = 'gd',
undo = 'gz',
filter = 'gf',
open_line = 'o',
open_line_above = 'O',
a_task = 'at',
i_task = 'it',
a_category = 'aC',
i_category = 'iC',
next_header = ']]',
prev_header = '[[',
next_task = ']t',
prev_task = '[t',
category = 'gc',
recur = 'gr',
move_down = 'J',
move_up = 'K',
wip = 'gw',
blocked = 'gb',
cancelled = 'g/',
priority_up = '<C-a>',
priority_down = '<C-x>',
priority_up_visual = 'g<C-a>',
priority_down_visual = 'g<C-x>',
},
sync = {},
forge = {
close = false,
validate = false,
warn_missing_cli = true,
github = {
icon = '',
issue_format = '%i %o/%r#%n',
instances = {},
},
gitlab = {
icon = '',
issue_format = '%i %o/%r#%n',
instances = {},
},
codeberg = {
icon = '',
issue_format = '%i %o/%r#%n',
instances = {},
},
},
icons = {
pending = ' ',
done = 'x',
priority = '!',
wip = 'w',
blocked = 'b',
cancelled = 'c',
due = '.',
recur = '~',
category = '#',
},
}
---@type pending.Config?
local _resolved = nil
---@return pending.Config
function M.get()
if _resolved then
return _resolved
end
local user = vim.g.pending or {}
_resolved = vim.tbl_deep_extend('force', defaults, user)
return _resolved
end
---@return nil
function M.reset()
_resolved = nil
end
---@return pending.ResolvedFolding
function M.resolve_folding()
local raw = M.get().view.category.folding
if raw == false then
return { enabled = false, foldtext = false }
elseif raw == true or raw == nil then
return { enabled = true, foldtext = '%c (%n tasks)' }
end
return { enabled = true, foldtext = raw.foldtext or false }
end
return M