neo-tree.nvim
neo-tree.nvim copied to clipboard
position=current + opening file resets position in tree
Did you check docs and existing issues?
- [X] I have read all the docs.
- [X] I have searched the existing issues.
- [X] I have searched the existing discussions.
Neovim Version (nvim -v)
0.9.1
Operating System / Version
MacOS 13.5.1
Describe the Bug
I'm using :Neotree position=current toggle to toggle Neotree. When going to a line in the tree and then toggling it off and on the cursor stays on the same position. If I open a file in the tree, of :e open a file when I'm in the Neotree buffer the tree gets reset and the cursor resets to the top of the tree.
Is is possible to keep the current state of the tree when opening a file? I looked at the events but I wasn't sure if I could use those to get the behavior I'm looking for.
Screenshots, Traceback
https://github.com/nvim-neo-tree/neo-tree.nvim/assets/3979/2e457eb9-5b66-4c15-8772-d2b35035e009
Steps to Reproduce
- Open vim
- Open Neotree with
:Neotree position=current toggle - Move the cursor to a random position / other file
- Close Neotree with
qor:Neotree position=current toggle - Open Neotree again
- Observe the cursor remained on the same position
- Open the file under the cursor in the tree
- Open Neotree again
- Observe that the cursor jumped back to the top of the tree
Expected Behavior
I wanted the cursor to be in the same position before I opened the file.
Your Configuration
("neo-tree").setup({
close_if_last_window = false, -- Close Neo-tree if it is the last window left in the tab
popup_border_style = "rounded",
enable_git_status = true,
enable_diagnostics = true,
enable_normal_mode_for_inputs = false, -- Enable normal mode for input dialogs.
open_files_do_not_replace_types = { "terminal", "trouble", "qf" }, -- when opening files, do not use windows containing these filetypes or buftypes
sort_case_insensitive = false, -- used when sorting files and directories in the tree
sort_function = nil, -- use a custom function for sorting files and directories in the tree
-- sort_function = function (a,b)
-- if a.type == b.type then
-- return a.path > b.path
-- else
-- return a.type > b.type
-- end
-- end , -- this sorts files and directories descendantly
default_component_configs = {
container = {
enable_character_fade = true
},
indent = {
indent_size = 2,
padding = 1, -- extra padding on left hand side
-- indent guides
with_markers = true,
indent_marker = "│",
last_indent_marker = "└",
highlight = "NeoTreeIndentMarker",
-- expander config, needed for nesting files
with_expanders = nil, -- if nil and file nesting is enabled, will enable expanders
expander_collapsed = "",
expander_expanded = "",
expander_highlight = "NeoTreeExpander",
},
icon = {
folder_closed = "",
folder_open = "",
folder_empty = "",
-- The next two settings are only a fallback, if you use nvim-web-devicons and configure default icons there
-- then these will never be used.
default = "*",
highlight = "NeoTreeFileIcon"
},
modified = {
symbol = "[+]",
highlight = "NeoTreeModified",
},
name = {
trailing_slash = false,
use_git_status_colors = true,
highlight = "NeoTreeFileName",
},
git_status = {
symbols = {
-- Change type
added = "", -- or "✚", but this is redundant info if you use git_status_colors on the name
modified = "", -- or "", but this is redundant info if you use git_status_colors on the name
deleted = "✖", -- this can only be used in the git_status source
renamed = "", -- this can only be used in the git_status source
-- Status type
untracked = "",
ignored = "",
unstaged = "",
staged = "",
conflict = "",
}
},
-- If you don't want to use these columns, you can set `enabled = false` for each of them individually
file_size = {
enabled = true,
required_width = 64, -- min width of window required to show this column
},
type = {
enabled = true,
required_width = 122, -- min width of window required to show this column
},
last_modified = {
enabled = true,
required_width = 88, -- min width of window required to show this column
},
created = {
enabled = true,
required_width = 110, -- min width of window required to show this column
},
symlink_target = {
enabled = false,
},
},
-- A list of functions, each representing a global custom command
-- that will be available in all sources (if not overridden in `opts[source_name].commands`)
-- see `:h neo-tree-custom-commands-global`
commands = {},
window = {
position = "left",
width = 40,
mapping_options = {
noremap = true,
nowait = true,
},
mappings = {
["<space>"] = {
"toggle_node",
nowait = false, -- disable `nowait` if you have existing combos starting with this char that you want to use
},
["<2-LeftMouse>"] = "open",
["<cr>"] = "open",
["<esc>"] = "cancel", -- close preview or floating neo-tree window
["P"] = { "toggle_preview", config = { use_float = true } },
["l"] = "focus_preview",
["S"] = "open_split",
["s"] = "open_vsplit",
-- ["S"] = "split_with_window_picker",
-- ["s"] = "vsplit_with_window_picker",
["t"] = "open_tabnew",
-- ["<cr>"] = "open_drop",
-- ["t"] = "open_tab_drop",
["w"] = "open_with_window_picker",
--["P"] = "toggle_preview", -- enter preview mode, which shows the current node without focusing
["C"] = "close_node",
-- ['C'] = 'close_all_subnodes',
["z"] = "close_all_nodes",
--["Z"] = "expand_all_nodes",
["a"] = {
"add",
-- this command supports BASH style brace expansion ("x{a,b,c}" -> xa,xb,xc). see `:h neo-tree-file-actions` for details
-- some commands may take optional config options, see `:h neo-tree-mappings` for details
config = {
show_path = "none" -- "none", "relative", "absolute"
}
},
["A"] = "add_directory", -- also accepts the optional config.show_path option like "add". this also supports BASH style brace expansion.
["d"] = "delete",
["r"] = "rename",
["y"] = "copy_to_clipboard",
["x"] = "cut_to_clipboard",
["p"] = "paste_from_clipboard",
["c"] = "copy", -- takes text input for destination, also accepts the optional config.show_path option like "add":
-- ["c"] = {
-- "copy",
-- config = {
-- show_path = "none" -- "none", "relative", "absolute"
-- }
--}
["m"] = "move", -- takes text input for destination, also accepts the optional config.show_path option like "add".
["q"] = "close_window",
["R"] = "refresh",
["?"] = "show_help",
["<"] = "prev_source",
[">"] = "next_source",
["i"] = "show_file_details",
}
},
nesting_rules = {},
filesystem = {
filtered_items = {
visible = false, -- when true, they will just be displayed differently than normal items
hide_dotfiles = true,
hide_gitignored = true,
hide_hidden = true, -- only works on Windows for hidden files/directories
hide_by_name = {
--"node_modules"
},
hide_by_pattern = { -- uses glob style patterns
--"*.meta",
--"*/src/*/tsconfig.json",
},
always_show = { -- remains visible even if other settings would normally hide it
--".gitignored",
},
never_show = { -- remains hidden even if visible is toggled to true, this overrides always_show
--".DS_Store",
--"thumbs.db"
},
never_show_by_pattern = { -- uses glob style patterns
--".null-ls_*",
},
},
follow_current_file = {
enabled = false, -- This will find and focus the file in the active buffer every time
-- -- the current file is changed while the tree is open.
leave_dirs_open = false, -- `false` closes auto expanded dirs, such as with `:Neotree reveal`
},
group_empty_dirs = false, -- when true, empty folders will be grouped together
hijack_netrw_behavior = "open_default", -- netrw disabled, opening a directory opens neo-tree
-- in whatever position is specified in window.position
-- "open_current", -- netrw disabled, opening a directory opens within the
-- window like netrw would, regardless of window.position
-- "disabled", -- netrw left alone, neo-tree does not handle opening dirs
use_libuv_file_watcher = true, -- This will use the OS level file watchers to detect changes
-- instead of relying on nvim autocmd events.
window = {
mappings = {
["<bs>"] = "navigate_up",
["."] = "set_root",
["H"] = "toggle_hidden",
["/"] = "fuzzy_finder",
["D"] = "fuzzy_finder_directory",
["#"] = "fuzzy_sorter", -- fuzzy sorting using the fzy algorithm
-- ["D"] = "fuzzy_sorter_directory",
["f"] = "filter_on_submit",
["<c-x>"] = "clear_filter",
["[g"] = "prev_git_modified",
["]g"] = "next_git_modified",
["o"] = { "show_help", nowait = false, config = {
title = "Order by", prefix_key = "o" }
},
["oc"] = { "order_by_created", nowait = false },
["od"] = { "order_by_diagnostics", nowait = false },
["og"] = { "order_by_git_status", nowait = false },
["om"] = { "order_by_modified", nowait = false },
["on"] = { "order_by_name", nowait = false },
["os"] = { "order_by_size", nowait = false },
["ot"] = { "order_by_type", nowait = false },
},
fuzzy_finder_mappings = {
-- define keymaps for filter popup window in fuzzy_finder_mode
["<down>"] = "move_cursor_down",
["<C-n>"] = "move_cursor_down",
["<up>"] = "move_cursor_up",
["<C-p>"] = "move_cursor_up",
},
},
commands = {} -- Add a custom command or override a global one using the same function name
},
buffers = {
follow_current_file = {
enabled = false, -- This will find and focus the file in the active buffer every time
-- -- the current file is changed while the tree is open.
leave_dirs_open = false, -- `false` closes auto expanded dirs, such as with `:Neotree reveal`
},
group_empty_dirs = true, -- when true, empty folders will be grouped together
show_unloaded = true,
window = {
mappings = {
["bd"] = "buffer_delete",
["<bs>"] = "navigate_up",
["."] = "set_root",
["o"] = { "show_help", nowait = false, config = {
title = "Order by", prefix_key = "o" }
},
["oc"] = { "order_by_created", nowait = false },
["od"] = { "order_by_diagnostics", nowait = false },
["om"] = { "order_by_modified", nowait = false },
["on"] = { "order_by_name", nowait = false },
["os"] = { "order_by_size", nowait = false },
["ot"] = { "order_by_type", nowait = false },
}
},
},
git_status = {
window = {
position = "float",
mappings = {
["A"] = "git_add_all",
["gu"] = "git_unstage_file",
["ga"] = "git_add_file",
["gr"] = "git_revert_file",
["gc"] = "git_commit",
["gp"] = "git_push",
["gg"] = "git_commit_and_push",
["o"] = { "show_help", nowait = false, config = {
title = "Order by", prefix_key = "o" }
},
["oc"] = { "order_by_created", nowait = false },
["od"] = { "order_by_diagnostics", nowait = false },
["om"] = { "order_by_modified", nowait = false },
["on"] = { "order_by_name", nowait = false },
["os"] = { "order_by_size", nowait = false },
["ot"] = { "order_by_type", nowait = false },
}
}
},
event_handlers = {
-- {
-- event = "neo_tree_buffer_leave",
-- handler = function()
-- error("zzz")
-- end
-- },
-- {
-- event = "file_open_requested",
-- handler = function(file_path)
-- error("zzz")
-- -- auto close
-- -- vimc.cmd(":Neotree position=current toggle<cr>")
-- -- OR
-- -- require("neo-tree.command").execute({ action = "close" })
-- end
-- },
-- {
-- event = "file_opened",
-- handler = function(file_path)
-- error("adfaf")
-- -- auto close
-- -- vimc.cmd(":Neotree position=current toggle<cr>")
-- -- OR
-- -- require("neo-tree.command").execute({ action = "close" })
-- end
-- },
}
})
-- maybe add something like this: https://www.reddit.com/r/neovim/comments/118unhi/nvimtree_follow_open_files_buffers/j9kvxgb/
vim.keymap.set({ "n" }, "-", ":Neotree position=current toggle<cr>",
{ desc = "Toggle neotree" })
If I remember correctly, that's a limitation of position=current unfortunately.
Instead, how about position=float (which does remember your cursor position)? Or you could set the config option config.filesystem.follow_current_file.enabled = true to achieve something similar.
Actually I think this is a bug @pysan3. I never noticed because I have always used follow_current_file and reveal so it is always focused on my last used file. With the steps described I would have expected it to retain focus from the last session.
Using config.filesystem.follow_current_file.enabled = true in combination with position=current doesn't seem to solve the issue. When opening a a file and then toggling neo-tree, the cursor in neo-tree jumps back to the top.
Is there a way I could adjust this behavior with event_handlers for example?
Also maybe helpful to point out: the cursor resets, but the state of the folder tree / open directories are remembered when toggling neo-tree.
@LeonB I was testing the @cseickel solution and you actually need to make sure to use reveal along with config.filesystem.follow_current_file.enabled = true. In my case I'm using a keymap ':Neotree reveal toggle<CR>' and I always set the cursor in the tree exactly on my last open buffer. The only issue I can see is that this doesn't really remember the last position like in the position=float configuration but it does the trick if you don't really mind the behaviour I'm mentioning.
I had a similar issue, for the moment downgrading to tag "3.14" fix the issue for me. use({ "nvim-neo-tree/neo-tree.nvim", tag = "3.14" })
Hi, could you test with the latest main branch againt?
I hope this is now fixed through a series of cursor position related PRs.
The suggestion from @danieljonguitud seemed to work!
vim.keymap.set({ "n" }, "-", ":Neotree reveal position=current toggle<cr>",
{ desc = "Toggle neotree" })
Now toggling remember the cursor position