neo-tree.nvim icon indicating copy to clipboard operation
neo-tree.nvim copied to clipboard

position=current + opening file resets position in tree

Open LeonB opened this issue 2 years ago • 5 comments

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

  1. Open vim
  2. Open Neotree with :Neotree position=current toggle
  3. Move the cursor to a random position / other file
  4. Close Neotree with q or :Neotree position=current toggle
  5. Open Neotree again
  6. Observe the cursor remained on the same position
  7. Open the file under the cursor in the tree
  8. Open Neotree again
  9. 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" })

LeonB avatar Sep 11 '23 11:09 LeonB

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.

pysan3 avatar Oct 18 '23 08:10 pysan3

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.

cseickel avatar Oct 21 '23 16:10 cseickel

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 avatar Nov 06 '23 11:11 LeonB

@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.

danieljonguitud avatar Dec 07 '23 05:12 danieljonguitud

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" })

kasshedi117 avatar Jan 19 '24 18:01 kasshedi117

Hi, could you test with the latest main branch againt?

I hope this is now fixed through a series of cursor position related PRs.

pysan3 avatar Mar 12 '24 10:03 pysan3

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

LeonB avatar Mar 21 '24 13:03 LeonB