nvim-tree.lua
nvim-tree.lua copied to clipboard
Previous window is not selected unless :NvimTreeFocus is used
Description
From https://github.com/nvim-tree/nvim-tree.lua/issues/1985#issuecomment-1582896807
Is there really no way to open to the window that was previously active before selecting the nvim-tree window (regardless on navigation method)?
I have the same problem as @paulrouget, however I often use the mouse to start interacting with nvim-tree (to open a file, for instance). If I don't use :NvimTreeFocus, then it opens the file in the last window to have previously used :NvimTreeFocus (or presumably have been created by nvim-tree).
Would it be possible to use the lua equivalent of :winnr(#) (if it exists)?
Would it be possible to track the previous window by an event that fires every time you leave a window? Like maybe the WinLeave autocmd event? We could add another WinLeave autocmd similar to the one defined here, but using a negated pattern to ignore unwanted buffers like NvimTree_*.
TL;DR
This plugin can only track the "previous active window" when it's focused via :NvimTreeFocus
. If the nvim-tree is focused by any other method, it will still refer to the window where :NvimTreeFocus
was lat called, not the actual last window.
Neovim version
NVIM v0.9.0
Build type: Release
LuaJIT 2.1.0-beta3
Operating system and version
Linux 6.2.12-zen1-1-zen, MacOS 13.4
nvim-tree version
Latest master (034511714bacfadc5008e49f73fcef67e5613840 as of testing)
Minimal config
vim.g.loaded_netrw = 1
vim.g.loaded_netrwPlugin = 1
vim.cmd [[set runtimepath=$VIMRUNTIME]]
vim.cmd [[set packpath=/tmp/nvt-min/site]]
local package_root = "/tmp/nvt-min/site/pack"
local install_path = package_root .. "/packer/start/packer.nvim"
local function load_plugins()
require("packer").startup {
{
"wbthomason/packer.nvim",
"nvim-tree/nvim-tree.lua",
"nvim-tree/nvim-web-devicons",
-- ADD PLUGINS THAT ARE _NECESSARY_ FOR REPRODUCING THE ISSUE
},
config = {
package_root = package_root,
compile_path = install_path .. "/plugin/packer_compiled.lua",
display = { non_interactive = true },
},
}
end
if vim.fn.isdirectory(install_path) == 0 then
print "Installing nvim-tree and dependencies."
vim.fn.system { "git", "clone", "--depth=1", "https://github.com/wbthomason/packer.nvim", install_path }
end
load_plugins()
require("packer").sync()
vim.cmd [[autocmd User PackerComplete ++once echo "Ready!" | lua setup()]]
vim.opt.termguicolors = true
vim.opt.cursorline = true
-- MODIFY NVIM-TREE SETTINGS THAT ARE _NECESSARY_ FOR REPRODUCING THE ISSUE
_G.setup = function()
require("nvim-tree").setup({
actions = {
open_file = {
window_picker = {
enable = false
},
},
},
})
end
Steps to reproduce
Setup
Open nvim-tree and open at least 2 files in splits (vertical/horizontal doesn't seem to matter). In this example I'll open file1
, file2
, and file3
in vertical splits in order (1 on the left, 3 on the right).
-
nvim -nu /tmp/nvt-min.lua
-
:NvimTreeOpen
- Select
file1
and press<C-v>
-
:NvimTreeFocus
- Select
file2
and press<C-v>
-
:NvimTreeFocus
- Select
file3
and press<C-v>
The bug
- With window 3 selected (as it should be after the last step above), focus nvim-tree with
:NvimTreeFocus
- Open another file with
<CR>
. The file opens in window 3, as it was the last window selected. - Focus window 1 (with
file1
open) with any method of your choice (mouse,<C-w>h
, whatever) - Focus nvim-tree this time with a method that doesn't involve calling
:NvimTreeFocus
, like clicking the window with the mouse, or using<C-w>h
to move the cursor to the nvim-tree window. - Open a file that is not currently open in a window with
<CR>
Expected behavior
I would expect the file to be opened in window 1 (where file1
used to be), as it was the last window selected.
Actual behavior
The file is opened in window 3 (where file3
was), as it was the window selected when :NvimTreeFocus
was last called.
target_winid
tracking for the previous window was added ~2021 https://github.com/nvim-tree/nvim-tree.lua/pull/174
This is functional but incomplete, which explains this behaviour.
The #
buffer is tracked per window so that will not be useful.
<c-w><c-p>
can be used to switch to the previous window however I'm not seeing an obvious means of programatically finding the previously focused window.
It is tempting to remove target_winid
however I must be mindful of Chesterton's fence
We could manually track windows by tab, however this feels very wrong:
local log = require("nvim-tree.log")
local windows_by_tabpage = {
previous = {},
current = {},
}
local function remove_invalid(mapping)
for t, w in pairs(mapping) do
if not vim.api.nvim_tabpage_is_valid(t) or not vim.api.nvim_win_is_valid(w) then
mapping[t] = nil
end
end
end
vim.api.nvim_create_autocmd({ "WinEnter", "WinLeave" }, {
callback = function(d)
local tabpage = vim.api.nvim_get_current_tabpage()
local window = vim.api.nvim_get_current_win()
-- set previous or current
if d.event == "WinEnter" then
windows_by_tabpage.current[tabpage] = window
elseif d.event == "WinLeave" then
windows_by_tabpage.previous[tabpage] = window
end
-- tidy closed windows/tabs
remove_invalid(windows_by_tabpage.current)
remove_invalid(windows_by_tabpage.previous)
log.line("dev", "%s %s\n", d.event, vim.inspect(windows_by_tabpage))
end,
})
To be honest, that doesn't feel "wrong" to me. It's a simple and effective (as far as I can tell) way to track the previous window. I haven't found a mechanism built into nvim that provides this function, probably because using these autocmds is easy and clean enough.
It's more thorough than only tracking the previous window when using :NvimTreeFocus
.
I can attempt to put together a PR, if you could point me in the right directions for which parts of this plug-in are responsible for window tracking.
I can attempt to put together a PR, if you could point me in the right directions for which parts of this plug-in are responsible for window tracking.
That would be fantastic!
- Add the tracking bits above to
lib.lua
. Call that from an autocommand innvim-tree.lua
- Remove
lib.target_winid
. Any accessors should be changed to use theprevious
value. - Find other places where we should also use the
previous
value.
I am not 100% sure if this bug is the same I am encountering.
:tabedit $somepath
select a file to open, and NvimTree will focus the previous tab and ask me which window I want to replace with the file.
If before opening the file I execute :NvimTreeFocus
then NvimTree will open the file in a vertical split.
After that, with another :tabedid $somepath
, NvimTree will replace itself with the opened file (no vertical split, no focus on the previous tab). This last behavior is similar to the original netrw, and what I expect.
I am not 100% sure if this bug is the same I am encountering.
That splitting behaviour does sound different however I would not be surprised if the above fix resolved it.
I can't reproduce, however there are nvim and nvim-tree settings that would affect this sort of behaviour.
Can you please provide a reproducer with exact steps as per clean room replication?
See #2722