Turn NeoVim into Lua IDE
- Turn NeoVim into Lua IDE
- Step 1. Installation
- Step 2. Detect Configuration Paths
- Step 3. Creating init.lua file
- Step 4. Installing Lazy plugin manager
- Step 5: Installing StyLua
- Step 6: Installing Language Server Protocol (LSP)
- Step 7. Useful options
- Step 8. Run current buffer with Lua code in single key
- Step 9 (Optional): Very Useful Plugins
- Step 10 (Optional). jk ninja trick
- More Tips to Become a Vim/NeoVim Master
NeoVim is a modern, Vim-based text editor with limitless customization possibilities. It is relatively lightweight and compatible with Vim, which has been beloved by IT professionals for decades. I would show how easy it is to set it up as IDE for Lua language.
Step 1. Installation¶
First of all, let’s install NeoVim. You can find a detailed guide. for your operating system.
Prerequisites for plugins¶
- Required Rust language compiler;
- Or instead of Rust, you can use
npm
shipped with Node.js®.
I would recommend using Node because you also might need it later for other plugins. But this is completely up to you.
Step 2. Detect Configuration Paths¶
The next step is to determine where NeoVim configuration files are stored. On Unix-like systems, they are usually stored in the $XDG_CONFIG_HOME
environment variable.
To find your current configuration directory, run the following command inside Vim: :echo stdpath('config')
. This will print the current configuration directory.
Usually, these are:
OS | Config Directory | NeoVim Config Directory |
---|---|---|
Unix | ~/.config | ~/.config/nvim |
Windows | ~/AppData/Local | ~/AppData/Local/nvim |
Read more about standard paths in the NeoVim documentation.
Step 3. Creating init.lua
file¶
Let’s start with an empty init.lua
file in the config directory. Let’s confisued we are on Linux and full path will be ~/.config/nvim/init.lua
.
--init.lua
Step 4. Installing Lazy plugin manager¶
NeoVim has an amazing plugin manager called Lazy, which is easy to install and use. You can follow the official installation guide, but this article covers the same approach.
After installation, paste the following code into an init.vim
file:
--init.lua
-- Lazy setup
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not (vim.uv or vim.loop).fs_stat(lazypath) then
local lazyrepo = "https://github.com/folke/lazy.nvim.git"
local out = vim.fn.system({
"git",
"clone",
"--filter=blob:none",
"--branch=stable",
lazyrepo,
lazypath,
})
if vim.v.shell_error ~= 0 then
vim.api.nvim_echo({
{ "Failed to clone lazy.nvim:\n", "ErrorMsg" },
{ out, "WarningMsg" },
{ "\nPress any key to exit..." },
}, true, {})
vim.fn.getchar()
os.exit(1)
end
end
vim.opt.rtp:prepend(lazypath)
-- Make sure to setup `mapleader` and `maplocalleader` before
-- loading lazy.nvim so that mappings are correct.
-- This is also a good place to setup other settings (vim.opt)
vim.g.mapleader = " "
vim.g.maplocalleader = "\\"
-- Setup lazy.nvim
local plugins = require("config.plugins")
require("lazy").setup(plugins, {
spec = {
-- import your plugins
{ import = "plugins" },
},
-- Configure any other settings here. See the documentation for more details.
-- colorscheme that will be used when installing plugins.
install = { colorscheme = { "habamax" } },
-- automatically check for plugin updates
checker = { enabled = true },
})
This is the initial setup for Lazy, and after you run NeoVim, the Lazy Plugin Manager will install automatically.
Next, let’s create a plugins
table that we will need in init.lua
. Create an empty table—we will need it later.
--init.lua
-- Lazy setup (code truncated) --
-- Plugins list
local plugins = {}
-- Setup lazy.nvim (code truncated) --
If you try to run nvim now, you will most likely get an error like:
Error detected while processing ~/.config/nvim/init.lua:
No specs found for module "plugins"
Press ENTER or type command to continue
Do not panic! This is normal because we have not yet installed any plugins. To check if Lazy is installed correctly, type :Lazy
and hit Enter.
If you see a screen similar to this:
Tip
To quit the Lazy screen, press the q key.
As you can see, the menu is quite straightforward:
- Install (I): Shift+i
- Update (U): Shift+u
- Help (?): ?
- And so on; ask help with command
:Lazy help
.
Alternatively, you can run the same commands inside the NeoVim command line: :Lazy install
, :Lazy update
, :Lazy help
, etc.
Tip
It is recommended to run :checkhealth lazy
after installation. Try to tix errors and warnings if they are reported.
Warning
After running Lazy plugin manager commands, a lazy-lock.json
file will be automatically created in the configuration directory. Do not modify this file, as it is updated and generated automatically, storing required metadata about plugins.
Step 5: Installing StyLua¶
StyLua is an opinionated code formatter for Lua.
To install it on your platform, there are three ways (return to step 1:
- Use Rust:
cargo install stylua
- Use NPM with Node.js®:
npm i -g @johnnymorganz/stylua-bin
- Compile it yourself from the source code
Choose whichever method you prefer.
StyLua allows you to set up custom rules to fit your needs. Read the official documentation on configuration for more details.
If you want to configure StyLua per project, you can create a .stylua.toml
file in the project root or check out my article dedicated to Stylua.
Another useful feature is auto-formatting files upon saving. For this purpose, we can create an autocommand in NeoVim. Edit your init.lua
as follows:
-- init.lua
-- Lazy setup (code truncated)
-- Plugins list (code truncated)
-- Setup lazy.nvim (code truncated)
-- Autocommands
vim.api.nvim_create_autocmd({ "BufWritePost" }, {
pattern = { "*.lua" },
callback = function()
local stylua_cmd = "silent! !stylua %"
vim.cmd([[silent! %s/\s\+$//e]])
vim.cmd(stylua_cmd)
end,
})
Step 6: Installing Language Server Protocol (LSP)¶
The Lua Language Server enhances Lua development by offering a range of features that streamline and accelerate the coding process. It includes annotations and typing systems, autocompletion, linting, and many other useful features.
There are two ways to install LSP: compile it yourself or download a prebuilt binary for your platform. Compilation is out of scope for this article. If you are interested in the compilation process, check out the official LSP documentation.
Here, we will use precompiled binaries. Download the latest release for your platform, and unzip it into a directory such as ~/.config/lua-lsp
.
If you used a path other than
~/.config/lua-lsp
, change it accordingly.
Next we need to tell OS where to install LSP; for this we need to add the LSP binary to the $PATH
environment variable. For Unix-like systems, add it to your .bashrc
.
echo 'export PATH="$HOME/.config/lua-lsp/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
exec $SHELL
Tip
Maybe your shell is other than bash. For example, in macOS, by default, it is zsh, so settings are in .zshrc
. Shell configuration depends on your platform and shell you use; possible files in your home directory are: .bashrc
, .bash_profile
, .zshrc
, .zsh_profile
etc.
Type the command in terminal printenv SHELL
to get your current shell.
Next, add neovim/nvim-lspconfig plugin to our plugins
table. Which we have already created in Step 4.
--init.lua
-- Lazy setup (code truncated)
-- Plugins list
local plugins = {
"neovim/nvim-lspconfig"
}
-- Setup lazy.nvim (code truncated)
-- Autocommands (code truncated)
Now we need to initialize the LSP setup; this also should be done in init.lua a file. Just append these lines:
--init.lua
-- Lazy setup (code truncated)
-- Plugins list (code truncated)
-- Setup lazy.nvim (code truncated)
-- Autocommands (code truncated)
-- Setup LSP
require("lspconfig").lua_ls.setup({
-- LSP can have lots of configurations.
-- Check out possibilities at official docs https://luals.github.io/wiki/configuration/
})
You can use the embedded code formatter provided by LSP, but I prefer to use StyLua. To use it or not is up to you.
Watch the demo of the LSP in action; notice that after table.
Ctrl+x+o.
Step 7. Useful options¶
NeoVim and Vim have a huge amount of preferences. Type :h options
in NeoVim command line to read documentation about options.
I would recommend using this setup, but you can change what you want. Lazy recommends setting up options before you initialize. Lazy
Make sure to setup
mapleader
andmaplocalleader
before loading lazy.nvim so that mappings are correct. This is also a good place to setup other settings (vim.opt)
--init.lua
-- Lazy setup (code truncated)
-- Plugins list (code truncated)
-- Options
vim.g.mapleader = ","
vim.opt.exrc = false
vim.opt.secure = true
vim.opt.number = true
vim.opt.mouse = ""
vim.opt.spelllang = "en_us"
vim.opt.foldmethod = "indent"
vim.opt.foldlevel = 99
vim.opt.clipboard = "unnamed"
vim.opt.tabstop = 4
vim.opt.shiftwidth = 4
vim.opt.softtabstop = 4
vim.opt.smartindent = true
vim.opt.ignorecase = true
vim.opt.infercase = true
vim.opt.smartcase = true
vim.opt.rulerformat = "%l,%v"
vim.opt.colorcolumn = "75,79"
vim.opt.undofile = true
vim.opt.undodir = vim.fn.expand("$HOME") .. "/.undodir"
vim.opt.lazyredraw = false
vim.opt.textwidth = 78
vim.opt.endoffile = true
-- Setup lazy.nvim (code truncated)
-- Setup LSP (code truncated)
That is all. This is a bare minimum to make your NeoVim as a Lua IDE. Next steps are optional.
Step 8. Run current buffer with Lua code in single key¶
Usually I use F5 key to run the file, but you can map it to any other key or sequence. To achieve this, add a key map in the autocommand section.
--init.lua
-- Lazy setup (code truncated)
-- Plugins list (code truncated)
-- Setup lazy.nvim (code truncated)
-- Autocommands (code truncated)
vim.api.nvim_create_autocmd({ "FileType" }, {
pattern = { "lua" },
callback = function()
vim.keymap.set("n", "<f5>", "<cmd>w<cr><cmd>!lua %<cr>")
end,
})
-- Setup LSP (code truncated)
In the same manner, you can use F6 for the debugger or something else.
Step 9 (Optional): Very Useful Plugins¶
Some plugins might make your life even happier with NeoVim.
- tpope/vim-commentary: A very useful plugin to comment/uncomment with the gcc keystroke.
- tpope/vim-repeat: If you’ve ever tried using the
.
command after a plugin mapping, you were likely disappointed to discover it only repeated the last native command inside that mapping, rather than the mapping as a whole. - tpope/vim-surround: This plugin is all about “surroundings”: parentheses,
brackets, quotes, XML/HTML tags, and more. It provides mappings to easily delete, change, and add such surroundings
in pairs. - vim-airline/vim-airline: A cool custom status line.
- vim-airline/vim-airline-themes: A large set of themes for vim-airline.
- ctrlpvim/ctrlp.vim: Allows opening files with Ctrl+p keystrokes. I also recommend setting wildcards to ignore files, like:
vim.g.wildignore = "*/node_modules/*,*.so,*.swp,*.zip,*.git,*.o,*.a,"
- jiangmiao/auto-pairs: Automatically completes closing pairs:
"
,'
,(
,[
,{
, etc. - neoclide/coc.nvim: Amazing autocompletion on the fly. You do not need to press Ctrl+x+o to get context suggestions. It might be tricky to install, but it is really worth it.
Tip: Try this if you are on Linux:cd ~/.local/share/nvim/lazy/coc.nvim/ && npm ci
or:CocInstall
. Run:CocConfig
to createcoc-settings.json
and configure JSON as you wish, for the reference check mycoc-settings.json
as example. - flazz/vim-colorschemes: A large collection of color schemes for NeoVim. Use the
:color <tab>
command to find your favorite color scheme. - nelstrom/vim-visual-star-search: Allows searching words with * in visual mode.
List of full plugins in the table:
--init.lua
-- Lazy setup (code truncated)
-- Plugins list
local plugins = {
"neovim/nvim-lspconfig",
"tpope/vim-commentary",
"tpope/vim-surround",
"tpope/vim-repeat",
"vim-airline/vim-airline",
"vim-airline/vim-airline-themes",
"ctrlpvim/ctrlp.vim",
"jiangmiao/auto-pairs",
"nelstrom/vim-visual-star-search",
"dhruvasagar/vim-table-mode",
"flazz/vim-colorschemes",
"neoclide/coc.nvim",
}
-- Setup lazy.nvim (code truncated)
-- Autocommands (code truncated)
-- Setup LSP (code truncated)
Step 10 (Optional). jk ninja trick¶
In NeoVim and Vim, by default, the key Esc is the default key to return to normal mode. The problem is that Esc key is too far from your main fingers. There is a ninja trick to map jk act as Esc. These small improvements greatly speed up coding.
--init.lua
-- Lazy setup (code truncated)
-- Custom key mappings
vim.keymap.set("i", "jk", "<Esc>")
-- Plugins list (code truncated)
-- Setup lazy.nvim (code truncated)
-- Autocommands (code truncated)
-- Setup LSP (code truncated)
Download complete init.lua
file.
More Tips to Become a Vim/NeoVim Master¶
- From time to time, review your configuration and adjust it to fit your needs.
- Train your fingers daily to build muscle memory for keystrokes and learn new shortcuts.
- In the beginning, you might be slow with Vim/NeoVim. Do not give up; it takes time to understand the wisdom of the masters.
- Read the book Practical Vim.
- Use
:h <topic>
the command to learn and get help; - There are limitless possibilities to customize NeoVim to match your needs and habits.
- If you’re struggling, you can check my
init.lua
as a starting point for your setup or inspiration.
That’s all! Happy Vim-ing!
Feedback
For feedback, please check the contacts section. Before writing, please specify where you came from and who you are. Sometimes spammers go insane. Thank you in advance for your understanding.