feat(buffer): render forge links as inline conceal overlays
Problem: forge tokens were stripped from the buffer and shown as EOL virtual text via `%l`. The token disappeared from the editable line, and multi-ref tasks broke. Solution: compute `forge_spans` in `views.lua` with byte offsets for each forge token in the rendered line. In `apply_inline_row()`, place extmarks with `conceal=''` and `virt_text_pos='inline'` to visually replace each raw token with its formatted label. Clear stale `forge_spans` on dirty rows to prevent `end_col` out-of-range errors after edits like `dd`.
This commit is contained in:
parent
0a64691edd
commit
819d27d751
2 changed files with 47 additions and 4 deletions
|
|
@ -1,6 +1,13 @@
|
|||
local config = require('pending.config')
|
||||
local forge = require('pending.forge')
|
||||
local parse = require('pending.parse')
|
||||
|
||||
---@class pending.ForgeLineMeta
|
||||
---@field ref pending.ForgeRef
|
||||
---@field cache? pending.ForgeCache
|
||||
---@field col_start integer
|
||||
---@field col_end integer
|
||||
|
||||
---@class pending.LineMeta
|
||||
---@field type 'task'|'header'|'blank'|'filter'
|
||||
---@field id? integer
|
||||
|
|
@ -14,6 +21,7 @@ local parse = require('pending.parse')
|
|||
---@field recur? string
|
||||
---@field forge_ref? pending.ForgeRef
|
||||
---@field forge_cache? pending.ForgeCache
|
||||
---@field forge_spans? pending.ForgeLineMeta[]
|
||||
|
||||
---@class pending.views
|
||||
local M = {}
|
||||
|
|
@ -43,6 +51,27 @@ local function format_due(due)
|
|||
return formatted
|
||||
end
|
||||
|
||||
---@param task pending.Task
|
||||
---@param prefix_len integer
|
||||
---@return pending.ForgeLineMeta[]?
|
||||
local function compute_forge_spans(task, prefix_len)
|
||||
local refs = forge.find_refs(task.description)
|
||||
if #refs == 0 then
|
||||
return nil
|
||||
end
|
||||
local cache = task._extra and task._extra._forge_cache or nil
|
||||
local spans = {}
|
||||
for _, r in ipairs(refs) do
|
||||
table.insert(spans, {
|
||||
ref = r.ref,
|
||||
cache = cache,
|
||||
col_start = prefix_len + r.start_byte,
|
||||
col_end = prefix_len + r.end_byte,
|
||||
})
|
||||
end
|
||||
return spans
|
||||
end
|
||||
|
||||
---@type table<string, integer>
|
||||
local status_rank = { wip = 0, pending = 1, blocked = 2, done = 3 }
|
||||
|
||||
|
|
@ -178,6 +207,7 @@ function M.category_view(tasks)
|
|||
local prefix = '/' .. task.id .. '/'
|
||||
local state = state_char(task)
|
||||
local line = prefix .. '- [' .. state .. '] ' .. task.description
|
||||
local prefix_len = #prefix + #('- [' .. state .. '] ')
|
||||
table.insert(lines, line)
|
||||
table.insert(meta, {
|
||||
type = 'task',
|
||||
|
|
@ -191,6 +221,7 @@ function M.category_view(tasks)
|
|||
recur = task.recur,
|
||||
forge_ref = task._extra and task._extra._forge_ref or nil,
|
||||
forge_cache = task._extra and task._extra._forge_cache or nil,
|
||||
forge_spans = compute_forge_spans(task, prefix_len),
|
||||
})
|
||||
end
|
||||
end
|
||||
|
|
@ -231,6 +262,7 @@ function M.priority_view(tasks)
|
|||
local prefix = '/' .. task.id .. '/'
|
||||
local state = task.status == 'done' and 'x' or (task.priority > 0 and '!' or ' ')
|
||||
local line = prefix .. '- [' .. state .. '] ' .. task.description
|
||||
local prefix_len = #prefix + #('- [' .. state .. '] ')
|
||||
table.insert(lines, line)
|
||||
table.insert(meta, {
|
||||
type = 'task',
|
||||
|
|
@ -245,6 +277,7 @@ function M.priority_view(tasks)
|
|||
recur = task.recur,
|
||||
forge_ref = task._extra and task._extra._forge_ref or nil,
|
||||
forge_cache = task._extra and task._extra._forge_cache or nil,
|
||||
forge_spans = compute_forge_spans(task, prefix_len),
|
||||
})
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue