Conversation
Agenda redo saved and restored the view of whatever window was current. Redo runs while orgmode's hidden edit window is current (remote edits) or an org buffer is (BufWritePost hooks that refresh the agenda), so the org file's cursor line was applied to the agenda and clamped to its last line. Users lost their position on every remote todo change. Redo now saves and restores the view of the agenda window itself and remembers the headline under the cursor. After the rebuild the cursor follows that headline (by :ID:, or by title when it has none), moving the window only when the headline left the visible range. If the headline is gone from the agenda, the cursor stays on the same line. Refs: nvim-orgmode#656, nvim-orgmode#868
The guard that skips the automatic resize after a manual resize only compared the window's screen position. A horizontal agenda split opens above the current window, so its position never changes when the user makes it taller, and every redo shrank it back to the default height. Remember the height alongside the position and skip the resize when either differs. Refs: nvim-orgmode#219
The cursor relocation after redo read :ID: and title from the headline object of the old agenda line. That object still points at tree-sitter nodes of the previous parse, so once the file was edited above the item (a write with a refresh hook, a refile or capture into the same file) it described a different headline and the cursor jumped to it. Each agenda line now records filename, :ID: and title when it is built, while the headline is fresh. ID lookup no longer follows property inheritance, and when a headline occupies several lines (scheduled and deadline on one day) the line nearest the previous cursor wins.
A todo state change from the agenda updates the line in place. Users who refresh the agenda on save, as suggested in nvim-orgmode#656 and nvim-orgmode#868, run a redo from BufWritePost during that same edit. The redo finishes first and the in-place update then targets a line from the previous render. It was matched by line number, so it overwrote whatever the fresh view had there and the item showed up in both its old and its new block. Match the line object instead. A line from an earlier render is not in the current view, so the in-place update does nothing and the redo stands. Refs: nvim-orgmode#656, nvim-orgmode#868
seflue
force-pushed
the
fix/agenda-redo-cursor
branch
from
September 19, 2026 09:25
19f17be to
51a667b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ref #656, #868
Refreshing the agenda on save, as suggested there, calls
agenda:redo('remote_edit', true)from aBufWritePostautocmd. After the refresh the cursor is positioned on the last line of the agenda window and the scroll position is gone. A todo state change from the agenda does the same whenever the edit adds lines to the file, for example the CLOSED timestamp on DONE. That is annoying: on a long agenda every state change loses the context around the item.The cause:
redosaved and restored the view of whatever window was current. The callers inside the agenda (filter, clock report) run with the agenda window current, and there it worked. From the write hook the current window is the org buffer, from a remote edit it is the hidden edit window. The restore then jumped to a line number in the agenda that was in fact the cursor line of the org file. When that number was larger than the agenda's line count, the cursor landed on the last agenda line.With this patch, redo takes the view from the agenda window and remembers the headline under the cursor (filename plus
:ID:, or the title when there is none). After the rebuild the cursor follows that headline, and the window scrolls only when the headline left the visible range. When the headline is gone from the agenda, the cursor stays on its line.Two more things the write hook setup turned up:
OrgHeadlineon the line points at tree-sitter nodes of the old parse; once lines were inserted above the item (a capture or refile into the same file), it describes a different headline.replace_linenow matches the line object; a line from an earlier render is not in the view and the update does nothing.The last commit is separate: the guard that skips the automatic resize after a manual resize compared only the window's screen position (#219). A horizontal split opens above the current window, so making it taller changes nothing there, and every redo shrank it back. The guard now also compares the height.