nvim-tree / nvim-tree.lua

A file explorer tree for neovim written in lua

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Feature: Nvim tree open in current buffer

wilkinson4 opened this issue · comments

I recently switched from using NerdTree, and it would be nice to have the ability to use nvim-tree like nerdtree/netrw in that when you open the tree it doesn't close the current buffer you are in. Also, I think it would be nice if the tree could open up in the current buffer instead of opening up in a fixed position("top", "left", "right", "bottom"). IMO this makes buffer management easier instead of having to worry if nvim-tree is going to close your buffer when you hit -. I typically will work in multiple buffer splits, and this is very difficult at the moment with nvim-tree.

commented

i don't understand what you mean by closing the current buffer ? There are options to configure this. Could you maybe share your config so i can pinpoint what's wrong (or read the documentation more thoroughly, but might be longer this way).

Here is my nvim-tree config

let g:nvim_tree_quit_on_open = 1 "0 by default, closes the tree when you open a file
let g:nvim_tree_indent_markers = 1 "0 by default, this option shows indent markers when folders are open
let g:nvim_tree_git_hl = 1 "0 by default, will enable file highlight for git attributes (can be used without the icons).
let g:nvim_tree_highlight_opened_files = 1 "0 by default, will enable folder and file icon highlight for opened files/directories.
let g:nvim_tree_root_folder_modifier = ':~' "This is the default. See :help filename-modifiers for more options
let g:nvim_tree_add_trailing = 1 "0 by default, append a trailing slash to folder names
let g:nvim_tree_group_empty = 1 " 0 by default, compact folders that only contain a single folder into one node in the file tree
let g:nvim_tree_icon_padding = ' ' "one space by default, used for rendering the space between the icon and the filename. Use with caution, it could break rendering if you set an empty string depending on your font.
let g:nvim_tree_symlink_arrow = ' >> ' " defaults to ' ➛ '. used as a separator between symlinks' source and target.
" let g:nvim_tree_respect_buf_cwd = 1 "0 by default, will change cwd of nvim-tree to that of new buffer's when opening nvim-tree.
let g:nvim_tree_create_in_closed_folder = 0 "1 by default, When creating files, sets the path of a file when cursor is on a closed folder to the parent folder when 0, and inside the folder when 1.
let g:nvim_tree_refresh_wait = 500 "1000 by default, control how often the tree can be refreshed, 1000 means the tree can be refresh once per 1000ms.
let g:nvim_tree_window_picker_exclude = {
    \   'filetype': [
    \     'notify',
    \     'packer',
    \     'qf'
    \   ],
    \   'buftype': [
    \     'terminal'
    \   ]
    \ }
" Dictionary of buffer option names mapped to a list of option values that
" indicates to the window picker that the buffer's window should not be
" selectable.
let g:nvim_tree_special_files = { 'README.md': 1, 'Makefile': 1, 'MAKEFILE': 1 } " List of filenames that gets highlighted with NvimTreeSpecialFile
let g:nvim_tree_show_icons = {
    \ 'git': 1,
    \ 'folders': 0,
    \ 'files': 0,
    \ 'folder_arrows': 0,
    \ }
"If 0, do not show the icons for one of 'git' 'folder' and 'files'
"1 by default, notice that if 'files' is 1, it will only display
"if nvim-web-devicons is installed and on your runtimepath.
"if folder is 1, you can also tell folder_arrows 1 to show small arrows next to the folder icons.
"but this will not work when you set indent_markers (because of UI conflict)

" default will show icon by default if no icon is provided
" default shows no icon by default
let g:nvim_tree_icons = {
    \ 'default': '',
    \ 'symlink': '',
    \ 'git': {
    \   'unstaged': "",
    \   'staged': "",
    \   'unmerged': "",
    \   'renamed': "",
    \   'untracked': "",
    \   'deleted': "",
    \   'ignored': ""
    \   },
    \ 'folder': {
    \   'arrow_open': "",
    \   'arrow_closed': "",
    \   'default': "",
    \   'open': "",
    \   'empty': "",
    \   'empty_open': "",
    \   'symlink': "",
    \   'symlink_open': "",
    \   }
    \ }

nnoremap <C-n> :NvimTreeToggle<CR>
nnoremap <leader>r :NvimTreeRefresh<CR>
nnoremap <leader>n :NvimTreeFindFile<CR>
" NvimTreeOpen, NvimTreeClose, NvimTreeFocus, NvimTreeFindFileToggle, and NvimTreeResize are also available if you need them

" a list of groups can be found at `:help nvim_tree_highlight`
highlight NvimTreeFolderIcon guibg=blue

I have the following NerdTree config in case this helps to compare

local opts = { noremap=true, silent=true }

vim.api.nvim_set_keymap('n', '<leader>nn', ':NERDTreeToggle<CR>:wincmd =<CR>', opts)
vim.api.nvim_set_keymap('n', '<leader>nf', ':NERDTreeFind<CR>:wincmd =<CR>', opts)
vim.cmd 'let g:NERDTreeShowBookmarks = 1'
vim.cmd 'let g:NERDTreeChDirMode = 1'
vim.cmd 'let g:NERDTreeMinimalUI = 1'
vim.cmd 'let g:NERDTreeHighlightCursorline = 0'
vim.cmd 'let g:WebDevIconsNerdTreeAfterGlyphPadding = " "'
vim.cmd 'let g:WebDevIconsNerdTreeGitPlugForceVAlign = ""'
vim.cmd 'let g:NERDTreeFileExtensionHighlightFullName = 1'

This is actually exactly what I'm looking for too. So the idea is that instead of opening new sidebar left/top/right or bottom. We would have option like 'buffer', which would replace current buffer with nvim-tree and after choosing file and opening it, nvim-tree would be again replaced with chosen new file.

This is how netrw working and some people prefer this kind of behaviour. I think this article explains it pretty well:
http://vimcasts.org/blog/2013/01/oil-and-vinegar-split-windows-and-project-drawer/

I, for one, am a huge fan of the vinegar method of file management as described by Sneikki, and implemented by Tim Pope in his vinegar.vim repository

My dream setup would be to be able to hit <leader>t to get nvim-tree as a persistent sidebar (e.g. stays open until I explicitly close it) and - to open parent directory of active file in current buffer window a la vinegar (if I open a file it opens in the current window effectively replacing the file explorer).

I tried by combining both nvim-tree and vinegar, but the former seems to replace the latter (experimenting with settings as I'm writing this).

commented

So you would like a vinegar mode basically ? I thought about doing this, maybe this is a good place to implement when cleaning up and fixing the view module at some point.

That would cover a lot of ground. Sometimes you want to quickly go down one level to see what's there, open up a related file, or whatever. You don't want to get lost in a tree here (albeit enabling "tree mode" could be an option). This is were vinegar really shines. nvim-tree rocks when you want to make sense of large hierarchical structures, or navigate back and forth between directories that are "far apart". Combing both would be awesome as both modes would share the same mappings and general configuration.

commented

Hi, i'm currently implementing an open method to allow a vinegar style.
Some questions i have for you people, because i've never used vinegar, and i'm not sure how it behaves when opening:

  1. does it wipe, delete or hide the buffer from which its opening ?
  2. does it close all windows if there are multiple windows ?

The buffer is hidden when vinegar is opened.
If there are multiple windows, then the file explorer window remains in the window it was opened in. This example illustrates:
image
For Tpope's vinegar, the - command is used to open the file.
In my experience, if the hijack_netrw option is set, the - command properly opens the tree in the side bar.

commented

Vinegar style should be available if i implemented it correctly. If you find any issue please let me know :)
To use this, see :help nvim-tree-vinegar

I'm amazed at the timing of implementing this feature 😄 I've just started using netrw instead of nvim-tree yesterday and immediately I'm missing the icons and git colors. It's great to be able to use nvim-tree in an netrw way.

After trying out vinegar mode of nvim-tree, there are some things I'd like to point out:

  1. nvim-tree uses the window's current working directory to decide the root of the file tree. After doing <C-]> or -, the current working directory is changed, and when I then open a file, it inherits the current working directory of the nvim-tree window, and not the vim's current working directory. netrw does not do that, it allows going up/down the directory tree and opening files without changing their current working directory, which I prefer. Is there an easy way of achieving that?

  2. After opening a file in place in nvim-tree (<C-e>), the tree is still shown on the side (albeit after another UI redraw). Doing the same in netrw hides the tree. I prefer netrw's behavior here. Looks like abandoning the current window https://github.com/kyazdani42/nvim-tree.lua/blob/494c9ecfbfe4e812d0c81b1f9169f336ffc35f75/lua/nvim-tree/actions/open-file.lua#L151 may not work correctly

  3. A welcome addition would be to automatically focus the opened buffer in open_replacing_current_buffer

  4. Another welcome addition would be for splits to appear relative to the nvim-tree window, without treating it as special. In the following example, after doing <C-v> I expect the new window to appear to the right of the nvim-tree buffer (bottom right), not top-right.

    Peek.2022-02-22.08-54.mp4
  5. For Tpope's vinegar, the - command is used to open the file.

    This is wrong. - is used to open netrw. <CR> is used to open the file in place. This means the user needs to map - to open_replacing_current_buffer in their global mappings. You may want to edit the nvim-tree-vinegar documentation to mention it instead of the existing information about the - mapping in nvim-tree mappings 🙂

Aside from that, I'm quite digging the new mode 👌

commented
  1. Even if you do not update the cwd globally, it will still update it for the tree window, and when opening a buffer in it, the window will still have this cwd set. An alternative would be to set the path to the window as the path to the file which is opened ?
  2. this is feasible
  3. the open-file function is getting really big and messy but the behavior you describe would make more sense indeed.
  4. you are right, docs should be updated 😄 done

The issue you mentioned ind 2 is related to something else actually. I might need to fix this but i'm not 100% sure how. You can set quit_on_open in the open-file action setup to avoid this behavior.

  1. I see, this can be tricky. I didn't play around with netrw enough to know it behaves with regards to cwd at all times, so I can't really tell. Another solution would be to remember the cwd in open_replacing_current_buffer and restore it in edit_in_place. The cwd could be stored in a buffer/window variable. Alternatively, nvim-tree could avoid using window's cwd to determine the root of the tree, but I imagine this is a hard change 😄

    EDIT: actually, it turned out to be pretty easy to change. The only thing I had to do was remove https://github.com/kyazdani42/nvim-tree.lua/blob/61b57e3676480687a0fbcc4e90f7e1bf779fb7f7/lua/nvim-tree/actions/change-dir.lua#L26-L32 and I could freely move up and down the directory tree without affecting my cwd in any way 🎉 Maybe we could add a configuration option to avoid modifying cwd?

    After removing that part, though, I noticed that editing a file in place opened the file, but then immediately replaced it with its alternate file (the file right before I opened nvim-tree). Yet another workaround here is to call the edit command again in <C-e>:

    {
        key = "<C-e>",
        action = "whatever",
        action_cb = function(node)
    	    vim.cmd("edit " .. vim.fn.fnameescape(node.absolute_path))
    	    require("nvim-tree").toggle()
    	    vim.cmd("edit " .. vim.fn.fnameescape(node.absolute_path))
        end,
    }

    Jumping to the alternate file also works:

    {
        key = "<C-e>",
        action = "whatever",
        action_cb = function(node)
    	    vim.cmd("edit " .. vim.fn.fnameescape(node.absolute_path))
    	    require("nvim-tree").toggle()
    	    vim.cmd("edit #")
        end,
    }
  2. You are right, I linked to the wrong line initially. Take a look at the edited comment.

    In the meantime, I was able to fix the issue with the following mapping:

    mappings = {
        list = {
    	    {
    		    key = "<C-e>",
    		    action = "whatever",
    		    action_cb = function(node)
    			    vim.cmd("edit " .. vim.fn.fnameescape(node.absolute_path))
    			    require("nvim-tree").toggle()
    		    end,
    	    },
        },
    },

    This hides the tree that automatically appears in the default <C-e> mapping

  3. Here's the code I am using to automatically focus the buffer after opening the tree replacing current buffer

    require("which-key").register({
        ["-"] = {
    	    function()
    		    local previous_buf = vim.api.nvim_get_current_buf()
    		    require("nvim-tree").open_replacing_current_buffer()
    		    require("nvim-tree").find_file(false, previous_buf)
    	    end,
    	    "NvimTree in place",
        },
    })
  4. I implemented it myself to avoid making the open_file function more complex, with the following mapping:

    {
        key = "<C-v>",
        action = "split_right",
        action_cb = function(node)
    	    vim.cmd("vsplit " .. vim.fn.fnameescape(node.absolute_path))
        end,
    },

    This does what I want and splits the nvim-tree window instead of splitting another existing window 😄

    EDIT: unfortunately, the buffer is closed after I open another file in place in the original nvim-tree window 😟

  5. Thanks!

I was able to configure nvim-tree to behave almost like netrw (Gelio/ubuntu-dotfiles@a174ce1). The only thing I am missing that requires modifying the plugin's code is maintaining cwd when moving up and down the directory structure. See the first point in my previous comment in this issue to find out what I mean and what needs to be disabled

I'm not raising any PRs myself yet because the config changes I made are still pretty messy, so I hope @kyazdani42 can suggest how some more robust improvements

I don't get nvim-tree working with netrw hijacking that it doesn't completely destroy splits.

If I have a vsplit: Left side is my code, on the right I want to open another file and I do: :e dir/

Then the first thing is that my left split is replaced by nvim-tree and if I then open a file by pressing enter, I don't have a split anymore. It destroys completely my splits. This works just fine with netrw.

@cryptomilk Looks like you will need to set up a mapping to open nvim-tree in place for that buffer on the right. The contents of that mapping could be

  local previous_buf = vim.api.nvim_get_current_buf()
  require("nvim-tree").open_replacing_current_buffer()
  require("nvim-tree").find_file(false, previous_buf)

I ended up tweaking the nvim-tree configuration and I believe I arrived at a pretty usable config. To show it easier to others, I ended up creating a PR for my own dotfiles: Gelio/ubuntu-dotfiles#1. Feel free to copy it to your own configs. We could also try to modify nvim-tree to make this netrw-mode easier to use (at the moment it requires quite a few modifications to the config, some of which can be considered hacks, like disabling winfixheight and winfixwidth).

I also raised #1019 since that is the only modification to nvim-tree's source code to use nvim-tree netrw-mode comfortably.

Thank you all! This is awesome! 🎉

commented

@Gelio i agree we could make this easier to set up. I'll fix the window reopening when opening the file in issue 😄

Great, thank you for fixing it! It seems netrw-mode / vinegar-mode can be used comfortably now, at least by me. It still requires some customization (see https://github.com/Gelio/ubuntu-dotfiles/pull/1/files). If you want to make it easier to onboard netrw users, I can help out to make the configuration easier (fix lualine extension, split nvim-tree window like a regular window).

We would need to discuss how to do it first 😄

Looks nice!

  • Would it be possible to make - open the current dir if you're on the start screen? E.g. when I start vim with just vim it'd be nice to be able to hit - to see what's there.
  • I can almost get both modes to play nicely together. If I use the edit_in_place action as per the help, vinegar mode works fine, but all files in the tree are opened inside the tree's window. If I do not use edit_in_place the tree pops up when I open a file from vinegar mode.
commented
  1. not sure if you should map - to some command that would open the tree and then unmap the - mapping ?
  2. would using quit_on_open in setup help for this situation ?

not sure if you should map - to some command that would open the tree and then unmap the - mapping ?

Sure, I can fix it. Was more of a suggestion for sane default behavior :) Right now I just check if the buffer name is "" and open the cwd in nvim-tree if it is.

would using quit_on_open in setup help for this situation ?

That is what I'm using at the moment to get by. But it gets annoying quickly. Especially since nvim-tree doesn't remember the state when I re-open it... and I use the sidebar mode to explore large code bases.

commented

Could you open a feature request for this with a proper description of the behavior you want ? This might just be done through custom scripting though :)