heph.nvim: make the view key-hint actually visible (header line, not virt-line)
Some checks failed
Build / validate (pull_request) Failing after 6m25s

virt_lines_above on the first line renders above the top screen row, which can't
be scrolled into view — so the hint was invisible. Use a real header line at the
top of next/list (dimmed via an extmark highlight); task rows start at line 2,
and the cursor lands on the first task. Specs updated for the +1 offset.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erich Blume 2026-06-02 12:01:36 -07:00
commit 95948d5563
3 changed files with 16 additions and 11 deletions

View file

@ -27,7 +27,8 @@ local function task_on_line(buf)
if not view then
return nil
end
return view.tasks[vim.api.nvim_win_get_cursor(0)[1]]
-- line 1 is the key-hint header; task rows start at line 2.
return view.tasks[vim.api.nvim_win_get_cursor(0)[1] - 1]
end
-- Find or create the named scratch buffer, fill it, and (re)bind its keymaps.
@ -48,23 +49,23 @@ local function render(name, tasks, refresh)
vim.bo[buf].bufhidden = "hide"
vim.bo[buf].swapfile = false
local lines = {}
-- Line 1 is a dimmed key hint; task rows follow.
local lines = { HINT }
for _, t in ipairs(tasks) do
lines[#lines + 1] = row(t)
end
if #lines == 0 then
lines = { "(nothing here — press 'a' to add a task)" }
if #tasks == 0 then
lines[#lines + 1] = "(nothing here — press 'a' to add a task)"
end
vim.bo[buf].modifiable = true
vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines)
vim.bo[buf].modifiable = false
-- A dimmed key hint above the first row — a virtual line, so it isn't a task
-- row (cursor lines still map 1:1 to tasks).
vim.api.nvim_buf_clear_namespace(buf, hint_ns, 0, -1)
vim.api.nvim_buf_set_extmark(buf, hint_ns, 0, 0, {
virt_lines_above = true,
virt_lines = { { { HINT, "Comment" } } },
end_row = 0,
end_col = #HINT,
hl_group = "Comment",
})
M._views[buf] = { tasks = tasks, refresh = refresh }
@ -84,6 +85,9 @@ local function render(name, tasks, refresh)
M.refresh(buf)
end, "heph: refresh")
vim.api.nvim_set_current_buf(buf)
if #tasks > 0 then
pcall(vim.api.nvim_win_set_cursor, 0, { 2, 0 }) -- land on the first task row
end
return buf
end

View file

@ -29,8 +29,9 @@ describe("task capture to done", function()
assert.are.equal(task.node_id, ranked[1].node_id)
assert.is_truthy(ranked[1].canonical_context_id)
-- Jump to its canonical context from the view (the one-keystroke jump).
vim.api.nvim_win_set_cursor(0, { 1, 0 })
-- Jump to its canonical context from the view (line 1 is the hint header,
-- task rows start at line 2).
vim.api.nvim_win_set_cursor(0, { 2, 0 })
require("heph.view").open_under_cursor()
local ctxbuf = vim.api.nvim_get_current_buf()
assert.are.equal(

View file

@ -50,7 +50,7 @@ describe("task list actions", function()
local t = ctx.q:call("task.create", { title = "Ship it", attention = "red" })
require("heph.view").list()
local buf = vim.api.nvim_get_current_buf()
vim.api.nvim_win_set_cursor(0, { 1, 0 })
vim.api.nvim_win_set_cursor(0, { 2, 0 }) -- line 1 is the hint header
require("heph.view").done_under_cursor(buf)