I started using Neovim (nvim for short) about three years ago, in Sep. 2018. At that time, nvim had just released v0.3.1. Over the years, I have been a staunch nvim user, constantly learning new knowledge, and sharing tips, tricks and interesting plugins in my blog posts.
How I started with Neovim#
Back when I was still in university, I had dabbled in Vim a little bit. I remember that in those days, most posts on the Internet recommended a plugin manager called vundle. As for auto-completion, ycm was the most popular plugin at the time. However, it is difficult to install and configure, and I never succeeded in installing it. I copied some basic config from various posts and did not really know what they mean. Vim script seemed weird and hard to understand. So my first trial of Vim didn’t really take off. I learned the basic motions and know how to save and quit a file, but no fancy and advanced features such as text objects. I was still using PyCharm and Sublime Text for serious project development.
After I graduated and started working, since we need to run the code on a remote server with no GUI support, I was forced to make choices:
- Develop on the server without GUI, which implies using a TUI editor. Vim is apparently the choice.
- Develop on my local PC and sync the code to remote via Git or other tools.
I find choice one more elegant, since I do not need to set up dev environment on my local machine, and I can run my code directly on the server (running the code requires GPU and there is no GPU on my local machine). At the time, I came to know the Neovim project. I choose Nvim because it is easily installable. It provides binary releases, so I do not need to compile from source myself. I also like its development model more than Vim’s. Nvim uses GitHub and other modern dev tools for better collaboration, while Vim is still using google groups1 for dev communications.
Finally, I was on the Neovim boat and started my journey.
My learning story#
The initial learning curve of nvim was indeed quite steep. I needed to constantly check the documentation or search on the Internet, then tweak the config to do what I want. Sometimes, a small setting may waste a lot of time, since I needed to understand what it does and how it works. I also spent a lot time tweaking the settings of various plugins to fit my need.
My way of learning Nvim is to add the features and plugins I need incrementally. At the start, I only added the settings I wanted most, like autocompletion, linting, file explorer etc. I searched intensively on the Internet for the state of the art plugins for a particular need. I will try several similar plugins, and only keep the one that best suits me. The most important point to remember is that never rush to master Vim in a few days. Vim has so many hidden features and settings, and it is impossible to master it quickly.
After about three or four months of rapid learning process, I was at ease using Nvim for my development work. I published a post on how to configure Nvim for Python development.
After building a usable config, when I want to do something, I always check if there is a better way to do it. I searched on the Internet and learned new tricks, and perfected those skills through practicing. Notice that not all tricks on the Internet are good and written by advanced Vim users. We need to constantly learn new Vim knowledge and update our existing settings.
Another great learning resource is the configurations of other people. We can find numerous dotfile repos on GitHub and learn from them little tips and tricks that we do not know yet. I have always advised against copying the config of others without knowing what you are doing. At the very least, we should read the documentation and understand what a particular setting does. If we copy other’s config blindly, it may cause endless pains afterwards when we spend hours debugging misbehaving Nvim.
As I became more proficient in Vim, I started learning more advanced features such as text objects.
I also created some custom text objects for my own use.
I have always wanted to write my own plugin and contribute to the Vim community.
After learning enough about Vim script, I wrote a plugin called better-escape.vim in Dec. 2020.
The goal is to help users escape insert mode quicker without lagging caused by timeoutlen
option.
This year (2021), I have been learning Lua and migrating some of my config to pure Lua.
Evolution of my configuration#
I didn’t create a repo to store my nvim config at first. I just stored it in a gist. It wasn’t until April 2019 that I created a repo for my nvim config.
Initially, all my config is stored in a single file init.vim
, which in its peak exceeded 2000 lines.
Later, as I learned more about how Vim works (autoload, ftplugin, after folder etc.)2,
I started splitting my config into different directories and files for better maintainability.
My config has been all vim script for a long time.
Since nvim is adding more lua support and using lua to implement its builtin LSP support,
I have also been updating my config and adding a little lua.
I have slowly moved my completion system to the builtin LSP3.
After that, part of my configuration is moved to lua/
directory。
With the release of Nvim v0.5, there has been a burst of lua-based plugins. I have also replaced some of the viml plugins to their lua-based counterparts4 this year.
What remains, what has changed, and some new plugins#
I am not a Vim purist5, so plugins have always been an essential part in using Vim/Nvim. Since there is no central plugin marketplace like Emacs MELPA, finding good plugins is not always easy.
That a plugin is popular and has more stars does not mean that it is better or it suits you6. Over the course of three years, I have always tried to find better alternatives for my existing plugins. Admittedly, trying a new plugin and adapting to it is a time-consuming process, especially when a plugin does not work out of the box and requires some degree of customization. However, the efficiency boost brought by a well-designed plugin can be huge.
What remains#
A few plugins still remain:
- git gutter plugin: I still use vim-signify, but gitsigns.nvim seems more powerful and promising.
- snippet plugin: I am still using ultisnips due to its powerful interpolation features. There are also many lua-based snippet engines worth trying.
- git plugins: still use vim-fugitive. I have also tried gina, but find it too complicated. There are also lua-based git plugins such as neogit, which aims to replicate the functionality of magit.
- markdown plugins: vim-markdown for editing and markdown-preview.nvim for preview.
What has changed#
I have also updated a large part of my plugins during the process:
- plugin manager: from vim-plug to packer.nvim. I switched to packer.nvim middle this year, because it allows all sort of crazy lazy loading and brings package management to a whole new level.
- autocompletion plugins: from deoplete + deoplete-jedi to vim-lsp + deoplete to nvim-lsp + nvim-compe to nvim-lsp + nvim-cmp. Nvim-cmp is light-weight, well-designed and awesome.
- pair management: from vim-surround to vim-sandwich. Vim-sandwich is well-designed and has better UX than vim-surround, though it is less popular than vim-surround.
- comment plugin: from nerdcommenter to commentary.vim. I like commentary’s feature of commenting code via motion.
- file explorer: from nerdtree to none. I use fuzzy file finder instead. If I need to explore a project, I check it in another tmux pane.
- statusline plugin: from vim-airline to lualine. Vim-airline is great, but it is also bloated with too many 3rd-party plugin integrations. Lualine is simple, faster, and easy to customize.
- change of linting: from Neomake to ALE to nvim-lsp
- auto-pair plugin: from auto-pairs to delimitMate. DelimitMate has saner behaviour for pair insertion than auto-pairs.
- in-buffer jump: from vim-sneak to hop.nvim. Vim-sneak has been a great plugin. I changed to hop.nvim because it may support jumping via pinyin (PR here), which is convenient for Chinese users.
- search item indexing: from vim-anzu to nvim-hlslens. Nvim-hlslens is a lua plugin that provides better UX for search indexing using virtual text feature of Nvim.
- clear search highlight automatically: from vim-cool to nvim-hlslens
- format plugin: from Neoformat to none (using LSP for formatting).
- multiple cursors: from vim-multiple-cursors to none. I now use
gn
mostly. vim-visual-multi may be a good replacement (also recommended by author of vim-multiple-cursors). - yank highlight: from vim-highlightedyank to nvim builtin, see this post for the detail.
- fuzzy finder: from fzf.vim to LeaderF. LeaderF works fast and reliably across different systems.
- startup screen: from vim-startify to alpha-nvim.
- tabline plugin: from vim-airline to bufferline.nvim.
- indent line plugin: from indentLine to indent-blankline.nvim. Indent-blankline uses the virtual text feature to make indent line flawless even on blank lines.
- auto save plugin: from vim-auto-save to AutoSave.nvim.
- showing tags: from tagbar to vista. Vista is better at displaying symbols.
New plugins#
I have also added some new and interesting plugins:
- nvim-treesitter: more accurate syntax highlighting, text object and more.
- nvim-notify: show notifications via floating windows.
- unicode.vim: check, search and insert unicode characters.
- asyncrun.vim: run code asynchronously in the background and show results in quick fix window.
- firenvim: run neovim inside text area in the browser and use it for quicker editing.
- vim-oscyank: yank text from remote server directly to the clipboard of your local machine.
- wilder.nvim: fancy autocompletion in command line for Nvim.
- whichkey.nvim: show key mappings and register contents etc. automatically for you.
My thoughts on several topics#
Vim or Neovim?#
This is a question that gets asked almost monthly by mainly beginners (e.g., see this post). The short and unbiased answer is that it does not really matter for novice.
Since Nvim is a fork of Vim and merges patches from Vim regularly, the basic features are almost the same. There are some subtle differences (see vim-differences), but that is largely irrelevant for beginners. If you are a beginner, you can pick either one and learn the basics7. Later when you become a proficient user, you can choose a side, or make your config compatible with both Vim and Nvim.
It is a sad truth that Vim and Nvim are going on quite different paths: Neovim is investing more on Lua, and its Lua plugin system is thriving, while Vim is trying hard implement the vim9 script, a completely new and incompatible version of viml. There might be more incompatible changes happening on both sides. It might be getting harder to port Vim patches to Neovim. Personally, I doubt whether the amount of effort put into building vim9 script will ever pay off. Considering that a lot of vim plugins are still trying to support Vim 7.xxx, I doubt how many of these plugin authors are willing to rewrite their plugins in vim9 script, especially when their plugins have very large code bases.
Personally, I will stick to Neovim and migrate to all-lua config some day.
init.vim vs init.lua?#
Since nvim has added support for init.lua, many users have moved from viml-based to lua-based config completely. Currently, my config is still a mix of vim script and lua script due to several reasons:
- Lua support in Nvim is still not complete and mature enough. For example, sometimes we still need to use
vim.cmd()
to run vim command. We still need to learn how to use Vim script. - Some viml command is more concise to write, and lua tends to be more verbose, e.g., when defining mappings or setting an option.
- I am still using quite a few vim script plugins, and it makes sense to configure these plugins in vim script.
Should I use a pre-made config distribution?#
There are several Vim/Nvim distributions, which aim at providing IDE-like and out-of-the-box experience. Some of the most popular distributions are LunarVim and NvChad, AstroNvim.
People ask frequently on r/neovim and r/vim whether they should use a vim/Nvim distribution. If you are serious about Vim and want to learn how to use it properly and eventually master it, I think it is better to avoid those distributions and build your own config from scratch:
- Those distributions may add their own configuration layer and complicate things. Users end up learning too much distribution-specific config without learning real Vim stuff.
- Even if you use those distributions, when you want to customize certain things, you still need to learn how Vim/Nvim works under the hood. Otherwise, you can only count on other developers to implement the feature for you.
- When you meet issues with those distributions, you may have a hard time debugging it, since they all include various configurations.
However, this does not mean that you can not learn from these distributions, e.g., how they configure, how they organize their directory structure. You can even steal some configs for your own use.
Concluding remarks#
Looking back, I think I have made the right choice to learn Vim/Nvim. It has been a rewarding journey for me. I am so used to vim’s style editing that Vim becomes second nature.
I am thankful to all the contributors of Vim/Nvim for building and maintaining such a great editor. I am grateful for the efforts that plugin authors put into in building those great plugins.
I am not saying that Vim’s development model is worse, I just like Nvim’s development model more. ↩︎
An excellent article on how to split your config is from .vimrc to .vim. ↩︎
I used deoplete with deoplete-jedi for over two years. Then I moved to vim-lsp + deoplete for several month, before moving to nvim-lsp. ↩︎
A good resource for finding lua plugins is awesome neovim. Neovimcraft also collects some lua-based neovim plugins and config distributions. ↩︎
Vim purist refers to people who use little or no external plugins. ↩︎
One such example is vim-surround vs vim-sandwich. Vim-sandwich has much lesser stars than vim-surround, but I find it more user-friendly and switched to it in 2020. ↩︎
If you decide to go all Lua and use
init.lua
, then you should definitely use Neovim. ↩︎