From fe6d7964d4e26e8a191a78d71dedfa9770764e69 Mon Sep 17 00:00:00 2001 From: Barrett Ruth Date: Thu, 12 Mar 2026 20:08:07 -0400 Subject: [PATCH] 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 --- lua/pending/init.lua | 45 +++++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/lua/pending/init.lua b/lua/pending/init.lua index aeba431..7a661e8 100644 --- a/lua/pending/init.lua +++ b/lua/pending/init.lua @@ -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