404 - Netrw Not Found
My Neovim configuration and dotfiles follow at least four principles I use in my career as a software engineer:
- Keep It Super Simple; I shouldn’t need rocket science to understand my setup.
- Atomic commits; Commits contain distinct changes so they can be reverted individually in case something breaks.
- Continuous improvement; Things can always be improved upon, especially workflows.
- Continuous learning; Every single change in my setup makes me grow a bit as a developer.
Today, I want to focus on the last part as something suddenly broke in my Neovim setup and I had to backtrack to get to the bottom of it. Sharing this knowledge is part of the joy I get working in the field of IT.
Git must be the de facto standard by now. At this time of writing, statistics
show that 77% of all the
repositories are created with git. I’ve yet to work for a client that didn’t use
git. Within Neovim I use quite a variety of plugins to deal with git:
neogit,
vim-fugitive,
gitsigns,
git-conflict and a bunch of
others. When remotely communicating with colleagues it’s sometimes useful to
send a link, highlighting a piece of code on GitHub. This neat feature is
supported by vim-fugitive. You can create a visual selection, execute
:GBrowse
, and your default browser will be opened automatically. Redirecting
you straight to GitHub and showing you the file and it’s selection. It cannot
get much quicker or simpler than this! However, to my surprise this no longer
worked today. I was greeted with the error Netrw not found. Define your own :Browse to use :GBrowse
.
As I’m not writing unit tests for my setup, sometimes things break over time
without me realising. But how did this suddenly stop working? Doesn’t netrw
come out-of-the-box with Neovim? Let’s try running :Explore
, as this should
open the default Neovim’s file explorer. Instead of showing the file explorer
I’m greeted with the error E492: Not an editor command: Explore
. It indeed
seems I can no longer use :Explore
or its alias :Ex
. Could it be there’s a
plugin intervening with netrw
? To make a long story short: Yes! It took a
simple binary search to find the
trouble maker. In my case it was
oil.nvim. When installed it becomes the
default file explorer, but that also intervenes with plugins relying on netrw
.
The fix for me was dead simple, I no longer allow it to become the default file
explorer as I only use it occasionally anyway:
{
"stevearc/oil.nvim",
opts = {
default_file_explorer = false
},
-- Optional dependencies
dependencies = { "nvim-tree/nvim-web-devicons" },
},
If you do want to keep oil.nvim as your default file explorer, you can easily
create a user command for :Browse
as
follows:
vim.api.nvim_create_user_command("Browse", function(opts)
vim.fn.system { "open", opts.fargs[1] }
end, { nargs = 1 })
As I’m using lazy.nvim, I decided to
create the user command in the init
function of the vim-fugitive block:
{
"tpope/vim-fugitive",
lazy = true,
keys = {
{ "<leader>gs", ":Git<cr>", desc = "[g]it [s]tatus" },
{ "<leader>gd", ":Git diff<cr>", desc = "[g]it [d]iff" },
{ "<leader>gb", ":Git blame<cr>", desc = "[g]it [b]lame" },
{ "<leader>gB", ":GBrowse<cr>", desc = "[g]it [B]rowse", mode = { "n", "o", "x" } },
{ "<leader>gl", ":GcLog<cr>", desc = "[g]it [l]og" },
},
init = function()
-- The Browse user command is needed for :GBrowse as oil.nvim is by
-- default set as the default file explorer. Without it you'll run into
-- the error: Netrw not found. Define your own :Browse to use :GBrowse
vim.api.nvim_create_user_command("Browse", function(opts)
vim.fn.system { "open", opts.fargs[1] }
end, { nargs = 1 })
end,
},
There are three advantages I’d like to highlight:
- The creation of the user command is close, or actually in the code that sets up vim-fugitive. There’s no way to accidentally remove it and the comment makes it clear why this user command needs to be created.
- vim-fugitive is fully lazy loaded (see screenshot below). However, the creation of
the
:Browse
command is accessible even though the plugin itself has not yet been loaded. How? Because theinit
function is called for all plugins, even plugins that haven’t been loaded by lazy.nvim yet.
Conclusion #
It can be quite fun to investigate a problem. Especially once you understand what the problem was all about. These are the things I learned today:
- oil.nvim disables
netrw
by default. - The
init
function of a lazy.nvim package is always invoked. Even if the plugin itself has not been loaded yet. - The
config
function of a lazy.nvim package is only called if the plugin is being loaded.
Posted on Jul 2, 2024 (updated on Jul 5, 2024)