Using Netrw, vim's builtin file explorer

Did you know that vim has a file explorer? It's a plugin that comes bundled with vim. It's called Netrw... and it's not very popular, at least not if you compare it with something like NERDtree. The reasons for this could include 1) is not very intuitive. 2) has a few annoying limitations. 3) doesn't look cool. Today we are going to learn how to use it, how to get around those limitations and in the process we're going to turn it into something more intuitive and easier to use.

Meeting Netrw

Let's begin our exploration by taking a quick look at it. We can do this if we try to open a directory using vim (something like this: vim .). Assuming you don't have a heavily customized vimrc, Netrw should look like this.

netrw in full screen

The first thing we see is a banner with information about the current directory. This is what is shows us.

Fun fact, you can actually interact with some of the "options" in the banner. So, if you put the cursor on the line that says "sorted" and press Enter you'll change the order of the files. You can order them by name, last update, size or the extension of the file. And the quick help can show you keymaps for some common tasks.

After the banner we have our directories and files. ../ is the parent directory and ./ is the current directory. Lastly, we have our files sorted perfectly.

Usage

Now that we now how Netrw looks like let's cover some of its basic features.

How to call it

Our first stop is the :Explore command. Using it with no arguments will show the directory of the file we are editing. If we don't want that we could give it the path to the directory we want. Depending on your vim config, specifically the hidden option, it will do things differently. If hidden is disabled (this is the default) and there are no unsaved changes in the current file, :Explore will make Netrw occupy the entire window. If we do have unsaved changes in a file it will create a horizontal split and have Netrw in the upper window.

netrw taking half the screen

If we wanted a vertical split we would use the :Explore! command.

If hidden is enabled Netrw will always occupy the whole window.

Now let's talk about some :Explore variants we have available.

See in asciinema.

If we want to move between directories and files these are the keymaps we need to know:

Let's recap. If we want to "go down a directory" we use Enter. To "go up" we use -. To go back, u. And if we want to "jump" quickly to a directory of our choosing we should first add it to the bookmarks (using mb) and then we can use gb to go there.

File operations

We know how to move, now let's see how can we perform some of the most common task on our files.

Perform an action on multiple files

After reading about those keymaps I bet you're wondering how does one copy or move a file. I'll do an example moving some files around.

This will be a three step process:

See in asciinema.

This is what happens in the demo:

"   Copy/Move Tgt: /tmp/vim/test dir/ (local)

And this is it, to copy and delete this is the process. To run external commands and delete files is the same thing, except we don't need a target directory.

Netrw's limitations

This happens on linux and maybe macOS is the same. In our previous example we moved a-file.txt to test dir, and that worked great, but if you try to move back a-file.txt to the parent directory you'll get this error.

**error** (netrw) tried using g:netrw_localmovecmd<mv>; it doesn't work!

This doesn't happen when you try to copy.

As far as I know this happens when the current directory (in the buffer) and the directory we are browsing don't match. To fix this you can set the global variable g:netrw_keepdir to zero.

let g:netrw_keepdir = 0

When you try to do something on marked files, the action only applies to the files that are listed in the current buffer.

Let's say we have this file structure.

vim
├── mini-plugins
│   ├── better-netrw.vim
│   ├── guess-indentation.vim
│   └── project-buffers.vim
├── test dir
│   ├── a-file.txt *
│   ├── another-file.txt *
│   └── text.txt
├── custom-commands.vim
└── init.vim *

The files with an * are the ones we have marked. If we are in the vim directory and we try to move the files to mini plugins only init.vim will be in the target directory. In theory this is a good thing, because we will always have in sight the files we are operating on.

And of course the answer to this is: use an external command. If you paid attention on previous sections you'll know that the mx keymap can help us do just that. Here it is in action.

See in asciinema.

So just in case. The solution: mark the directories with mf, use mx and type the command you need (rm -r in the demo). That's it. But can we make this more convenient? Yes we can, and we are going to that in the next section.

Customization

If you decided to give Netrw a chance you might want to make some tweaks to make it nicer.

Keep the current directory and the browsing directory synced. This helps you avoid the move files error.

let g:netrw_keepdir = 0

Change the size of the Netrw window when it creates a split. I think 30% is fine.

let g:netrw_winsize = 30

Hide the banner (if you want). To show it temporarily you can use I inside Netrw.

let g:netrw_banner = 0

Hide dotfiles on load.

let g:netrw_list_hide = '\(^\|\s\s\)\zs\.\S\+'

Change the copy command. Mostly to enable recursive copy of directories.

let g:netrw_localcopydircmd = 'cp -r'

Highlight marked files in the same way search matches are.

hi! link netrwMarkFile Search

This is the easiest way I could think of to highlight marks. This may cause some confusion if you begin a search in Netrw and have marked files. If you wish to apply other colors search information about the highlight command.

Keymaps

Now that Netrw looks better-ish, let's make it easier to use.

Better call Netrw

We begin by changing the way we call Netrw. We bind :Lexplore to a shortcut so we can toggle it whenever we want.

nnoremap <leader>dd :Lexplore %:p:h<CR>
nnoremap <Leader>da :Lexplore<CR>

Unfortunately we don't have a direct way to assign a keymap in Netrw. We can still have them but it does requires a few steps.

Netrw is a plugin that defines its own filetype, so we are going to use that to our advantage. What we are going to do is place our keymaps inside a function and create an autocommand that calls it everytime vim opens a filetype netrw.

function! NetrwMapping()
endfunction

augroup netrw_mapping
  autocmd!
  autocmd filetype netrw call NetrwMapping()
augroup END

With this in our config all we have to do now is place the keymaps inside NetrwMapping. Like this.

function! NetrwMapping()
  nmap <buffer> H u
  nmap <buffer> h -^
  nmap <buffer> l <CR>

  nmap <buffer> . gh
  nmap <buffer> P <C-w>z

  nmap <buffer> L <CR>:Lexplore<CR>
  nmap <buffer> <Leader>dd :Lexplore<CR>
endfunction

Since we don't have access to the functions Netrw uses internally (at least not all of them), we use nmap to make our keymaps. For example, H will be the same thing as pressing u, and u will trigger the command we want to execute. So this is what we have:

With these (plus the recommended config) Netrw can become a decent file explorer. But wait, we can still do more.

Marks

Let's find a better way to manage the marks on files. I suggest using <Tab>.

nmap <buffer> <TAB> mf
nmap <buffer> <S-TAB> mF
nmap <buffer> <Leader><TAB> mu

File managing

Since there are quite a few commands related to files we are going to use the f key as a prefix to group these together.

nmap <buffer> ff %:w<CR>:buffer #<CR>
nmap <buffer> fe R
nmap <buffer> fc mc
nmap <buffer> fC mtmc
nmap <buffer> fx mm
nmap <buffer> fX mtmm
nmap <buffer> f; mx

We can still do a couple of things, if you don't mind using some of Netrw's internal variables.

Show a list of marked files.

nmap <buffer> fl :echo join(netrw#Expose("netrwmarkfilelist"), "\n")<CR>

Show the target directory, just in case we want to avoid the banner.

nmap <buffer> fq :echo 'Target:' . netrw#Expose("netrwmftgt")<CR>

Now we can use that along side mt.

nmap <buffer> fd mtfq

Again, this is only useful if you really, really want to avoid showing the banner.

Bookmarks

In the same way we grouped the file related actions, we do it for bookmarks.

nmap <buffer> bb mb
nmap <buffer> bd mB
nmap <buffer> bl gb

Remove files recursively

Last thing we will do is "automate" that process we did to remove non empty directories. For this we will need a function.

function! NetrwRemoveRecursive()
  if &filetype ==# 'netrw'
    cnoremap <buffer> <CR> rm -r<CR>
    normal mu
    normal mf
    
    try
      normal mx
    catch
      echo "Canceled"
    endtry

    cunmap <buffer> <CR>
  endif
endfunction

First thing we do in this function is check if we are in a buffer controlled by Netrw. Then we prepare the remove command. We take advantage of the fact that vim makes us drop to command mode and create a keymap (<CR>) that will write the command for us. Next, we use normal mu to clear all the marks, 'cause we don't want to remove anything by accident. We then mark the directory under the cursor with normal mf. Here comes the funny part, normal mx will ask us what command we want to execute, and is at this point when we can abort the process using ctrl + c or press Enter which will trigger the command rm -r. Lastly, we undo the keymap we created in the beginning of the function, because it will be terrible to have it permanently.

And how do we use it?

Creating a keymap inside NetrwMapping, of course.

nmap <buffer> FF :call NetrwRemoveRecursive()<CR>

You can find every option and function in this article here.

Conclusion

Netrw might not be the best file manager in the vim ecosystem but with a little effort we can turn it into an intuitive file explorer. Even if you don't adopt in Netrw in your workflow, knowing how to use it can be handy in some situations. You never know when you're going to be stuck in a remote server without your favorite vim plugins at hand.

Source

:help netrw


Have any question? Feel free to leave a comment in one of these platform where I have shared this:

You can reach out to me on social media:

Thank you for reading. If you find this article useful and want to support my efforts, buy me a coffee ☕

Buy Me A Coffee