Commit graph

8 commits

Author SHA1 Message Date
ebd61ba870 fix: resolve remaining LuaLS type errors
Problem: CI lua-typecheck-action reported three categories of errors:
1. parse.lua - multi-assignment of tonumber() results left y/m/d typed
   as number? rather than integer, failing os.time()'s field types
2. gcal.lua - url_encode returned str:gsub() which yields string+integer
   but the annotation declared @return string (redundant-return-value)
3. gcal.lua - calendar_id typed string? from find_or_create_calendar was
   passed to functions expecting string; the existing `if err` guard did
   not narrow the type for LuaLS

Solution: replace the y/m/d multi-assignment with yn/mn/dn locals whose
types resolve cleanly to integer; wrap the gsub return in parentheses to
discard the count; add `or not calendar_id` to the error guard so LuaLS
narrows calendar_id to string for the rest of the scope.
2026-02-24 18:50:28 -05:00
0522cf3263 feat(init): multi-level undo, quickfix due, BufEnter reload
Problem: undo was single-level with shallow references; no way to
query due/overdue tasks via quickfix; two instances sharing
tasks.json would diverge silently.

Solution: replace _undo_state with _undo_states[] (cap 20, deep
copies via store.snapshot()); add M.due() which populates the
quickfix list with overdue/due-today tasks; add BufEnter autocmd
that reloads from disk when the buffer is unmodified; expand
show_help() with folds, :Pending due, relative date syntax,
PendingOverdue, and empty-input date clearing.
2026-02-24 18:44:13 -05:00
ebe9368fad feat(buffer): add category folds via foldexpr
Problem: category_view had no fold support, making it harder to
focus on one category in large lists.

Solution: add M.get_fold() returning '>1' for headers, '1' for task
lines, and '0' for blanks. M.render() now sets foldmethod=expr
(foldlevel=99) in category view and foldmethod=manual in priority.
2026-02-24 18:44:13 -05:00
c8c35ab534 feat(store): add snapshot() and atomic json write
Problem: the single-level undo used shallow references so mutations
during diff.apply() corrupted the saved state. JSON writes were also
non-atomic, risking partial writes on crash.

Solution: add M.snapshot() which deep-copies active tasks (including
_extra). Change M.save() to write a .tmp file then rename atomically.
2026-02-24 18:44:13 -05:00
00ea92ce33 fix(gcal): add LuaCATS annotations and resolve type errors
Problem: gcal.lua had ~10 LuaLS errors from untyped credential and
token tables, string|osdate casts, and untyped _gcal_event_id
field access.

Solution: add pending.GcalCredentials and pending.GcalTokens class
definitions, annotate all local functions with @param/@return, add
--[[@as string]] casts on os.date returns, and fix _gcal_event_id
access to use bracket notation with casts.
2026-02-24 18:44:13 -05:00
Barrett Ruth
ce8decc2b0 fix(parse): cast os.date('*t') return to osdate (#3)
Problem: LuaLS types os.date('*t') as string|osdate, causing type
errors when accessing .year, .month, .day, .wday fields in
is_valid_date and resolve_date.

Solution: add --[[@as osdate]] casts on both os.date('*t') calls.
2026-02-24 18:40:46 -05:00
Barrett Ruth
3a35fab6cf feat: overdue highlighting, relative dates, undo write, buffer mappings (#1)
* feat(config): add category_order field

Problem: category display order was always insertion order with no way
to configure it.

Solution: add category_order to config defaults so users can declare a
preferred category ordering; unspecified categories append after.

* feat(parse): add relative date resolution

Problem: due dates required full YYYY-MM-DD input, adding friction for
common cases like "today" or "next monday".

Solution: add resolve_date() supporting today, tomorrow, +Nd, and
weekday abbreviations; extend inline token parsing to resolve relative
values before falling back to strict date validation.

* feat(views): overdue flag, category in priority view, category ordering

Problem: overdue tasks were visually indistinct from upcoming ones;
priority view had no category context; category display order was not
configurable.

Solution: compute overdue meta flag for pending tasks past their due
date; set show_category on priority view task meta; reorder categories
according to config.category_order when present.

* feat(buffer): overdue highlight, category virt text in priority view

Problem: overdue tasks had no visual distinction; priority view showed
no category context alongside due dates.

Solution: add PendingOverdue highlight group; render category name as
right-aligned virtual text in priority view, composited with the due
date when both are present.

* feat(init): undo write and buffer-local default mappings

Problem: _undo_state was captured on every save but never consumed;
toggle_priority and prompt_date had no buffer-local defaults, requiring
manual <Plug> configuration.

Solution: implement undo_write() to restore pre-save task state; add !,
d, and U as buffer-local defaults following fugitive's philosophy of
owning the buffer; expose :Pending undo as a command alias.

* test(views): add views spec

Problem: views.lua had no test coverage.

Solution: add 26 tests covering category_view and priority_view
including sort order, line format, overdue detection, show_category
meta, and category_order config behavior.

* test(archive): add archive spec

Problem: archive had no test coverage.

Solution: add 9 tests covering cutoff logic, custom day counts, pending
task preservation, deleted task cleanup, and notify output.

* docs: add vimdoc

Problem: no :help documentation existed.

Solution: add doc/pending.txt covering all features — commands,
mappings, views, configuration, Google Calendar sync, highlight groups,
data format, and health check — following standard vimdoc conventions.

* ci: format

* fix: resolve lint and type check errors

Problem: selene flagged unused variables in new spec files; LuaLS
flagged os.date/os.time return type mismatches, integer? assignments,
and stale task.Task/task.GcalConfig type references.

Solution: prefix unused spec variables with _ or drop unnecessary
assignments; add --[[@as string/integer]] casts for os.date and
os.time calls; add category_order field to pending.Config annotation;
fix task.GcalConfig -> pending.GcalConfig and task.Task[] ->
pending.Task[]; add nil guards on meta[row].id before store calls;
cast store.data() return to non-optional.

* ci: format

* fix: sync

* ci: format
2026-02-24 18:33:07 -05:00
53ab1cc000 feat: rename 2026-02-24 15:21:44 -05:00