Compare commits
No commits in common. "1f4a43fc0199c219fbdbcc43cfc513bc803fe222" and "c57cc0845bf0ff1330ae26e4137124cd58490663" have entirely different histories.
1f4a43fc01
...
c57cc0845b
4 changed files with 5 additions and 644 deletions
|
|
@ -390,178 +390,6 @@ function M.due()
|
|||
vim.cmd('copen')
|
||||
end
|
||||
|
||||
---@param token string
|
||||
---@return string|nil field
|
||||
---@return any value
|
||||
---@return string|nil err
|
||||
local function parse_edit_token(token)
|
||||
local recur = require('pending.recur')
|
||||
local cfg = require('pending.config').get()
|
||||
local dk = cfg.date_syntax or 'due'
|
||||
local rk = cfg.recur_syntax or 'rec'
|
||||
|
||||
if token == '+!' then
|
||||
return 'priority', 1, nil
|
||||
end
|
||||
if token == '-!' then
|
||||
return 'priority', 0, nil
|
||||
end
|
||||
if token == '-due' or token == '-' .. dk then
|
||||
return 'due', vim.NIL, nil
|
||||
end
|
||||
if token == '-cat' then
|
||||
return 'category', vim.NIL, nil
|
||||
end
|
||||
if token == '-rec' or token == '-' .. rk then
|
||||
return 'recur', vim.NIL, nil
|
||||
end
|
||||
|
||||
local due_val = token:match('^' .. vim.pesc(dk) .. ':(.+)$')
|
||||
if due_val then
|
||||
local resolved = parse.resolve_date(due_val)
|
||||
if resolved then
|
||||
return 'due', resolved, nil
|
||||
end
|
||||
if
|
||||
due_val:match('^%d%d%d%d%-%d%d%-%d%d$') or due_val:match('^%d%d%d%d%-%d%d%-%d%dT%d%d:%d%d$')
|
||||
then
|
||||
return 'due', due_val, nil
|
||||
end
|
||||
return nil,
|
||||
nil,
|
||||
'Invalid date: ' .. due_val .. '. Use YYYY-MM-DD, today, tomorrow, +Nd, weekday names, etc.'
|
||||
end
|
||||
|
||||
local cat_val = token:match('^cat:(.+)$')
|
||||
if cat_val then
|
||||
return 'category', cat_val, nil
|
||||
end
|
||||
|
||||
local rec_val = token:match('^' .. vim.pesc(rk) .. ':(.+)$')
|
||||
if rec_val then
|
||||
local raw_spec = rec_val
|
||||
local rec_mode = nil
|
||||
if raw_spec:sub(1, 1) == '!' then
|
||||
rec_mode = 'completion'
|
||||
raw_spec = raw_spec:sub(2)
|
||||
end
|
||||
if not recur.validate(raw_spec) then
|
||||
return nil, nil, 'Invalid recurrence pattern: ' .. rec_val
|
||||
end
|
||||
return 'recur', { spec = raw_spec, mode = rec_mode }, nil
|
||||
end
|
||||
|
||||
return nil,
|
||||
nil,
|
||||
'Unknown operation: '
|
||||
.. token
|
||||
.. '. Valid: '
|
||||
.. dk
|
||||
.. ':<date>, cat:<name>, '
|
||||
.. rk
|
||||
.. ':<pattern>, +!, -!, -'
|
||||
.. dk
|
||||
.. ', -cat, -'
|
||||
.. rk
|
||||
end
|
||||
|
||||
---@param id_str string
|
||||
---@param rest string
|
||||
---@return nil
|
||||
function M.edit(id_str, rest)
|
||||
if not id_str or id_str == '' then
|
||||
vim.notify(
|
||||
'Usage: :Pending edit <id> [due:<date>] [cat:<name>] [rec:<pattern>] [+!] [-!] [-due] [-cat] [-rec]',
|
||||
vim.log.levels.ERROR
|
||||
)
|
||||
return
|
||||
end
|
||||
|
||||
local id = tonumber(id_str)
|
||||
if not id then
|
||||
vim.notify('Invalid task ID: ' .. id_str, vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
store.load()
|
||||
local task = store.get(id)
|
||||
if not task then
|
||||
vim.notify('No task with ID ' .. id .. '.', vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
if not rest or rest == '' then
|
||||
vim.notify(
|
||||
'Usage: :Pending edit <id> [due:<date>] [cat:<name>] [rec:<pattern>] [+!] [-!] [-due] [-cat] [-rec]',
|
||||
vim.log.levels.ERROR
|
||||
)
|
||||
return
|
||||
end
|
||||
|
||||
local tokens = {}
|
||||
for tok in rest:gmatch('%S+') do
|
||||
table.insert(tokens, tok)
|
||||
end
|
||||
|
||||
local updates = {}
|
||||
local feedback = {}
|
||||
|
||||
for _, tok in ipairs(tokens) do
|
||||
local field, value, err = parse_edit_token(tok)
|
||||
if err then
|
||||
vim.notify(err, vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
if field == 'recur' then
|
||||
if value == vim.NIL then
|
||||
updates.recur = vim.NIL
|
||||
updates.recur_mode = vim.NIL
|
||||
table.insert(feedback, 'recurrence removed')
|
||||
else
|
||||
updates.recur = value.spec
|
||||
updates.recur_mode = value.mode
|
||||
table.insert(feedback, 'recurrence set to ' .. value.spec)
|
||||
end
|
||||
elseif field == 'due' then
|
||||
if value == vim.NIL then
|
||||
updates.due = vim.NIL
|
||||
table.insert(feedback, 'due date removed')
|
||||
else
|
||||
updates.due = value
|
||||
table.insert(feedback, 'due date set to ' .. tostring(value))
|
||||
end
|
||||
elseif field == 'category' then
|
||||
if value == vim.NIL then
|
||||
updates.category = vim.NIL
|
||||
table.insert(feedback, 'category removed')
|
||||
else
|
||||
updates.category = value
|
||||
table.insert(feedback, 'category set to ' .. tostring(value))
|
||||
end
|
||||
elseif field == 'priority' then
|
||||
updates.priority = value
|
||||
table.insert(feedback, value == 1 and 'priority added' or 'priority removed')
|
||||
end
|
||||
end
|
||||
|
||||
local snapshot = store.snapshot()
|
||||
local stack = store.undo_stack()
|
||||
table.insert(stack, snapshot)
|
||||
if #stack > UNDO_MAX then
|
||||
table.remove(stack, 1)
|
||||
end
|
||||
|
||||
store.update(id, updates)
|
||||
store.save()
|
||||
|
||||
local bufnr = buffer.bufnr()
|
||||
if bufnr and vim.api.nvim_buf_is_valid(bufnr) then
|
||||
buffer.render(bufnr)
|
||||
end
|
||||
|
||||
vim.notify('Task #' .. id .. ' updated: ' .. table.concat(feedback, ', '))
|
||||
end
|
||||
|
||||
---@param args string
|
||||
---@return nil
|
||||
function M.command(args)
|
||||
|
|
@ -572,9 +400,6 @@ function M.command(args)
|
|||
local cmd, rest = args:match('^(%S+)%s*(.*)')
|
||||
if cmd == 'add' then
|
||||
M.add(rest)
|
||||
elseif cmd == 'edit' then
|
||||
local id_str, edit_rest = rest:match('^(%S+)%s*(.*)')
|
||||
M.edit(id_str, edit_rest)
|
||||
elseif cmd == 'sync' then
|
||||
M.sync()
|
||||
elseif cmd == 'archive' then
|
||||
|
|
|
|||
|
|
@ -293,11 +293,7 @@ function M.update(id, fields)
|
|||
local now = timestamp()
|
||||
for k, v in pairs(fields) do
|
||||
if k ~= 'id' and k ~= 'entry' then
|
||||
if v == vim.NIL then
|
||||
task[k] = nil
|
||||
else
|
||||
task[k] = v
|
||||
end
|
||||
task[k] = v
|
||||
end
|
||||
end
|
||||
task.modified = now
|
||||
|
|
|
|||
|
|
@ -3,173 +3,17 @@ if vim.g.loaded_pending then
|
|||
end
|
||||
vim.g.loaded_pending = true
|
||||
|
||||
---@return string[]
|
||||
local function edit_field_candidates()
|
||||
local cfg = require('pending.config').get()
|
||||
local dk = cfg.date_syntax or 'due'
|
||||
local rk = cfg.recur_syntax or 'rec'
|
||||
return {
|
||||
dk .. ':',
|
||||
'cat:',
|
||||
rk .. ':',
|
||||
'+!',
|
||||
'-!',
|
||||
'-' .. dk,
|
||||
'-cat',
|
||||
'-' .. rk,
|
||||
}
|
||||
end
|
||||
|
||||
---@return string[]
|
||||
local function edit_date_values()
|
||||
return {
|
||||
'today',
|
||||
'tomorrow',
|
||||
'yesterday',
|
||||
'+1d',
|
||||
'+2d',
|
||||
'+3d',
|
||||
'+1w',
|
||||
'+2w',
|
||||
'+1m',
|
||||
'mon',
|
||||
'tue',
|
||||
'wed',
|
||||
'thu',
|
||||
'fri',
|
||||
'sat',
|
||||
'sun',
|
||||
'eod',
|
||||
'eow',
|
||||
'eom',
|
||||
'eoq',
|
||||
'eoy',
|
||||
'sow',
|
||||
'som',
|
||||
'soq',
|
||||
'soy',
|
||||
'later',
|
||||
}
|
||||
end
|
||||
|
||||
---@return string[]
|
||||
local function edit_recur_values()
|
||||
local ok, recur = pcall(require, 'pending.recur')
|
||||
if not ok then
|
||||
return {}
|
||||
end
|
||||
local result = {}
|
||||
for _, s in ipairs(recur.shorthand_list()) do
|
||||
table.insert(result, s)
|
||||
end
|
||||
for _, s in ipairs(recur.shorthand_list()) do
|
||||
table.insert(result, '!' .. s)
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
---@param lead string
|
||||
---@param candidates string[]
|
||||
---@return string[]
|
||||
local function filter_candidates(lead, candidates)
|
||||
return vim.tbl_filter(function(s)
|
||||
return s:find(lead, 1, true) == 1
|
||||
end, candidates)
|
||||
end
|
||||
|
||||
---@param arg_lead string
|
||||
---@param cmd_line string
|
||||
---@return string[]
|
||||
local function complete_edit(arg_lead, cmd_line)
|
||||
local cfg = require('pending.config').get()
|
||||
local dk = cfg.date_syntax or 'due'
|
||||
local rk = cfg.recur_syntax or 'rec'
|
||||
|
||||
local after_edit = cmd_line:match('^Pending%s+edit%s+(.*)')
|
||||
if not after_edit then
|
||||
return {}
|
||||
end
|
||||
|
||||
local parts = {}
|
||||
for part in after_edit:gmatch('%S+') do
|
||||
table.insert(parts, part)
|
||||
end
|
||||
|
||||
local trailing_space = after_edit:match('%s$')
|
||||
if #parts == 0 or (#parts == 1 and not trailing_space) then
|
||||
local store = require('pending.store')
|
||||
store.load()
|
||||
local ids = {}
|
||||
for _, task in ipairs(store.active_tasks()) do
|
||||
table.insert(ids, tostring(task.id))
|
||||
end
|
||||
return filter_candidates(arg_lead, ids)
|
||||
end
|
||||
|
||||
local prefix = arg_lead:match('^(' .. vim.pesc(dk) .. ':)(.*)$')
|
||||
if prefix then
|
||||
local after_colon = arg_lead:sub(#prefix + 1)
|
||||
local dates = edit_date_values()
|
||||
local result = {}
|
||||
for _, d in ipairs(dates) do
|
||||
if d:find(after_colon, 1, true) == 1 then
|
||||
table.insert(result, prefix .. d)
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
local rec_prefix = arg_lead:match('^(' .. vim.pesc(rk) .. ':)(.*)$')
|
||||
if rec_prefix then
|
||||
local after_colon = arg_lead:sub(#rec_prefix + 1)
|
||||
local pats = edit_recur_values()
|
||||
local result = {}
|
||||
for _, p in ipairs(pats) do
|
||||
if p:find(after_colon, 1, true) == 1 then
|
||||
table.insert(result, rec_prefix .. p)
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
local cat_prefix = arg_lead:match('^(cat:)(.*)$')
|
||||
if cat_prefix then
|
||||
local after_colon = arg_lead:sub(#cat_prefix + 1)
|
||||
local store = require('pending.store')
|
||||
store.load()
|
||||
local seen = {}
|
||||
local cats = {}
|
||||
for _, task in ipairs(store.active_tasks()) do
|
||||
if task.category and not seen[task.category] then
|
||||
seen[task.category] = true
|
||||
table.insert(cats, task.category)
|
||||
end
|
||||
end
|
||||
table.sort(cats)
|
||||
local result = {}
|
||||
for _, c in ipairs(cats) do
|
||||
if c:find(after_colon, 1, true) == 1 then
|
||||
table.insert(result, cat_prefix .. c)
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
return filter_candidates(arg_lead, edit_field_candidates())
|
||||
end
|
||||
|
||||
vim.api.nvim_create_user_command('Pending', function(opts)
|
||||
require('pending').command(opts.args)
|
||||
end, {
|
||||
bar = true,
|
||||
nargs = '*',
|
||||
complete = function(arg_lead, cmd_line)
|
||||
local subcmds = { 'add', 'archive', 'due', 'edit', 'sync', 'undo' }
|
||||
local subcmds = { 'add', 'sync', 'archive', 'due', 'undo' }
|
||||
if not cmd_line:match('^Pending%s+%S') then
|
||||
return filter_candidates(arg_lead, subcmds)
|
||||
end
|
||||
if cmd_line:match('^Pending%s+edit') then
|
||||
return complete_edit(arg_lead, cmd_line)
|
||||
return vim.tbl_filter(function(s)
|
||||
return s:find(arg_lead, 1, true) == 1
|
||||
end, subcmds)
|
||||
end
|
||||
return {}
|
||||
end,
|
||||
|
|
|
|||
|
|
@ -1,304 +0,0 @@
|
|||
require('spec.helpers')
|
||||
|
||||
local config = require('pending.config')
|
||||
local store = require('pending.store')
|
||||
|
||||
describe('edit', function()
|
||||
local tmpdir
|
||||
local pending = require('pending')
|
||||
|
||||
before_each(function()
|
||||
tmpdir = vim.fn.tempname()
|
||||
vim.fn.mkdir(tmpdir, 'p')
|
||||
vim.g.pending = { data_path = tmpdir .. '/tasks.json' }
|
||||
config.reset()
|
||||
store.unload()
|
||||
store.load()
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
vim.fn.delete(tmpdir, 'rf')
|
||||
vim.g.pending = nil
|
||||
config.reset()
|
||||
end)
|
||||
|
||||
it('sets due date with resolve_date vocabulary', function()
|
||||
local t = store.add({ description = 'Task one' })
|
||||
store.save()
|
||||
pending.edit(tostring(t.id), 'due:tomorrow')
|
||||
local updated = store.get(t.id)
|
||||
local today = os.date('*t') --[[@as osdate]]
|
||||
local expected =
|
||||
os.date('%Y-%m-%d', os.time({ year = today.year, month = today.month, day = today.day + 1 }))
|
||||
assert.are.equal(expected, updated.due)
|
||||
end)
|
||||
|
||||
it('sets due date with literal YYYY-MM-DD', function()
|
||||
local t = store.add({ description = 'Task one' })
|
||||
store.save()
|
||||
pending.edit(tostring(t.id), 'due:2026-06-15')
|
||||
local updated = store.get(t.id)
|
||||
assert.are.equal('2026-06-15', updated.due)
|
||||
end)
|
||||
|
||||
it('sets category', function()
|
||||
local t = store.add({ description = 'Task one' })
|
||||
store.save()
|
||||
pending.edit(tostring(t.id), 'cat:Work')
|
||||
local updated = store.get(t.id)
|
||||
assert.are.equal('Work', updated.category)
|
||||
end)
|
||||
|
||||
it('adds priority', function()
|
||||
local t = store.add({ description = 'Task one' })
|
||||
store.save()
|
||||
pending.edit(tostring(t.id), '+!')
|
||||
local updated = store.get(t.id)
|
||||
assert.are.equal(1, updated.priority)
|
||||
end)
|
||||
|
||||
it('removes priority', function()
|
||||
local t = store.add({ description = 'Task one', priority = 1 })
|
||||
store.save()
|
||||
pending.edit(tostring(t.id), '-!')
|
||||
local updated = store.get(t.id)
|
||||
assert.are.equal(0, updated.priority)
|
||||
end)
|
||||
|
||||
it('removes due date', function()
|
||||
local t = store.add({ description = 'Task one', due = '2026-06-15' })
|
||||
store.save()
|
||||
pending.edit(tostring(t.id), '-due')
|
||||
local updated = store.get(t.id)
|
||||
assert.is_nil(updated.due)
|
||||
end)
|
||||
|
||||
it('removes category', function()
|
||||
local t = store.add({ description = 'Task one', category = 'Work' })
|
||||
store.save()
|
||||
pending.edit(tostring(t.id), '-cat')
|
||||
local updated = store.get(t.id)
|
||||
assert.is_nil(updated.category)
|
||||
end)
|
||||
|
||||
it('sets recurrence', function()
|
||||
local t = store.add({ description = 'Task one' })
|
||||
store.save()
|
||||
pending.edit(tostring(t.id), 'rec:weekly')
|
||||
local updated = store.get(t.id)
|
||||
assert.are.equal('weekly', updated.recur)
|
||||
assert.is_nil(updated.recur_mode)
|
||||
end)
|
||||
|
||||
it('sets completion-based recurrence', function()
|
||||
local t = store.add({ description = 'Task one' })
|
||||
store.save()
|
||||
pending.edit(tostring(t.id), 'rec:!daily')
|
||||
local updated = store.get(t.id)
|
||||
assert.are.equal('daily', updated.recur)
|
||||
assert.are.equal('completion', updated.recur_mode)
|
||||
end)
|
||||
|
||||
it('removes recurrence', function()
|
||||
local t = store.add({ description = 'Task one', recur = 'weekly', recur_mode = 'scheduled' })
|
||||
store.save()
|
||||
pending.edit(tostring(t.id), '-rec')
|
||||
local updated = store.get(t.id)
|
||||
assert.is_nil(updated.recur)
|
||||
assert.is_nil(updated.recur_mode)
|
||||
end)
|
||||
|
||||
it('applies multiple operations at once', function()
|
||||
local t = store.add({ description = 'Task one' })
|
||||
store.save()
|
||||
pending.edit(tostring(t.id), 'due:today cat:Errands +!')
|
||||
local updated = store.get(t.id)
|
||||
assert.are.equal(os.date('%Y-%m-%d'), updated.due)
|
||||
assert.are.equal('Errands', updated.category)
|
||||
assert.are.equal(1, updated.priority)
|
||||
end)
|
||||
|
||||
it('pushes to undo stack', function()
|
||||
local t = store.add({ description = 'Task one' })
|
||||
store.save()
|
||||
local stack_before = #store.undo_stack()
|
||||
pending.edit(tostring(t.id), 'cat:Work')
|
||||
assert.are.equal(stack_before + 1, #store.undo_stack())
|
||||
end)
|
||||
|
||||
it('persists changes to disk', function()
|
||||
local t = store.add({ description = 'Task one' })
|
||||
store.save()
|
||||
pending.edit(tostring(t.id), 'cat:Work')
|
||||
store.unload()
|
||||
store.load()
|
||||
local updated = store.get(t.id)
|
||||
assert.are.equal('Work', updated.category)
|
||||
end)
|
||||
|
||||
it('errors on unknown task ID', function()
|
||||
store.add({ description = 'Task one' })
|
||||
store.save()
|
||||
local messages = {}
|
||||
local orig_notify = vim.notify
|
||||
vim.notify = function(msg, level)
|
||||
table.insert(messages, { msg = msg, level = level })
|
||||
end
|
||||
pending.edit('999', 'cat:Work')
|
||||
vim.notify = orig_notify
|
||||
assert.are.equal(1, #messages)
|
||||
assert.truthy(messages[1].msg:find('No task with ID 999'))
|
||||
assert.are.equal(vim.log.levels.ERROR, messages[1].level)
|
||||
end)
|
||||
|
||||
it('errors on invalid date', function()
|
||||
local t = store.add({ description = 'Task one' })
|
||||
store.save()
|
||||
local messages = {}
|
||||
local orig_notify = vim.notify
|
||||
vim.notify = function(msg, level)
|
||||
table.insert(messages, { msg = msg, level = level })
|
||||
end
|
||||
pending.edit(tostring(t.id), 'due:notadate')
|
||||
vim.notify = orig_notify
|
||||
assert.are.equal(1, #messages)
|
||||
assert.truthy(messages[1].msg:find('Invalid date'))
|
||||
assert.are.equal(vim.log.levels.ERROR, messages[1].level)
|
||||
end)
|
||||
|
||||
it('errors on unknown operation token', function()
|
||||
local t = store.add({ description = 'Task one' })
|
||||
store.save()
|
||||
local messages = {}
|
||||
local orig_notify = vim.notify
|
||||
vim.notify = function(msg, level)
|
||||
table.insert(messages, { msg = msg, level = level })
|
||||
end
|
||||
pending.edit(tostring(t.id), 'bogus')
|
||||
vim.notify = orig_notify
|
||||
assert.are.equal(1, #messages)
|
||||
assert.truthy(messages[1].msg:find('Unknown operation'))
|
||||
assert.are.equal(vim.log.levels.ERROR, messages[1].level)
|
||||
end)
|
||||
|
||||
it('errors on invalid recurrence pattern', function()
|
||||
local t = store.add({ description = 'Task one' })
|
||||
store.save()
|
||||
local messages = {}
|
||||
local orig_notify = vim.notify
|
||||
vim.notify = function(msg, level)
|
||||
table.insert(messages, { msg = msg, level = level })
|
||||
end
|
||||
pending.edit(tostring(t.id), 'rec:nope')
|
||||
vim.notify = orig_notify
|
||||
assert.are.equal(1, #messages)
|
||||
assert.truthy(messages[1].msg:find('Invalid recurrence'))
|
||||
assert.are.equal(vim.log.levels.ERROR, messages[1].level)
|
||||
end)
|
||||
|
||||
it('errors when no operations given', function()
|
||||
local t = store.add({ description = 'Task one' })
|
||||
store.save()
|
||||
local messages = {}
|
||||
local orig_notify = vim.notify
|
||||
vim.notify = function(msg, level)
|
||||
table.insert(messages, { msg = msg, level = level })
|
||||
end
|
||||
pending.edit(tostring(t.id), '')
|
||||
vim.notify = orig_notify
|
||||
assert.are.equal(1, #messages)
|
||||
assert.truthy(messages[1].msg:find('Usage'))
|
||||
assert.are.equal(vim.log.levels.ERROR, messages[1].level)
|
||||
end)
|
||||
|
||||
it('errors when no id given', function()
|
||||
local messages = {}
|
||||
local orig_notify = vim.notify
|
||||
vim.notify = function(msg, level)
|
||||
table.insert(messages, { msg = msg, level = level })
|
||||
end
|
||||
pending.edit('', '')
|
||||
vim.notify = orig_notify
|
||||
assert.are.equal(1, #messages)
|
||||
assert.truthy(messages[1].msg:find('Usage'))
|
||||
assert.are.equal(vim.log.levels.ERROR, messages[1].level)
|
||||
end)
|
||||
|
||||
it('errors on non-numeric id', function()
|
||||
local messages = {}
|
||||
local orig_notify = vim.notify
|
||||
vim.notify = function(msg, level)
|
||||
table.insert(messages, { msg = msg, level = level })
|
||||
end
|
||||
pending.edit('abc', 'cat:Work')
|
||||
vim.notify = orig_notify
|
||||
assert.are.equal(1, #messages)
|
||||
assert.truthy(messages[1].msg:find('Invalid task ID'))
|
||||
assert.are.equal(vim.log.levels.ERROR, messages[1].level)
|
||||
end)
|
||||
|
||||
it('shows feedback message on success', function()
|
||||
local t = store.add({ description = 'Task one' })
|
||||
store.save()
|
||||
local messages = {}
|
||||
local orig_notify = vim.notify
|
||||
vim.notify = function(msg, level)
|
||||
table.insert(messages, { msg = msg, level = level })
|
||||
end
|
||||
pending.edit(tostring(t.id), 'cat:Work')
|
||||
vim.notify = orig_notify
|
||||
assert.are.equal(1, #messages)
|
||||
assert.truthy(messages[1].msg:find('Task #' .. t.id .. ' updated'))
|
||||
assert.truthy(messages[1].msg:find('category set to Work'))
|
||||
end)
|
||||
|
||||
it('respects custom date_syntax', function()
|
||||
vim.g.pending = { data_path = tmpdir .. '/tasks.json', date_syntax = 'by' }
|
||||
config.reset()
|
||||
store.unload()
|
||||
store.load()
|
||||
local t = store.add({ description = 'Task one' })
|
||||
store.save()
|
||||
pending.edit(tostring(t.id), 'by:tomorrow')
|
||||
local updated = store.get(t.id)
|
||||
local today = os.date('*t') --[[@as osdate]]
|
||||
local expected =
|
||||
os.date('%Y-%m-%d', os.time({ year = today.year, month = today.month, day = today.day + 1 }))
|
||||
assert.are.equal(expected, updated.due)
|
||||
end)
|
||||
|
||||
it('respects custom recur_syntax', function()
|
||||
vim.g.pending = { data_path = tmpdir .. '/tasks.json', recur_syntax = 'repeat' }
|
||||
config.reset()
|
||||
store.unload()
|
||||
store.load()
|
||||
local t = store.add({ description = 'Task one' })
|
||||
store.save()
|
||||
pending.edit(tostring(t.id), 'repeat:weekly')
|
||||
local updated = store.get(t.id)
|
||||
assert.are.equal('weekly', updated.recur)
|
||||
end)
|
||||
|
||||
it('does not modify store on error', function()
|
||||
local t = store.add({ description = 'Task one', category = 'Original' })
|
||||
store.save()
|
||||
local orig_notify = vim.notify
|
||||
vim.notify = function() end
|
||||
pending.edit(tostring(t.id), 'due:notadate')
|
||||
vim.notify = orig_notify
|
||||
local updated = store.get(t.id)
|
||||
assert.are.equal('Original', updated.category)
|
||||
assert.is_nil(updated.due)
|
||||
end)
|
||||
|
||||
it('sets due date with datetime format', function()
|
||||
local t = store.add({ description = 'Task one' })
|
||||
store.save()
|
||||
pending.edit(tostring(t.id), 'due:tomorrow@14:00')
|
||||
local updated = store.get(t.id)
|
||||
local today = os.date('*t') --[[@as osdate]]
|
||||
local expected =
|
||||
os.date('%Y-%m-%d', os.time({ year = today.year, month = today.month, day = today.day + 1 }))
|
||||
assert.are.equal(expected .. 'T14:00', updated.due)
|
||||
end)
|
||||
end)
|
||||
Loading…
Add table
Add a link
Reference in a new issue