5

This didn't get much love on stackoverflow (https://stackoverflow.com/q/48269793/2512141), but I think it's important so I'm reposting here. I think this could be a major barrier to people using Vim's buffers as they're intended, and consequently they resort to tabs to get the file-switching capability they need. Text from the original post follows.

Vim's Netrw file explorer has the following bug: Running the command :e. will open Netrw, but after Netrw closes there is a latent buffer in Vim's buffer list which cannot be traversed with command :bprev. (:bnext works fine.)

This bug is discussed in the following places:

https://www.bountysource.com/issues/45921122-previous-doesn-t-work-with-e-buffer

https://groups.google.com/forum/#!topic/vim_use/zzeQItJQNZI

To replicate this bug, start Vim and run the following commands:

:ls!
:edit ./file1.txt | ls!
:edit ./file2.txt | ls!
:e. #(choose file3.txt in Netrw)
:edit ./file4.txt | ls!
:ls!

At this point, you will see buffers for the files you have opened as well as some buffers with paths, and a buffer with [No Name]. Try to navigate these buffers with

:bnext | ls!
:bprev | ls!

You will find that :bnext successfully loops over the buffers, but :bprev hangs on the Netrw buffer. Is there a workaround for this bug so that buffer navigation with :bnext and :bprev still works?

  • 2
    You should discuss this issue with Charles, the netrw plugin maintainer. He is the best chance to get this fixed. – Christian Brabandt Jan 27 '18 at 19:56
  • I like that idea. I have an issue registered on github, github.com/vim/vim/issues/2597 , but if it doesn't go anywhere I'll reach out to him. – BitPusher16 Jan 30 '18 at 15:21
  • fwiw to you, I cannot replicate this. version or option difference maybe? – Mass Jan 31 '18 at 21:13
  • @Mass Interesting... It could be something in my vimrc: bitbucket.org/BitPusher16/dotfiles/src/… . But I know at least a few other people have had the problem. (See links in my post.) Which step specifically is not replicating? Do you see the [No Name] buffer after running :e. ? – BitPusher16 Feb 2 '18 at 0:12
  • @BitPusher16 correct, I do not see [No Name]. After the last ls! on the first code block I have buffers 1,2,4,5, and 6; 4 is ~/path. I can tell you the difference is the hidden option. I know it's popular but consider removing it until know the full consequence of the option. Additionally, if you do :bwipe manually you can get rid of the buffer. Possibly you could set up an autocmd to do this for you. – Mass Feb 2 '18 at 15:32
3

I've discovered through experimentation that :bprev will resume functioning if I delete the path buffer just prior to the [No Name] buffer. However, this is burdensome.

Instead, I have started using :Explore to open Netrw. This does not create the latent buffer which trips up :bprev, but I am still able to browse my local directory tree and open files for editing.

1

Maybe this function will help you? I use it in my neovim configuration. With it :bprev works as expected.

ToggleNetrw display netrw explorer in current window (with command :Ntree) on specified directory (or parent directory of current opened file) and cleanup excess buffer to fix unexpected :bprev behaviour.

Second call of ToggleNetrw hide explorer and show previous buffer.

function! ToggleNetrw(...)
  if &filetype ==# 'netrw'
    execute 'Rexplore'
  else
    if a:0 ==# 1
      let path = fnamemodify(expand(a:1), ':p')
    else
      let path = fnamemodify(expand('%'), ':p:h')
    endif
    execute 'Ntree' path
    let excess_buffer = bufnr(path)
    if excess_buffer != -1
      execute 'bdelete' excess_buffer
    endif
  endif
endf
nnoremap <silent> <Leader>ee :call ToggleNetrw()<CR>
nnoremap <silent> <Leader>ec :call ToggleNetrw('.')<CR>
nnoremap <silent> <Leader>eh :call ToggleNetrw($HOME)<CR>
  • Welcome to this site @zpah, you could edit your answer to explain your code a little more: that would be useful for future reader so that they can understand faster what your function does. – statox Nov 29 '18 at 8:51
0

Yang-Le Wu (yangle) works around the problem by using keybinds to switch buffer. See the commit linked from the issue:

https://github.com/yangle/dotfiles/commit/d2e3962a4f1c42f32ae1fa70fb690665011f1a43

The keybinds call a function which will remove the first netrw buffer, if found, before attempting to do the actual movement.

Without the first buffer sitting in the way, the movement will go to the expected buffer.

So that's one solution, but it does require using certain keybinds. You may want to add some of the other popular keystrokes:

noremap <silent> [b :call ChangeBuffer("prev")<CR>
noremap <silent> ]b :call ChangeBuffer("next")<CR>
noremap <silent> :bp<CR> :call ChangeBuffer("prev")<CR>
noremap <silent> :bn<CR> :call ChangeBuffer("next")<CR>
noremap <silent> :bprev<CR> :call ChangeBuffer("prev")<CR>
noremap <silent> :bnext<CR> :call ChangeBuffer("next")<CR>

But I have had limited success with it. It seems to always destroy the netrw buffer when it's unfocused.

I use :set hidden. I don't want to destroy it, I just don't want to get stuck on it!


My own experiments are a WIP. I started off trying to remove the second buffer, as suggested by BitPusher16. I used this method to detect it, which seems to work even if it was destroyed and then recreated:

buflisted(bufnum) == 0 && getbufvar(bufnum, "netrw_curdir") != ''

But if we do remove netrw2, the next time we focus the netrw1 buffer, it will recreate the second buffer now at the end of the buffer list, and focus it. This moves us out of our place in the buffer list.

If I have time, I may pursue a new strategy:

  • Still use a function to change buffer (using keybinds as above). Inside the function:
  • If we start off focused on netrw2, then switch to netrw1 before moving.
  • If after moving, we are now focused on netrw2, perform another move in the same direction (skip it).

In this case we won't actually need to destroy the second netrw window. We will rather skip it, and act as if netrw1 and 2 are bound together.

If that does work, investigate edge cases:

  • ...Worry about counts like :3bprev or 3[b...
  • ...Worry about multiple open netrw buffers...
  • ...Check if the strategy still works with netrw visible in window panes...
  • ...Worry about cleaning up both netrw windows, if the user deletes one of them...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.