Configuring Neovim with Lua: Part 1
Intro
If you’re a Vim/Neovim user, you might be familiar with a Vim script which you would normally find at $HOME/.vimrc
. This file can get pretty large and messy so in this part 1 of “Configuring Neovim with Lua”, I am going to walkthrough configuring Vim options with Lua.
File Placement
In Neovim, the initialization file or init
file resides in the following path:
$HOME/.config/nvim/init.lua
The way that I configure Neovim doesn’t require that we alter the init.lua
file because our Vim options, keymaps, and plugins will reside in their own individual Lua files. Neovim looks for additional Lua configuration files in the following directory:
$HOME/.config/nvim/lua/
To keep things organized, I like to keep my Lua configuration files in a folder called profile:
$HOME/.config/nvim/lua/profile/
In the profile directory, I have the following three files:
options.lua
: contains my Vim optionskeymaps.lua
: contains my Vim keymapsplugins.lua
: contains my Vim plugins which are managed by packer
In this blog, I’ll talk about setting Vim options in the options.lua
file. In part 2, I’ll talk about creating keymappings and in part 3, I’ll provide a walkthrough for configuring pluggins with packer. Let’s go for it.
Setting up init.lua
As previously mentioned, we won’t be touching the init.lua
file much, but it will contain references to our Lua files that actually contain configuration options. To do this, we will use Lua’s require
keyword to import our Lua files. So the init.lua
file should look like this:
init.lua
require 'profile.plugins'
require 'profile.options'
require 'profile.keymaps'
So go ahead and create the following three files:
$HOME/.config/nvim/lua/profile/options.lua
$HOME/.config/nvim/lua/profile/keymaps.lua
$HOME/.config/nvim/lua/profile/plugins.lua
With our init.lua
file now properly pointing to our additional Lua config files, we can go ahead and start adding configuration options to the options.lua
file.
Configuring Vim Options
Popular Vim options, like the number
option which tells Neovim to show line numbers, can be set through the vim.opt
table. For example, setting the number
option would require the following line of code to be placed in the options.lua
file:
vim.opt.number = true
Now this is slightly more typing than I’d prefer but of couse because Lua is a programming language, we can use it like one. So to not have to repeatedly type vim.opt.*
for every single option, we can use a little Lua-fu to make our lives easier:
local options = {
number = true,
relativenumber = true,
ignorecase = true,
encoding = "UTF-8",
wrap = false,
}
for k, v in pairs(options) do
vim.opt[k] = v
end
Using a Lua table called options
, we can set options by creating key-value pairs - the key is the option name, and the value can be a string, boolean, integer, or even a table, for more complex values. Finally, we have a basic for-loop that iterates over the options
table and sets the option via the vim.opt
table. If you open up Neovim, you should see the enabled options:
Here is my personal options.lua
file for reference:
local options = {
backup = false,
writebackup = false,
swapfile = false,
relativenumber = true,
number = true,
clipboard = "unnamedplus",
ignorecase = true,
undofile = true,
undodir = string.format("%s/.undodir", vim.env.HOME),
encoding = "UTF-8",
pastetoggle = "<F2>",
shiftwidth = 2,
expandtab = true,
hlsearch = true,
wrap = false,
cursorline = true,
pumheight = 10,
conceallevel = 0,
tabstop = 2,
cmdheight = 2,
splitright = true,
splitbelow = true,
termguicolors = true,
background = "dark",
list = true,
listchars = {
eol = "$",
trail = "+",
tab = "> "
},
shell = "/bin/bash",
}
for k,v in pairs(options) do
vim.opt[k] = v
end
-- FZF
vim.env.FZF_DEFAULT_COMMAND = "rg --files --hidden --follow --no-ignore-vcs --fixed-strings"
vim.env.FZF_DEFAULT_OPTS = [[--ansi --preview-window 'right:60%' --layout reverse --margin=1,4 --bind ctrl-j:down,ctrl-k:up,ctrl-h:preview-down,ctrl-l:preview-up]]
-- Emmet
vim.g.user_emmet_leader_key = ","
-- Gitgutter
vim.g.gitgutter_git_executable = "/usr/bin/git"
-- VimGo
vim.g.go_def_mode='gopls'
vim.g.go_info_mode='gopls'
vim.g.go_highlight_structs = 1
vim.g.go_highlight_methods = 1
vim.g.go_highlight_functions = 1
vim.g.go_highlight_function_calls = 1
vim.g.go_highlight_function_parameters = 1
vim.g.go_highlight_operators = 1
vim.g.go_highlight_types = 1
vim.g.go_highlight_fields = 1
vim.g.go_highlight_build_constraints = 1
vim.g.go_highlight_generate_tags = 1
vim.g.go_highlight_format_strings = 1
vim.g.go_highlight_variable_declarations = 1
vim.g.go_highlight_variable_assignments = 1
vim.g.go_auto_type_info = 1
vim.g.go_fmt_autosave = 1
vim.g.go_mod_fmt_autosave = 1
vim.g.go_gopls_enabled = 1
-- Rust.vim
vim.g.rustfmt_autosave = 1
--[[
the following code alternates between the tokyonight
and papercolor colorschemes using even or odd numbers
]]
math.randomseed(os.time()) --set seed to current time
local rand = math.random(1000)
if (rand % 2 == 0) then
--Tokyonight
vim.g.tokyonight_style = "night"
vim.cmd 'colorscheme tokyonight'
else
--PaperColor
vim.cmd 'colorscheme PaperColor'
end
As you can see, to set global Vimscript variables, you use the vim.g
API; to set environment variables, you’d use the vim.env
API; And lastly, if you’d like to directly execute Vimscript from within a Lua file, you’d have to the use the vim.cmd
API.
EOF
You should now be able to continue to expand your options.lua
file with your favorite options using the information you learned from this tutorial so have fun!
If you enjoyed reading this blog and learned something, keep an eye out for more of my posts and maybe consider following me on GitHub, where I work on cybersecurity projects. And if you are feeling really generous, consider buying me a coffee!