March 06, 2022
Professionally I started using Vi in 1997 on AIX. Personally I started using Vim around 2008 when I began using Octopress as my static site generator. In November 2011 I started keeping the configuration in a Git repository. In December 2014 I started using Neovim in addition to Vim. Eventually my use of Vim tapered off, and for the past several years I haven’t bothered to keep my Vim configuration up-to-date. It has now been deprecated in my dotfiles repository in favor of Neovim.
The size and complexity of my configuration has ebbed and flowed over time; generally trending
toward more complexity and greater size. When I set out to migrate to a Lua based configuration
init.vim file was just over 1000 lines long, excluding comments and white space.
To paraphrase Gregory Mallory, “Because I can.”
All kidding aside I converted for two reasons. First I don’t know anything about Lua , and this was a chance to learn a little about this language. Second, it would force me to examine my entire configuration, allowing for some house cleaning.
The support for Lua is still evolving, so having your configuration written in Lua is pretty close to bleeding edge. For me, tinkering with my Neovim setup is part of the enjoyment of using Neovim, so I’m willing to endure some pain caused by being closer to the leading edge of development.
Rather than have a single, monolithic file, containing my entire configuration, I wanted to modularize my setup. Fortunately many of the examples I found on GitHub and the r/vimporn and r/neovim Reddits are broken out into directories and files.
Only install the plugins I have a use for. My previous Neovim configuration had gotten crufty, bloated even, with plugins I no longer used, and with odd mappings I no longer remembered the purpose for.
I have several computers of my own, and a couple provided by my employer, I need this configuration to be portable and relatively easy to install in a variety of environments. My preferred OS is MacOS, but I work on Ubuntu and AmazonLinux servers professionally, and I have a Linux laptop for personal experimentation.
Not wanting to corrupt my current Neovim configuration, I chose to start experimenting with a Lua configuration on a Raspberry Pi. I simply didn’t setup my configuration when I installed Neovim on the Pi. Since this meant I was using the configuration I was making to edit the configuration I was making (eating my own dog food), I was painfully aware any time I managed to break something.
When, in the course of exploring other people’s configurations, I discovered some new plugin that I
wanted right away, I’d add it to the
configuration on my other machines, by embedding the Lua code in the Vimscript base.
Eventually I felt I understood enough about how to structure a Lua configuration, that I started in earnest with a new branch of my dotfiles repository. That branch continued to improved and I started using it for everyday use about a month ago.
This past weekend I watched nearly all of the videos in the “Neovim from Scratch” series on YouTube, which resulted in a major refactoring of my setup. The result is cleaner and better organized. It is also more robust.
My Neovim configuration is organized into several directories and about 40 files. While this may seem like a lot, the structure is straight forward and easy to understand.
nvim directory is located in
~/.config. It contains the
init.lua file, a README, the Git
repository and ignore file, and a
lua directory. The
init.lua file has a list of
for each of these categories.
options all contain what you would expect: auto commands, my
color scheme, all my key mappings, and all my options.
helpers has several functions that are useful for creating mappings or setting options.
plugins sets up my plugin manager of choice, and all the plugins I use.
The actual files referenced by these
requires are kept in
~/.config/nvim/lua/usr. Putting them in a folder
lua directory creates a namespace, which is useful in avoiding collisions with files that
might be included in plugins added later. The namespace directory can be called anything, I chose
usr since the contents are for me, and since
user might show up in a plugin. Many people use
their GitHub account name for this namespace directory.
lua directory has two sub-directories:
config is where the configuration files for plugins are kept. For any plugin where there is a
configuration file, that file is kept here. Since setting up and maintaining language servers is
slightly different than most plugins, there is a separate directory under
config for LSP specific
As described above,
usr contains the files that describe my mappings, options, auto commands,
color scheme, and plugins.
The entire configuration can be viewed and cloned from my dotfiles repository. However there are some specific examples I think are important enough to draw attention to.
Including a plugin via the Lua
require statement will result in an error if the plugin can’t be
found or isn’t available. When this happens the Neovim configuration won’t load properly. Using the Lua
pcall function to wrap the require allows the status of the call to be captured and tested, thus
protecting the rest of the configuration process.
Each of my plugin configuration files has this code block at the start of the file.
The actual name of the plugin is substituted in for
plugin-handle is a
local variable that is used by the rest of the file as it points to the instance of the plugin
returned by the require statement. A print statement or
vim.notify statement could be added just
ahead of the
return, if you wanted to provide some visible feedback in the event of a failed
I’m using Packer to manage my plugins. The following code block will automatically install Packer if it isn’t already installed.
In essence this clones the GitHub repository for Packer into the proper location in the file system.
This block of code will trigger a
:PackerSync command any time the
plugins.lua buffer is
written. Very useful for updating the current list of plugins.
All of the plugins are managed inside this code block.
Each plugin is identified by a
It is possible to specify dependencies on other plugins as a part of the
It is also possible to specify the configuration file for the plugin here.
get_config is a small helper function I included in the
Currently I am using the following plugins.
There are others (dependencies and ancillary plugins) I haven’t listed. See the my GitHub repository for the complete set.
I’ve been using my “new and improved” Neovim configuration for several days now. Other than a couple of minor tweaks to plugin settings and mappings, it has worked flawlessly. I’ve been able to install it on all my computers, with very little effort. The only part that isn’t complete is the tracking of words I’ve added to the spelling dictionary.
Neovim continues to be my favorite tool, and tinkering with its configuration is a very satisfying activity.
These are some of the sources I used while converting from a vimscript based configuration to a Lua based configuration.