fix(parse): skip forge refs in right-to-left metadata scan (#142)
Problem: `parse.body()` scans tokens right-to-left and breaks on the first non-metadata token. Forge refs like `gl:a/b#12` halted the scan, preventing metadata tokens to their left (e.g. `due:tomorrow`) from being parsed. Additionally, `diff.parse_buffer()` ignored `metadata.priority` from `+!!` tokens and only used checkbox-derived priority, and priority updates between two non-zero values were silently skipped. Solution: Recognize forge ref tokens via `forge.parse_ref()` during the right-to-left scan and skip past them, re-appending them to the description so `forge.find_refs()` still works. Prefer `metadata.priority` over checkbox priority in `parse_buffer()`, and simplify the priority update condition to catch all value changes.
This commit is contained in:
parent
d26bdcb3a8
commit
79343cac2e
4 changed files with 74 additions and 5 deletions
|
|
@ -63,7 +63,7 @@ function M.parse_buffer(lines)
|
|||
type = 'task',
|
||||
id = id and tonumber(id) or nil,
|
||||
description = description,
|
||||
priority = priority,
|
||||
priority = metadata.priority or priority,
|
||||
status = status,
|
||||
category = metadata.category or current_category or config.get().default_category,
|
||||
due = metadata.due,
|
||||
|
|
@ -146,10 +146,7 @@ function M.apply(lines, s, hidden_ids)
|
|||
task.category = entry.category
|
||||
changed = true
|
||||
end
|
||||
if entry.priority == 0 and task.priority > 0 then
|
||||
task.priority = 0
|
||||
changed = true
|
||||
elseif entry.priority > 0 and task.priority == 0 then
|
||||
if entry.priority ~= task.priority then
|
||||
task.priority = entry.priority
|
||||
changed = true
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
local config = require('pending.config')
|
||||
local forge = require('pending.forge')
|
||||
|
||||
---@class pending.Metadata
|
||||
---@field due? string
|
||||
|
|
@ -543,6 +544,7 @@ function M.body(text)
|
|||
local date_pattern_strict = '^' .. vim.pesc(dk) .. ':(%d%d%d%d%-%d%d%-%d%d[T%d:]*)$'
|
||||
local date_pattern_any = '^' .. vim.pesc(dk) .. ':(.+)$'
|
||||
local rec_pattern = '^' .. vim.pesc(rk) .. ':(%S+)$'
|
||||
local forge_indices = {}
|
||||
|
||||
while i >= 1 do
|
||||
local token = tokens[i]
|
||||
|
|
@ -602,6 +604,9 @@ function M.body(text)
|
|||
end
|
||||
metadata.recur = raw_spec
|
||||
i = i - 1
|
||||
elseif forge.parse_ref(token) then
|
||||
table.insert(forge_indices, i)
|
||||
i = i - 1
|
||||
else
|
||||
break
|
||||
end
|
||||
|
|
@ -615,6 +620,9 @@ function M.body(text)
|
|||
for j = 1, i do
|
||||
table.insert(desc_tokens, tokens[j])
|
||||
end
|
||||
for fi = #forge_indices, 1, -1 do
|
||||
table.insert(desc_tokens, tokens[forge_indices[fi]])
|
||||
end
|
||||
local description = table.concat(desc_tokens, ' ')
|
||||
|
||||
return description, metadata
|
||||
|
|
|
|||
|
|
@ -379,5 +379,41 @@ describe('diff', function()
|
|||
local task = s:get(1)
|
||||
assert.are.equal(0, task.priority)
|
||||
end)
|
||||
|
||||
it('sets priority from +!! token', function()
|
||||
local lines = {
|
||||
'# Inbox',
|
||||
'- [ ] Pay bills +!!',
|
||||
}
|
||||
diff.apply(lines, s)
|
||||
s:load()
|
||||
local task = s:get(1)
|
||||
assert.are.equal(2, task.priority)
|
||||
end)
|
||||
|
||||
it('updates priority between non-zero values', function()
|
||||
s:add({ description = 'Task name', priority = 2 })
|
||||
s:save()
|
||||
local lines = {
|
||||
'# Inbox',
|
||||
'/1/- [!] Task name',
|
||||
}
|
||||
diff.apply(lines, s)
|
||||
s:load()
|
||||
local task = s:get(1)
|
||||
assert.are.equal(1, task.priority)
|
||||
end)
|
||||
|
||||
it('parses metadata with forge ref on same line', function()
|
||||
local lines = {
|
||||
'# Inbox',
|
||||
'- [ ] Fix bug due:2026-03-15 gh:user/repo#42',
|
||||
}
|
||||
diff.apply(lines, s)
|
||||
s:load()
|
||||
local task = s:get(1)
|
||||
assert.are.equal('2026-03-15', task.due)
|
||||
assert.is_not_nil(task._extra._forge_ref)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
|
|
|||
|
|
@ -110,6 +110,34 @@ describe('parse', function()
|
|||
assert.is_nil(meta.due)
|
||||
assert.truthy(desc:find('due:garbage', 1, true))
|
||||
end)
|
||||
|
||||
it('parses metadata before a forge ref', function()
|
||||
local desc, meta = parse.body('Fix bug due:2026-03-15 gh:user/repo#42')
|
||||
assert.are.equal('2026-03-15', meta.due)
|
||||
assert.truthy(desc:find('gh:user/repo#42', 1, true))
|
||||
assert.truthy(desc:find('Fix bug', 1, true))
|
||||
end)
|
||||
|
||||
it('parses metadata after a forge ref', function()
|
||||
local desc, meta = parse.body('Fix bug gh:user/repo#42 due:2026-03-15')
|
||||
assert.are.equal('2026-03-15', meta.due)
|
||||
assert.truthy(desc:find('gh:user/repo#42', 1, true))
|
||||
assert.truthy(desc:find('Fix bug', 1, true))
|
||||
end)
|
||||
|
||||
it('parses all metadata around forge ref', function()
|
||||
local desc, meta = parse.body('Fix bug due:tomorrow gh:user/repo#42 cat:Work')
|
||||
assert.are.equal(os.date('%Y-%m-%d', os.time() + 86400), meta.due)
|
||||
assert.are.equal('Work', meta.category)
|
||||
assert.truthy(desc:find('gh:user/repo#42', 1, true))
|
||||
end)
|
||||
|
||||
it('parses forge ref between metadata tokens', function()
|
||||
local desc, meta = parse.body('Fix bug cat:Work gl:a/b#12 due:2026-03-15')
|
||||
assert.are.equal('2026-03-15', meta.due)
|
||||
assert.are.equal('Work', meta.category)
|
||||
assert.truthy(desc:find('gl:a/b#12', 1, true))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('parse.resolve_date', function()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue