* refactor: tighten LuaCATS annotations across modules Problem: type annotations repeated inline unions with no aliases, used `table<string, any>` where structured types exist, and had loose `string` where union types should be used. Solution: add `pending.TaskStatus`, `pending.RecurMode`, `pending.TaskExtra`, `pending.ForgeType`, `pending.ForgeState`, `pending.ForgeAuthStatus` aliases and `pending.SyncBackend` interface. Replace inline unions and loose types with the new aliases in `store.lua`, `forge.lua`, `config.lua`, `diff.lua`, `views.lua`, `parse.lua`, `init.lua`, and `oauth.lua`. * refactor: canonicalize internal metadata field names Problem: `pending.Metadata` used shorthand field names (`cat`, `rec`, `rec_mode`) matching user-facing token syntax, coupling internal representation to config. `RecurSpec.from_completion` used a boolean where a `pending.RecurMode` alias exists. `category_syntax` was hardcoded to `'cat'` with no config option. Solution: rename `Metadata` fields to `category`/`recur`/`recur_mode`, add `category_syntax` config option (default `'cat'`), rename `ParsedEntry` fields to match, replace `RecurSpec.from_completion` with `mode: pending.RecurMode`, and restore `[string]` indexer on `pending.ForgeConfig` alongside explicit fields.
223 lines
5.2 KiB
Lua
223 lines
5.2 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 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
|
|
|
|
---@class pending.CategoryViewConfig
|
|
---@field order? string[]
|
|
---@field folding? boolean|pending.FoldingConfig
|
|
|
|
---@class pending.QueueViewConfig
|
|
|
|
---@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 = {},
|
|
},
|
|
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',
|
|
priority_up = '<C-a>',
|
|
priority_down = '<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 = '>',
|
|
blocked = '=',
|
|
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
|