Configuring Neovim With Lua: What You Should Know NeoVim is such an amazing and powerful tool. It’s insanely fast, flexible, and clean. I honestly can’t believe I used to use vimscript to set it up, but anyways, in today’s article, I’m going to show you how to start making your neovim config! But before we continue though, I’d like to give a big shout-out to Chris@machine’s NeoVim from Scratch series, and ThePrimeagen, since a lot of my config is based on theirs.

Configuring Neovim With Lua: What You Should Know

Table Of Contents

  1. But Why
  2. Starting
  3. Configuring Settings
  4. Using and Setting Remaps
  5. Plugins?
  6. Conclusion

But why?

Before we get started, you must understand why pairing NeoVim with Lua will make such a big difference. Here are some key points of why using Lua is more beneficial than vimscript:

  • Organisation - NeoVim allows you to use a more clean-looking file Structure.
  • Faster - Lua is a lot faster than vimscript
  • Plugins - Specifically talking about Packer here, it makes making amazing plugins easier.
  • It’s Lua - Let me justify a bit, vimscript is a scripting language, specifically made to configure Vim. On the other hand, Lua is an actual programing language, which allows the editor to do so many more amazing things!

And don’t worry, vimscript can still be used if it is needed, which I’m going talk a little about here.


First, I’d recommend you make sure to have the latest version of NeoVim installed. You can get the latets on their releases page. Let’s start by having a quick look at the tree of my personal config tree.

├── after
│   └── plugin
│       ├── autopairs.lua
│       ├── cmp.lua
│       ├── dashboard.lua
│       ├── lualine.lua
│       ├── nvim-tree.lua

│       ├── telescope.lua
│       └── treesitter.lua
├── init.lua
├── lua
│   └── user
│       ├── packer.lua
│       ├── remaps.lua
│       └── settings.lua
└── plugin
    └── packer_compiled.lua

5 directories, 12 files

As you can see, we have three head directories and one file in the parent directory. One of the most important files will be the init.lua file; it’s the file that NeoVim will look for on every startup. If you have configured neovim before, it’s similar to the init.vim file or vimrc in Vim. You must remember to require each file you want to use in the lua/user directory.

Next, we have our after directory, which only has a plugin folder inside. Inside that plugin directory, we have all of our configuration for our plugins, which we’ll talk about later.

Our lua directory, is probably the one we’ll be visiting the most. Here, inside our personal user directory we’ve split all our Lua files. The packer.lua our plugins (which we’ll talk about later), the remaps.lua file is for our remaps, which we’ll configure later too, and finally, our settings.lua file, where our settings are at (we’ll talk about that next).

Just a quick note: you might notice we have a user directory in our lua directory. This can be named anything, some people name it after themselves, but I prefer to keep it as user. This directory, however, is important as it prevents our Lua files from interfering with other Lua files.

You don’t have to worry about the plugin directory too much for now.

I wanted to address quickly: you can still use vimscript if you really need by using vim.cmd[],

vim.cmd [[
  # vim script goes here!
  syntax enable

Configuring Settings

Let’s start by making our editor feel a little bit more comfortable. This can easily be done by changing some of the editor’s settings. Inside of lua/settings.lua or however you want to call your settings file. To make things look cleaner, I made two variables to reference the vim API. Setting up your settings is easy; the way I did it is using the following method:

local o = vim.o

o.myOption = myValue

-- Example:
o.number = true
o.history = 50
o.mouse = 'a'

On the examples above I used the scope for general settings, but of course, there are many more:

  • vim.o - for general settings
  • vim.wo - for for window-scoped options.
  • - for for buffer-scoped settings.
  • vim.g - for for global variables, which you’re commonly use for plugins.
  • vim.opt - to set global, window, and buffer options. Basiclly :set

If you want to see more options and what they change to the edtior, you can use :help options

Using and Setting Remaps

Remaps, while you can live without them, definitely make the developer experience a lot more comfortable, and sometimes can even boost productivity. They are also easy to set up. So In our remaps.lua file inside of lua/user we’ll do:

  • Mode - refers to what mode the remap is for. You’re gonna have to use an abreviation though, which you can find the list of here.
  • Function - can be either a command from the bar, or a key combination (in the same format you define the remap)
  • For additional arguments, you might want to use :help vim.keymap.set().
-- Some variables to be more organized
local opts = { noremap = true, silent = true } -- Commonly used option
local keymap = vim.api.nvim_set_keymap -- Calls the vim api

-- Basic Syntax:
keymap("mode", "<remap>", "function") -- more info about what these mean above.

-- Example:
keymap("n", "<C-e>", ":NvimTreeToggle<cr>", opts)
--     ^^^ will run ":NvimTreeToggle", which is a plugin that I'll talk about later

To get an idea of some remaps you might like, you can check out my personal remap file

RELATED: ⭐️ Get Started With Git: a MUST for Developers


Plugins are a big part of neovim (and honestly one of my favorites) because they make it so easy to use Lua to make plugins, which allows the community to create amazing plugins! While there are multiple plugin managers available, I found I liked packer.nvim the most. To get started you need a packer.lua file. In this file, we’ll first install Packer, and then I added some other optional commands (thanks to chris@machine), like making Packer use a popup window. If we move a little further down, we’ll see some of the actual plugins. To install plugins you can use the following:

-- Simple syntax:
use "github/repo"

-- For more options:
        -- other options, but I'd recommend using a separate config file for each plugin

-- Example:
use({'nvim-treesitter/nvim-treesitter', run = ':TSUpdate'})
-- ^^^ Installs nvim-treesitter, and runs ':TSUpdate' on load

Again, you can check out my config to get an idea of the plugins that I use. But here are some of my personal favorites:

Most plugins require, or you’ll most likely want to configure them. Now, you can configure your plugins in the packer.lua file, but I’d recommend creating a separate file for each plugins you want to configure in after/plugin. The first thing you’ll have to do in every configure file is require your plugin, then you can simply follow the docs of each specific plugin. Here are my plugin config files, which again are heavily inspired from NeoVim from Scratch.


I hope that you learnt at least one thing new while reading today. In short, we’ve learnt the basics of how to define new remaps, set settings, and use a plugin manager to use.. well plugins!

I appreciate you spending your time reading this post, if you’d like to read more here you go:

🏠 Home Page

🔥 Goodbye 2022, and What to Expect in the Fututre