fix(init): preserve cursor column and position in mutation functions

Problem: `toggle_complete()`, `toggle_priority()`, `adjust_priority()`,
`toggle_status()`, and `move_task()` captured only the row from
`nvim_win_get_cursor` and restored the cursor to column 0 after
re-render. Additionally, `toggle_complete()` followed the toggled task
to its new sorted position at the bottom of the category, which is
disorienting when working through a list of tasks.

Solution: Capture both row and column from the cursor, and restore the
column in all five functions. For `toggle_complete()`, instead of
chasing the task ID after render, clamp the cursor to the original row
(or total lines if shorter) and advance to the nearest task line,
similar to the `]t` motion in `textobj.lua`.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Barrett Ruth 2026-03-12 20:08:07 -04:00
parent 077e4121b4
commit fe6d7964d4

View file

@ -524,7 +524,8 @@ function M.toggle_complete()
if not require_saved() then
return
end
local row = vim.api.nvim_win_get_cursor(0)[1]
local cursor = vim.api.nvim_win_get_cursor(0)
local row, col = cursor[1], cursor[2]
local meta = buffer.meta()
if not meta[row] or meta[row].type ~= 'task' then
return
@ -558,11 +559,25 @@ function M.toggle_complete()
end
_save_and_notify()
buffer.render(bufnr)
for lnum, m in ipairs(buffer.meta()) do
if m.id == id then
vim.api.nvim_win_set_cursor(0, { lnum, 0 })
break
local new_meta = buffer.meta()
local total = #new_meta
local target = math.min(row, total)
if new_meta[target] and new_meta[target].type == 'task' then
vim.api.nvim_win_set_cursor(0, { target, col })
else
for r = target, total do
if new_meta[r] and new_meta[r].type == 'task' then
vim.api.nvim_win_set_cursor(0, { r, col })
return
end
end
for r = target, 1, -1 do
if new_meta[r] and new_meta[r].type == 'task' then
vim.api.nvim_win_set_cursor(0, { r, col })
return
end
end
vim.api.nvim_win_set_cursor(0, { target, col })
end
end
@ -634,7 +649,8 @@ function M.toggle_priority()
if not require_saved() then
return
end
local row = vim.api.nvim_win_get_cursor(0)[1]
local cursor = vim.api.nvim_win_get_cursor(0)
local row, col = cursor[1], cursor[2]
local meta = buffer.meta()
if not meta[row] or meta[row].type ~= 'task' then
return
@ -655,7 +671,7 @@ function M.toggle_priority()
buffer.render(bufnr)
for lnum, m in ipairs(buffer.meta()) do
if m.id == id then
vim.api.nvim_win_set_cursor(0, { lnum, 0 })
vim.api.nvim_win_set_cursor(0, { lnum, col })
break
end
end
@ -671,7 +687,8 @@ local function adjust_priority(delta)
if not require_saved() then
return
end
local row = vim.api.nvim_win_get_cursor(0)[1]
local cursor = vim.api.nvim_win_get_cursor(0)
local row, col = cursor[1], cursor[2]
local meta = buffer.meta()
if not meta[row] or meta[row].type ~= 'task' then
return
@ -695,7 +712,7 @@ local function adjust_priority(delta)
buffer.render(bufnr)
for lnum, m in ipairs(buffer.meta()) do
if m.id == id then
vim.api.nvim_win_set_cursor(0, { lnum, 0 })
vim.api.nvim_win_set_cursor(0, { lnum, col })
break
end
end
@ -762,7 +779,8 @@ function M.toggle_status(target_status)
if not require_saved() then
return
end
local row = vim.api.nvim_win_get_cursor(0)[1]
local cursor = vim.api.nvim_win_get_cursor(0)
local row, col = cursor[1], cursor[2]
local meta = buffer.meta()
if not meta[row] or meta[row].type ~= 'task' then
return
@ -785,7 +803,7 @@ function M.toggle_status(target_status)
buffer.render(bufnr)
for lnum, m in ipairs(buffer.meta()) do
if m.id == id then
vim.api.nvim_win_set_cursor(0, { lnum, 0 })
vim.api.nvim_win_set_cursor(0, { lnum, col })
break
end
end
@ -801,7 +819,8 @@ function M.move_task(direction)
if not require_saved() then
return
end
local row = vim.api.nvim_win_get_cursor(0)[1]
local cursor = vim.api.nvim_win_get_cursor(0)
local row, col = cursor[1], cursor[2]
local meta = buffer.meta()
if not meta[row] or meta[row].type ~= 'task' then
return
@ -876,7 +895,7 @@ function M.move_task(direction)
for lnum, m in ipairs(buffer.meta()) do
if m.id == id then
vim.api.nvim_win_set_cursor(0, { lnum, 0 })
vim.api.nvim_win_set_cursor(0, { lnum, col })
break
end
end