Your first Neovim config
I want to show you how to build a simple configuration file for Vim and Neovim. So here I will teach you the basic commands and functions that you can use to customize Neovim.
I will explain enough so you understand what is happening, but I will not go in depth on every single detail and possibility. At the end there will be a snippet of code you could use as the base for your first configuration.
The config directory
By default Neovim's main configuration file needs to be in a dedicated directory. The path to this directory can change depending on the operating system or environments variables, but these are the usual places:
~/.config/nvim/ (Unix and OSX)
~/AppData/Local/nvim/ (Windows)You must create this directory yourself.
To know the exact path of Neovim's config directory execute this command on the terminal.
nvim --headless -c 'echo stdpath("config") . "\n"' -c 'quit'The init file
Here decisions need to be made. The configuration file for Neovim can be written in vimscript or lua.
I will use vimscript because I want to show a configuration that works in Vim and Neovim. But do keep in mind Vim and Neovim have different names and location for the configuration file.
In Neovim the configuration file should be called init.vim. And this would be the (usual) path.
~/.config/nvim/init.vim (Unix and OSX)
~/AppData/Local/nvim/init.vim (Windows)Of course, if we were to choose lua the file wouldn't be init.vim, it would be init.lua.
Set your settings
In vimscript we use the :set command to configure Vim options. These are the settings I find useful.
set number
set norelativenumber
set signcolumn=yes
set tabstop=2
set shiftwidth=2
set expandtab
set nowrap
set nohlsearch
set smartcase
set ignorecase
set mouse=nvi
set termguicolors
set cursorline
set noswapfile
set completeopt=menu,menuone,noinsertNotice some of these start with the prefix no. This works for a specific type called boolean. Boolean options can only have two values, it's either enabled or disabled. Consider this.
set relativenumber
set norelativenumberrelativenumber is the name of the option itself. But if it has the prefix no then it means we want to disable it.
To know more details about an option you can read the help page. Write the command :help and wrap the name of the option in single quotes. For example:
:help 'relativenumber'Changing the color scheme
Interestingly enough there isn't an option to change the theme of the editor. Instead we have a dedicated command, :colorscheme.
colorscheme habamaxUnfortunately the command colorscheme habamax will fail on older versions of Neovim below v0.8.
If we don't want the execution of our config to be interrupted by an error we can use the :try command.
try
colorscheme habamax
endtryCheck Neovim's version
Not every package manager will have the latest Neovim available in its official repository. Installing Neovim on OSX via homebrew can get you v0.11 or greater. But using apt install on Ubuntu 24.04 will get you v0.9.5.
If we want to have a configuration that's backwards compatible is a good idea to check Neovim's version before using a feature that we know is only available in newer versions.
Here's an example using a new colorscheme called retrobox.
if has('nvim-0.10')
colorscheme retrobox
endifIn this snippet we are using two features of vimscript. We have a conditional block and the has() function. In this case we check if we have Neovim v0.10, and if it's true use the retrobox theme.
has() can also be used to detect if we are using Vim or Neovim. We can do this.
if !has('nvim')
set hidden
set belloff=all
set autoread
set autoindent
set laststatus=2
set wildmenu
set wildoptions=pum,tagfile
syntax enable
endifHere you can read !has('nvim') as "we are not inside Neovim" and so the code inside the block will only execute on Vim. Note the code inside the if block is already part of Neovim's default, there is no need to execute it (again) if we are already in Neovim.
Configure Netrw
Right now Netrw is the default file explorer in Vim and Neovim. This is implemented as a plugin written in vimscript. This means we have to use global variables to configure it.
To modify global variables we use the :let command. Here is an example.
let g:netrw_banner = 0Here g:netrw_banner is the name of the variable. The equal sign means this is an assignment. The thing on the right hand side of = must be valid vimscript. Although most of the time we will use numbers or text wrapped in quotes.
To know what settings are available in Netrw read the documentation.
:help netrw-browser-settingsNow, if your configuration is written in lua then the syntax will change a little bit. In lua we must use vim.g to modify global variables of vimscript plugins.
vim.g.netrw_banner = 0Remember that lua is another scripting language. We can't just write valid vimscript in a lua file. In lua there are special features we can use to interact with vimscript plugins, vim.g is just one of them.
Simple mappings
Keymaps in Vim are basically a way of automating keystrokes. Here is a good example.
xnoremap gy "+yThis command will create the keymap gy in visual mode. So in visual mode when you press gy it'll be the same as pressing "+y.
"+y is the annoying way we can copy text from Neovim to the system clipboard.
xnoremap is part of a family of commands. These are the ones we'll be using most of the time.
nnoremap -> normal mode mapping
xnoremap -> visual mode mapping
inoremap -> insert mode mappingNow, to execute ex-commands we can use :. Like this.
nnoremap <C-g> :echo "Hello there"<cr>With this pressing Ctrl + g in normal mode will print the message Hello there. Notice the : before the echo command, and also the <cr> at the end.
But there is another way to trigger a command, that is using the special sequence <cmd>. I like this more than : because it'll tell you if you forget to add <cr> at the end. Also, according to the documentation, is a little bit more flexible than :.
The previous example can be written like this.
nnoremap <C-g> <cmd>echo "Hello there"<cr>One more thing...
We have to talk about "the leader key." This is a special sequence people use as a prefix for their custom keymaps. If you go around in the wild you might find a keymap like this.
nnoremap <leader>w <cmd>write<cr>This <leader> sequence can be configured, so it can be whatever we want. Most people like to use the Space key.
We modify the value of the leader key by assigning a value to the global variable mapleader. This is the most common setup.
let g:mapleader = " "A more complete example would look like this.
let g:mapleader = " "
" Exit Neovim
nnoremap <leader>q <cmd>quitall<cr>
" Save file
nnoremap <leader>w <cmd>write<cr>We have to configure g:mapleader before we use it. Here Space + q would exit Neovim. Space + w would save the current file.
First look at autocommands
Autocommands is the mechanism we use to execute code when an "event" happens.
Consider this piece of code.
autocmd filetype help nnoremap <buffer> q <cmd>close<cr>Here we are creating an autocommand on the event filetype. This event is triggered after Neovim figures out what type of file we are editing. In this specific example we only care about the help filetype. So when we open help page Neovim will execute the nnoremap command.
Sometimes people like to group autocommands together. That way they can track better the code. For example.
augroup hello_cmds
autocmd!
autocmd filetype netrw echo "Hello from netrw"
autocmd filetype help echo "Hello from the help page"
augroup ENDHere we have the hello_cmds group. If we want to inspect all the autocommands in this group, we execute this command.
:autocmd hello_cmdsExample init.vim
" ============================================================================
" === EDITOR SETTINGS ===
" ============================================================================
set number
set norelativenumber
set signcolumn=yes
set tabstop=2
set shiftwidth=2
set expandtab
set nowrap
set nohlsearch
set smartcase
set ignorecase
set mouse=nvi
set noswapfile
set completeopt=menu,menuone,noinsert
if !has('nvim')
set hidden
set belloff=all
set autoread
set autoindent
set laststatus=2
set wildmenu
set wildoptions=pum,tagfile
syntax enable
endif
try
set termguicolors
set cursorline
colorscheme habamax
catch
set notermguicolors
set nocursorline
colorscheme default
highlight clear SignColumn
endtry
let g:netrw_banner = 0
let g:netrw_winsize = 30
let g:netrw_liststyle = 0
" ============================================================================
" === KEYMAPS ===
" ============================================================================
" Use <Space> as a leader key
let g:mapleader = " "
" Copy/paste using system clipboard
nnoremap gy "+y
xnoremap gy "+y
nnoremap gp "+p
xnoremap gp "+p
" Exit Neovim
nnoremap <leader>q <cmd>quitall<cr>
nnoremap <leader>Q <cmd>quitall!<cr>
" Save file
nnoremap <leader>w <cmd>write<cr>
" Toggle file explorer
nnoremap <expr> <leader>e &ft=='netrw' ? '<cmd>close<cr>' : '<cmd>Lexplore<cr>'
function NetrwMapping()
" Go back in history
nmap <buffer> H u
" Go up a directory
nmap <buffer> h -^
" Open file/directory
nmap <buffer> l <cr>
endfunction
augroup user_cmds
autocmd!
autocmd filetype netrw call NetrwMapping()
autocmd filetype help,man,checkhealth nnoremap <buffer> q <cmd>close<cr>
augroup END