10

neovim 0.2-dev

:Lexplore opens up explorer window and entering :Lexplore again toggles it. However, if I interact with the explorer window(i.e. expand a directory), then typing :Lexplore opens up another explorer window instead of closing the existing one.

Lexplore opens up a new explorer

Is this the expected behavior? Is there any command/function that will toggle explorer even if the window had interaction?

10 Answers 10

5

Please try v162j of netrw which may have fixed this problem: http://www.drchip.org/astronaut/vim/index.html#NETRW

12

I followed this script (https://www.reddit.com/r/vim/comments/6jcyfj/toggle_lexplore_properly/djdmsal/) and it works as expected.

let g:NetrwIsOpen=0

function! ToggleNetrw()
    if g:NetrwIsOpen
        let i = bufnr("$")
        while (i >= 1)
            if (getbufvar(i, "&filetype") == "netrw")
                silent exe "bwipeout " . i 
            endif
            let i-=1
        endwhile
        let g:NetrwIsOpen=0
    else
        let g:NetrwIsOpen=1
        silent Lexplore
    endif
endfunction

" Add your own mapping. For example:
noremap <silent> <C-E> :call ToggleNetrw()<CR>
6

Once this works, each time Lexplore is toggled on, it will create a new buffer but not wipe the previous one.

A solution is to wipeout netrw buffers when they are hidden.

augroup AutoDeleteNetrwHiddenBuffers
  au!
  au FileType netrw setlocal bufhidden=wipe
augroup end

Then, Lexplore does work as intended.

See bufhidden.

2
  • Is there a way to set that for the Vexplore too?
    – Eddy Ekofo
    Commented Jan 15, 2021 at 14:16
  • This should work for any netrw buffer, however you opened it.
    – Biggybi
    Commented Jan 16, 2021 at 12:42
3

Updating the version of the netrw plugin indeed fixes the problem, as stated in this answer.

On my Vim v8.0 (installed with Homebrew), I had netrw v156 (find out with :echo g:loaded_netrwPlugin), and the mentioned problem existed. You can find the newest version of netrw on Dr. Chip's website (currently v165b, updated on 13 March 2019). Installing this version fixed the problem for me (confirming what is stated in the other answer that the problem should have been fixed in v162j).

Here is how to install the newest version of the netrw plugin:

  1. Go to http://www.drchip.org/astronaut/vim/index.html#NETRW
  2. Click on the title, this should download a file named netrw.vba.gz
  3. The netrw.vba file contained in the downloaded archive is a vimball file. A vimball file is something like a self-installing plugin. Note that you don't have to unzip the .gz file, as this is done automatically in the next step.
  4. Install the plugin (as explained here or here or by :help vimball):
    1. Open the vimball file with Vim: vim netrw.vba.gz
    2. In Vim, run: :source %

The above command installs the components of the plugin to their proper locations in one of your Vim directories (most probably ~/.vim).

After the installation, you can restart Vim and test if the new version of the plugin has been correctly installed:

:echo g:loaded_netrwPlugin

This should output v165b now (or whatever version you have installed).

2

I tried several times and it seems once you have interacted with the content, it opens a new window when :Lexplore is called again like you stated above, however, it could be a desired behavior when you just want to explore multiple directories at once, why not use :NERDTree instead if you just want to keep a single && browser?

3
  • 1
    Hey thank you for looking into this. netrw does everything I need for exploring and interacting with files and directories. I don't want to install a plugin only for toggling behavior.
    – Sayem
    Commented Jan 15, 2017 at 7:57
  • I wasn't able to reproduce this behavior here, tried to open and close several directories and open files, but :Lexplore simply works. What exactly have you guys done to get that?
    – lsrdg
    Commented Jan 15, 2017 at 11:42
  • Try with the latest neovim 0.2-dev or Vim 7.4
    – Sayem
    Commented Jan 16, 2017 at 21:12
2

Full solution (Vexplore + buffer resize + conf) based on different answers and my own experimentation. Togglecode taken from: https://stackoverflow.com/questions/5006950/setting-netrw-like-nerdtree enter image description here

function! ToggleVimExplorer()
  if exists("t:expl_buf_num")
      let expl_win_num = bufwinnr(t:expl_buf_num)
      if expl_win_num != -1
          let cur_win_nr = winnr()
          exec expl_win_num . 'wincmd w'
          close
          exec cur_win_nr . 'wincmd w'
          unlet t:expl_buf_num
      else
          unlet t:expl_buf_num
      endif
  else
      exec '1wincmd w'
      Vexplore 
      " After switching to netwr buff, lets resize to 45
      vertical resize 45
      let t:expl_buf_num = bufnr("%")
  endif
endfunction

nmap <leader>9 :call ToggleVimExplorer()<cr>

function! NetrwMapping()
    " noremap <buffer> <C-l> <C-W>l
    " noremap <buffer> <C-h> <C-W>h

    let g:netrw_banner = 0 " remove the banner at the top
    let g:netrw_liststyle = 3  " default directory view. Cycle with i 
    let g:netrw_browse_split = 4
    let g:netrw_altv = 1
    let g:netrw_sort_sequence = '[\/]$,*

    let g:netrw_list_hide= '.*.swp$, 
            \ *.pyc$,
            \ *.log$,
            \ *.o$,
            \ *.xmi$,
            \ *.swp$,
            \ *.bak$,
            \ *.pyc$,
            \ *.class$,
            \ *.jar$,
            \ *.war$,
            \ *__pycache__*'

endfunction

augroup netrw_mapping
    autocmd!
    autocmd filetype netrw call NetrwMapping()
augroup END
2
  • 1
    Welcome to Vi and Vim and thanks for writing a thoughtful answer!
    – filbranden
    Commented Jun 17, 2020 at 19:49
  • g:netrw_sort_sequence values is missing the closing quote. Couldn't suggest edit since the change is less than 6 chars.
    – Joyce Babu
    Commented Mar 10, 2023 at 6:37
1

This is something that worked for me after I looked at the code for netrw.vim Seems like :Rexplore will look if the variable w:netrw_rexlocal exists, if it doesn't (which happens when you have a netrw window that didn't come from a buffer window) it will cause a warning to appear on screen. Seems that there is a w:netrw_rexfile variable being set though, which you can use to return the editing file.

function ToggleExplorer()
    if &ft == "netrw"
        if exists("w:netrw_rexfile")
            if w:netrw_rexfile == "" || w:netrw_rexfile == "NetrwTreeListing"
                quit
            else
                exec 'e ' . w:netrw_rexfile
            endif
        else
            if exists("w:netrw_rexlocal")
                Rexplore
            else
                quit
            endif
        endif
    else
        Explore
    endif
endfun
2
  • Welcome to Vi and Vim! A little explanation with the code would go a long way. Also: exec 'q' is just quit; you only need execute when you're building up commands from strings or to protect commands from consuming |.
    – D. Ben Knoble
    Commented Apr 2, 2021 at 21:27
  • Thank you Ben, added the explanation, the way I found my solution was to read the netrw.vim script, since I wanted to supress the warning that was displayed when using Rexplore
    – c64cosmin
    Commented Apr 3, 2021 at 23:29
0

Based on alwc's answer without using global state. This way it doesn't get out of sync when Netrw was open manually first. It will still "glitch" when opening Netrw manully after it was opend with this function. But there is nothing one can do about manual commands I guess.

function! ToggleNetrw()
        let i = bufnr("$")
        let wasOpen = 0
        while (i >= 1)
            if (getbufvar(i, "&filetype") == "netrw")
                silent exe "bwipeout " . i
                let wasOpen = 1
            endif
            let i-=1
        endwhile
    if !wasOpen
        silent Lexplore
    endif
endfunction
map <F3> :call ToggleNetrw() <CR>

Additionally you can set some defaults

augroup ProjectDrawer
    autocmd!
    autocmd VimEnter * :Vexplore
augroup END
let g:netrw_banner=0        " disable annoying banner
let g:netrw_winsize = 18    " width in percent
let g:netrw_browse_split=4  " open in prior window
let g:netrw_altv=1          " open splits to the right
let g:netrw_liststyle=3     " tree view
" ret g:netrw_list_hide=netrw_gitignore#Hide()
" let g:netrw_list_hide.=',\(^\|\s\s\)\zs\.\S\+'
" check: |netrw-browse-maps| for more mappings
0

I found a pretty "elegant" solution. You can close a vim buffer by name so all you need is to get the buffer name for Netrw. The only problem is that Netrw doesn't have a buffer name out of the box - so we tell it to have one.

I have it do a vertical split in tree view, and I don't know if the buffer name changes with the configuration. If it doesn't work, try replacing 'NetrwTreeListing' with the name you get after running :ls.

let g:netrw_active = 1
function! Togglenetrw()
    if g:netrw_active
        Vexplore
        let g:netrw_active = 0
    else
        " This is the name of the buffer
        bd NetrwTreeListing 
        let g:netrw_active = 1
    endif
    return 1
endfunction
nnoremap <silent> <C-f> :call Togglenetrw()<CR>

" This is where we tell Netrw to have a buffer name
" (everything is default except 'buflisted')
let g:netrw_bufsettings = 'noma nomod nonu nowrap ro buflisted'

" This is my config
let g:netrw_liststyle = 3
let g:netrw_banner = 0
let g:netrw_browse_split = 4
let g:netrw_winsize = 20
let g:netrw_altv = 1
0

Use this keymap, I'm using Control + N, but you can change it:

vim.keymap.set('n', '<C-n>', function()
    if vim.bo.filetype == 'netrw' then
        vim.cmd 'bwipeout'
    else
        vim.cmd 'Explore'
    end
end, { silent = true })

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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