Skip to content

Commit 7d3b020

Browse files
authored
fix(renderer): clean out edge cases of cursor.position.restore (#1355)
1 parent db178f4 commit 7d3b020

File tree

3 files changed

+28
-53
lines changed

3 files changed

+28
-53
lines changed

Diff for: lua/neo-tree/sources/filesystem/init.lua

+1-7
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ local follow_internal = function(callback, force_show, async)
8585
end
8686
end
8787

88-
state.position.is.restorable = false -- we will handle setting cursor position here
8988
fs_scan.get_items(state, nil, path_to_reveal, function()
9089
show_only_explicitly_opened()
9190
renderer.focus_node(state, path_to_reveal, true)
@@ -129,12 +128,7 @@ M._navigate_internal = function(state, path, path_to_reveal, callback, async)
129128

130129
if path_to_reveal then
131130
renderer.position.set(state, path_to_reveal)
132-
log.debug(
133-
"navigate_internal: in path_to_reveal, state.position is ",
134-
state.position.node_id,
135-
", restorable = ",
136-
state.position.is.restorable
137-
)
131+
log.debug("navigate_internal: in path_to_reveal, state.position=", state.position.node_id)
138132
fs_scan.get_items(state, nil, path_to_reveal, callback)
139133
else
140134
local is_current = state.current_position == "current"

Diff for: lua/neo-tree/sources/manager.lua

+1-8
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,7 @@ local function create_state(tabid, sd, winid)
3939
state.tabid = tabid
4040
state.id = winid or tabid
4141
state.dirty = true
42-
state.position = {
43-
is = { restorable = false },
44-
}
42+
state.position = {}
4543
state.git_base = "HEAD"
4644
events.fire_event(events.STATE_CREATED, state)
4745
table.insert(all_states, state)
@@ -527,11 +525,6 @@ M.reveal_current_file = function(source_name, callback, force_cwd)
527525
local state = M.get_state(source_name)
528526
state.current_position = nil
529527

530-
-- When events trigger that try to restore the position of the cursor in the tree window,
531-
-- we want them to ignore this "iteration" as the user is trying to explicitly focus a
532-
-- (potentially) different position/node
533-
state.position.is.restorable = false
534-
535528
local path = M.get_path_to_reveal()
536529
if not path then
537530
M.focus(source_name)

Diff for: lua/neo-tree/ui/renderer.lua

+26-38
Original file line numberDiff line numberDiff line change
@@ -522,8 +522,10 @@ M.focus_node = function(state, id, do_not_focus_window, relative_movement, botto
522522
end
523523
local success, err = pcall(vim.api.nvim_win_set_cursor, state.winid, { linenr, col })
524524

525-
-- now ensure that the window is scrolled correctly
526525
if success then
526+
-- forget about cursor position as it is overwritten
527+
M.position.clear(state)
528+
-- now ensure that the window is scrolled correctly
527529
local execute_win_command = function(cmd)
528530
if vim.api.nvim_get_current_win() == state.winid then
529531
vim.cmd(cmd)
@@ -647,59 +649,51 @@ M.position = {
647649
log.debug("There's already a position saved to be restored. Cannot save another.")
648650
return
649651
end
650-
651652
if state.tree and M.window_exists(state) then
652653
local win_state = vim.api.nvim_win_call(state.winid, vim.fn.winsaveview)
653654
state.position.topline = win_state.topline
654655
state.position.lnum = win_state.lnum
655656
log.debug("Saved cursor position with lnum: " .. state.position.lnum)
656657
log.debug("Saved window position with topline: " .. state.position.topline)
657-
-- Only need to restore the cursor state once per save, comes
658-
-- into play when some actions fire multiple times per "iteration"
659-
-- within the scope of where we need to perform the restore operation
660-
state.position.is.restorable = true
661658
end
662659
end,
663660
set = function(state, node_id)
664661
if not type(node_id) == "string" and node_id > "" then
665662
return
666663
end
667664
state.position.node_id = node_id
668-
state.position.is.restorable = true
665+
end,
666+
clear = function (state)
667+
log.debug("Forget about cursor position.")
668+
-- Clear saved position, so that we can save another position later.
669+
state.position.topline = nil
670+
state.position.lnum = nil
671+
-- After focusing a node, we clear it so that subsequent renderer.position.restore don't
672+
-- focus on it anymore
673+
state.position.node_id = nil
669674
end,
670675
restore = function(state)
671-
if state.position.is.restorable then
672-
if state.position.topline and state.position.lnum then
673-
log.debug("Restoring window position to topline: " .. state.position.topline)
674-
log.debug("Restoring cursor position to lnum: " .. state.position.lnum)
675-
vim.api.nvim_win_call(state.winid, function()
676-
vim.fn.winrestview({ topline = state.position.topline, lnum = state.position.lnum })
677-
end)
678-
-- Clear saved position, so that we can save another position later.
679-
state.position.topline = nil
680-
state.position.lnum = nil
681-
end
682-
if state.position.node_id then
683-
log.debug("Focusing on node_id: " .. state.position.node_id)
684-
M.focus_node(state, state.position.node_id, true)
685-
-- After focusing a node, we clear it so that subsequent renderer.position.restore don't
686-
-- focus on it anymore
687-
state.position.node_id = nil
688-
end
689-
else
690-
log.debug("Position is not restorable")
676+
if state.position.topline and state.position.lnum then
677+
log.debug("Restoring window position to topline: " .. state.position.topline)
678+
log.debug("Restoring cursor position to lnum: " .. state.position.lnum)
679+
vim.api.nvim_win_call(state.winid, function()
680+
vim.fn.winrestview({ topline = state.position.topline, lnum = state.position.lnum })
681+
end)
682+
end
683+
if state.position.node_id then
684+
log.debug("Focusing on node_id: " .. state.position.node_id)
685+
M.focus_node(state, state.position.node_id, true)
691686
end
692-
state.position.is.restorable = false
687+
M.position.clear(state)
693688
end,
694-
is = { restorable = true },
695689
}
696690

697691
---Redraw the tree without relaoding from the source.
698692
---@param state table State of the tree.
699693
M.redraw = function(state)
700694
if state.tree and M.tree_is_visible(state) then
701695
log.trace("Redrawing tree", state.name, state.id)
702-
-- every now and then this will fail because the window was closed in
696+
-- every now and then this will fail because the window was closed in
703697
-- betweeen the start of an async refresh and the redraw call.
704698
-- This is not a problem, so we just ignore the error.
705699
local success = pcall(render_tree, state)
@@ -938,7 +932,7 @@ local get_buffer = function(bufname, state)
938932
vim.api.nvim_buf_set_option(bufnr, "filetype", "neo-tree")
939933
vim.api.nvim_buf_set_option(bufnr, "modifiable", false)
940934
vim.api.nvim_buf_set_option(bufnr, "undolevels", -1)
941-
autocmd.buf.define(bufnr, "WinLeave", function()
935+
autocmd.buf.define(bufnr, "BufDelete", function()
942936
M.position.save(state)
943937
end)
944938
end
@@ -1045,15 +1039,9 @@ M.acquire_window = function(state)
10451039
vim.api.nvim_buf_set_name(state.bufnr, bufname)
10461040
vim.api.nvim_set_current_win(state.winid)
10471041
-- Used to track the position of the cursor within the tree as it gains and loses focus
1048-
--
1049-
-- Note `WinEnter` is often too early to restore the cursor position so we do not set
1050-
-- that up here, and instead trigger those events manually after drawing the tree (not
1051-
-- to mention that it would be too late to register `WinEnter` here for the first
1052-
-- iteration of that event on the tree window)
1053-
win:on({ "WinLeave" }, function()
1042+
win:on({ "BufDelete" }, function()
10541043
M.position.save(state)
10551044
end)
1056-
10571045
win:on({ "BufDelete" }, function()
10581046
win:unmount()
10591047
end, { once = true })

0 commit comments

Comments
 (0)