Once you're comfortable with Vim, Neovim starts to look interesting. Neovim keeps what's great about Vim and adds modern features on top.
Working Code
Install
# macOS
brew install neovim
# Ubuntu / Debian
sudo apt install neovim
# confirm install
nvim --version
Run it by typing nvim in a terminal. Every keybinding you know from Vim still works.
Your first Lua config file
Neovim's config lives at ~/.config/nvim/init.lua. Create the directory and the file:
mkdir -p ~/.config/nvim
nvim ~/.config/nvim/init.lua
Enter the following content:
-- set the leader key (before everything else!)
vim.g.mapleader = ' '
-- basic options
vim.opt.number = true
vim.opt.relativenumber = true
vim.opt.tabstop = 2
vim.opt.shiftwidth = 2
vim.opt.expandtab = true
vim.opt.ignorecase = true
vim.opt.smartcase = true
vim.opt.termguicolors = true
-- keymaps
vim.keymap.set('n', '<leader>w', ':w<CR>', { desc = 'Save file' })
vim.keymap.set('n', '<leader>q', ':q<CR>', { desc = 'Quit' })
Save the file and reopen Neovim — line numbers and relative line numbers appear.
Try It Yourself
Open init.lua and change some options:
-- highlight the cursor line
vim.opt.cursorline = true
-- highlight search results
vim.opt.hlsearch = true
-- system clipboard integration
vim.opt.clipboard = 'unnamedplus'
-- scroll offset
vim.opt.scrolloff = 8
Add shortcuts with vim.keymap.set:
-- buffer navigation
vim.keymap.set('n', '<leader>bn', ':bnext<CR>', { desc = 'Next buffer' })
vim.keymap.set('n', '<leader>bp', ':bprevious<CR>', { desc = 'Previous buffer' })
-- window navigation with Ctrl + hjkl
vim.keymap.set('n', '<C-h>', '<C-w>h')
vim.keymap.set('n', '<C-j>', '<C-w>j')
vim.keymap.set('n', '<C-k>', '<C-w>k')
vim.keymap.set('n', '<C-l>', '<C-w>l')
"Why?"
Why use Neovim over Vim?
| Feature | Vim | Neovim |
|---|---|---|
| Config language | VimScript | Lua + VimScript |
| LSP support | Needs a plugin | Built-in |
| Async processing | Limited | Full support |
| Plugin ecosystem | Mature | Growing fast |
| Defaults | Minimal | More sensible |
Lua is fast and easy to learn. Here's how settings translate from VimScript to Lua:
| VimScript (vimrc) | Lua (init.lua) |
|---|---|
set number | vim.opt.number = true |
set tabstop=2 | vim.opt.tabstop = 2 |
let mapleader = " " | vim.g.mapleader = ' ' |
nnoremap <leader>w :w<CR> | vim.keymap.set('n', '<leader>w', ':w<CR>') |
colorscheme desert | vim.cmd('colorscheme desert') |
If you already have a .vimrc, you don't need to switch everything at once. Neovim also supports VimScript, so you can migrate to Lua one piece at a time.
Deep Dive
Splitting your config
As your config grows, split it into modules under ~/.config/nvim/lua/:
~/.config/nvim/
├── init.lua -- require('options'), require('keymaps')
└── lua/
├── options.lua -- vim.opt settings
└── keymaps.lua -- vim.keymap.set settings
Then load them from init.lua:
require('options')
require('keymaps')
Build your own init.lua
- Create
~/.config/nvim/init.lua. - Set the Leader key to Space.
- Configure line numbers, tab width 2, and case-insensitive search.
- Add keymaps:
<leader>wto save,<leader>qto quit. - Open any file to confirm the settings are active.
Where is Neovim's config file located?