refactor: organize tests and dry (#49)
* refactor(store): convert singleton to Store.new() factory
Problem: store.lua used module-level _data singleton, making
project-local stores impossible and creating hidden global state.
Solution: introduce Store metatable with all operations as instance
methods. M.new(path) constructs an instance; M.resolve_path()
searches upward for .pending.json and falls back to
config.get().data_path. Singleton module API is removed.
* refactor(diff): accept store instance as parameter
Problem: diff.apply called store singleton methods directly, coupling
it to global state and preventing use with project-local stores.
Solution: change signature to apply(lines, s, hidden_ids?) where s is
a pending.Store instance. All store operations now go through s.
* refactor(buffer): add set_store/store accessors, drop singleton dep
Problem: buffer.lua imported store directly and called singleton
methods, preventing it from working with per-project store instances.
Solution: add module-level _store, M.set_store(s), and M.store()
accessors. open() and render() use _store instead of the singleton.
init.lua will call buffer.set_store(s) before buffer.open().
* refactor(complete,health,sync,plugin): update callers to store instance API
Problem: complete.lua, health.lua, sync/gcal.lua, and plugin/pending.lua
all called singleton store methods directly.
Solution: complete.lua uses buffer.store() for category lookups;
health.lua uses store.new(store.resolve_path()) and reports the
resolved path; gcal.lua calls require('pending').store() for task
access; plugin tab-completion creates ephemeral store instances via
store.new(store.resolve_path()). Add 'init' to the subcommands list.
* feat(init): thread Store instance through init, add :Pending init
Problem: init.lua called singleton store methods throughout, and there
was no way to create a project-local .pending.json file.
Solution: add module-level _store and private get_store() that
lazy-constructs via store.new(store.resolve_path()). Add public
M.store() accessor used by specs and sync backends. M.open() calls
buffer.set_store(get_store()) before buffer.open(). All store
callsites converted to get_store():method(). goto_file() and
add_here() derive the data directory from get_store().path.
Add M.init() which creates .pending.json in cwd and dispatches from
M.command() as ':Pending init'.
* test: update all specs for Store instance API
Problem: every spec used the old singleton API (store.unload(),
store.load(), store.add(), etc.) and diff.apply(lines, hidden).
Solution: lower-level specs (store, diff, views, complete, file) use
s = store.new(path); s:load() directly. Higher-level specs (archive,
edit, filter, status, sync) reset package.loaded['pending'] in
before_each and use pending.store() to access the live instance.
diff.apply calls updated to diff.apply(lines, s, hidden_ids).
* docs(pending): document :Pending init and store resolution
Add *pending-store-resolution* section explaining upward .pending.json
discovery and fallback to the global data_path. Document :Pending init
under COMMANDS. Add a cross-reference from the data_path config field.
* ci: format
* ci: remove unused variable
This commit is contained in:
parent
64b19360b1
commit
0e0568769d
19 changed files with 819 additions and 703 deletions
|
|
@ -1,10 +1,12 @@
|
|||
local config = require('pending.config')
|
||||
local store = require('pending.store')
|
||||
local views = require('pending.views')
|
||||
|
||||
---@class pending.buffer
|
||||
local M = {}
|
||||
|
||||
---@type pending.Store?
|
||||
local _store = nil
|
||||
|
||||
---@type integer?
|
||||
local task_bufnr = nil
|
||||
---@type integer?
|
||||
|
|
@ -41,6 +43,17 @@ function M.current_view_name()
|
|||
return current_view
|
||||
end
|
||||
|
||||
---@param s pending.Store?
|
||||
---@return nil
|
||||
function M.set_store(s)
|
||||
_store = s
|
||||
end
|
||||
|
||||
---@return pending.Store?
|
||||
function M.store()
|
||||
return _store
|
||||
end
|
||||
|
||||
---@return string[]
|
||||
function M.filter_predicates()
|
||||
return _filter_predicates
|
||||
|
|
@ -281,7 +294,7 @@ function M.render(bufnr)
|
|||
current_view = current_view or config.get().default_view
|
||||
local view_label = current_view == 'priority' and 'queue' or current_view
|
||||
vim.api.nvim_buf_set_name(bufnr, 'pending://' .. view_label)
|
||||
local all_tasks = store.active_tasks()
|
||||
local all_tasks = _store and _store:active_tasks() or {}
|
||||
local tasks = {}
|
||||
for _, task in ipairs(all_tasks) do
|
||||
if not _hidden_ids[task.id] then
|
||||
|
|
@ -341,7 +354,9 @@ end
|
|||
---@return integer bufnr
|
||||
function M.open()
|
||||
setup_highlights()
|
||||
store.load()
|
||||
if _store then
|
||||
_store:load()
|
||||
end
|
||||
|
||||
if task_winid and vim.api.nvim_win_is_valid(task_winid) then
|
||||
vim.api.nvim_set_current_win(task_winid)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue