Neovim is a fork of Vim created in 2014 by Thiago de Arruda, based on the entirely correct observation that Vim’s scripting language was horrible and the somewhat debatable conclusion that replacing it with Lua would fix things.
Vimscript was horrible. On this, there is universal agreement. It was a language that looked like it had been designed by accident, maintained by habit, and understood by no one, including the people who wrote plugins in it. Something had to change.
The something that changed was Lua.
“I thought Vimscript was horrible. And it was. But Lua feels like it is for kids. I went from a language I couldn’t read to a language I don’t want to read. These are different problems, and I’m not sure the second one is better.”
— riclib, on the Neovim experience
The Lua Question
Lua is a fine language. It is small, fast, embeddable, and used in game engines, Redis, and Nginx. It has exactly the qualities you want in an embedded scripting language for a text editor.
It also has the aesthetic quality of a language designed for beginners, which it was. Tables for everything. One-indexed arrays. No classes, just metatables that simulate classes in a way that makes every object-oriented programmer slightly uncomfortable. The syntax reads like pseudocode that someone forgot to translate into a real language.
This is not a criticism of Lua in general. Lua is good at what Lua does. But when you are configuring your editor — when you are writing the code that shapes your primary tool for writing code — you want the configuration language to feel like it respects you. Vimscript did not respect anyone. Lua respects everyone equally, which in practice means it respects no one in particular.
“Lua is the language where everything is a table. Your config is a table. Your plugins are tables. Your keybindings are a table of tables. Your life becomes a table. After a while you look up and realize you’ve become a Lua programmer, which was not the plan. The plan was to edit text.”
— The Caffeinated Squirrel, who has seven hundred lines of init.lua
The Plugin Event Horizon
Neovim’s true innovation was not Lua. Neovim’s true innovation was making plugins so easy to write that everyone wrote one.
Vim had plugins. Vim had many plugins. But writing a Vim plugin required Vimscript, and Vimscript was horrible (see above, see everywhere, see the specific expression on every developer’s face who has ever opened a .vim file), which imposed a natural barrier. Only the dedicated, the stubborn, and the slightly masochistic wrote Vim plugins.
Neovim removed the barrier. Lua was easy. The API was clean. The documentation was good. And so the plugins came. And came. And came.
- telescope.nvim — a fuzzy finder so powerful you can find files, grep content, browse git commits, search LSP symbols, and pick a colour scheme, all from the same floating window
- nvim-treesitter — syntax highlighting that actually understands the syntax, not just regex patterns pretending to
- nvim-lspconfig — language server support that turns the editor into an IDE
- lazy.nvim — a plugin manager for the plugins, because the plugins needed managing
- which-key.nvim — a plugin that shows you what your keybindings do, because you have so many keybindings you can no longer remember them
Each plugin is excellent. Each plugin does its job well. The problem is not any individual plugin. The problem is that Neovim with thirty plugins is no longer a text editor. It is a platform. It is an IDE that you assembled yourself from parts, and the assembly is the hobby, and the hobby is what you do instead of the work the IDE was supposed to help you do.
“The Neovim user has replaced the IDE with something more complex than the IDE, and calls it minimalism. This is not minimalism. This is maximalism with a terminal aesthetic.”
— A Passing AI, observing the Neovim subreddit
The Configuration Folder
A Vim user has a .vimrc. One file. Possibly long, possibly messy, but one file.
A Neovim user has a folder:
~/.config/nvim/
init.lua
lua/
config/
keymaps.lua
options.lua
autocmds.lua
lazy.lua
plugins/
telescope.lua
treesitter.lua
lsp.lua
completion.lua
ui.lua
git.lua
editing.lua
debug.lua
...
This is a project. This has a directory structure. This has more files than some of the projects the developer is using Neovim to edit. The developer has built a bespoke IDE from Lua files, and the Lua files need their own version control, and the version control needs its own branch strategy, and the developer has just committed “refactor: reorganize plugin config structure” to their dotfiles repository and it is 11 PM and they have not written a single line of application code.
The Return to vi
There exists a lifecycle:
- Learn vi
- Discover Vim, marvel at the improvements
- Discover Neovim, marvel at Lua over Vimscript
- Install thirty plugins
- Spend a weekend configuring the plugins
- Realize the plugins need updating
- Realize the plugin APIs have changed
- Realize you are maintaining a software project whose sole user is you
- Open plain vi
- Edit the file
- Close vi
- It took nine seconds
The return to vi is not universal but it is common enough to constitute a pattern. The developer who has gone through the Neovim phase and come out the other side carries the knowledge of what Neovim can do and the wisdom of knowing they don’t need it. This is the difference between ignorance and simplicity. Ignorance is not knowing the features exist. Simplicity is knowing they exist and choosing not to use them.
Measured Characteristics
Year forked: 2014
Based on: Vim (1991), which was based on vi (1976)
Configuration language: Lua (fine for games, debatable for editors)
Previous configuration language: Vimscript (horrible — undisputed)
Average plugin count (casual user): 5-10
Average plugin count (enthusiast): 30-50
Average plugin count (Reddit poster): 70+
Lines of Lua in a typical Neovim config: 300-800
Files in ~/.config/nvim/: 15-40
Time to configure from scratch: 1-3 days
Time to maintain per month: 2-4 hours (plugin updates, API changes)
Developers who have committed to their dotfiles repo at 11 PM: most of them
Developers who returned to plain vi after: enough to notice
The configuration: a software project
The editor: somewhere inside the software project
See Also
- vi — The editor that was already finished. Neovim is what happens when you fork something finished and add Lua.
- Vim — The parent fork. Replaced by Neovim for the same reason Vim replaced vi: the young always think they can do better. Sometimes they can. Sometimes they just do more.
- Emacs — The only editor with a more complex configuration ecosystem. Emacs users, however, enjoy configuring in Lisp. Neovim users tolerate configuring in Lua. This is a meaningful distinction.
- VS Code — The editor that provides what Neovim provides, out of the box, without Lua, at the cost of Electron. The trade-off is: would you rather configure for three days or accept Electron? Both answers are valid. Both groups judge the other.
- Zed — The editor that may make the question moot.
