Preface

Welcome to how2neovim!

Neovim is a highly customizable and extensible text editor. And although wonderful, it can sometimes be a bit confusing or daunting for newcomers to start configuring.

It’s a terminal-based application built for editing and manipulating text, and is also popular among programmers due to its large plugin ecosystem.

This book aims to be an entry point to Neovim configuration - explaining in detail how it works, and how you can configure Neovim on your own.

What this book is not

This book is not a copy and paste configuration for Neovim.

It is intended to help you understand how configuration works so you can make the program your own, rather than giving you a bootstrapped system.

This book is not a guide on how to use Vim motions. Using Neovim and becoming productive with its many keybinds is not in the scope of this book.

Plenty of excellent resources exist on getting proficient with Vim keybindings, and this book is instead focused purely on understanding how Neovim, as a tool/program works.

Installing Neovim

To install Neovim on MacOS or Linux, you can use your operating system's package manager.

MacOS

MacOS using Homebrew:

brew install neovim

Linux

Arch Linux:

sudo pacman -S neovim

Debian:

sudo apt-get install neovim

Ubuntu:

sudo apt install neovim

For all other Linux distributons, try installing it with your respective package manager. See the entire list of supported distros here.

First Steps

To run Neovim, open up a terminal and type the command nvim.

From here, you can press I to enter insert mode, and start typing.

To quit Neovim, press Esc or Ctrl + [ to enter normal mode, and type :q! to quit without saving the file.

Neovim, like a lot of other UNIX programs, is configured through a user’s dotfiles.

By creating dotifles for Neovim, you can change the default settings, initialize plugins, set colorschemes, and more.

When you open Neovim, it will look for these dotfiles in order to load your configuration into Neovim. One of the most important files that Neovim will look for on startup is the init.lua file.

Creating an init.lua file

Neovim will look for a file named init.lua stored in your config directory, which is ~/.config/nvim.

If you don't already have one, create the directories needed with the following command:

mkdir ~/.config/nvim

And from your home directory, enter it with:

cd .config/nvim

From here, run touch init.lua to create your initial configuration file.

If you want to learn more about how this works, open Neovim, type :h lua-guide, and scroll to lua-guide-config.

Testing Your Initial Configuration File

Open up your new init.lua file with nvim init.lua.

Enter insert mode with I and type the following:

print("Hello World!")

Then go back to normal mode with Esc, and type :wq to save and quit the file.

Re-open the file with nvim init.lua, and you should see "Hello World!" at the bottom of your terminal.

If so, then congratulations! 🎉

You've just created your first custom Neovim configuration.

Writing an initial configuration

Neovim has numerous built-in options for changing the default behaviour of Neovim.

Let’s start by creating some very simple settings that you might want for your Lua configuration. We'll then go over the configuration line by line, and explain what the settings do.

Open up your init.lua file and add the following code:

vim.opt.cursorline = true
vim.opt.number = true
vim.opt.relativenumber = true
vim.opt.termguicolors = true

You can save and quit with :wq and re-open Neovim, and you should notice some changes to your editor.

This code:

  • Sets a cursorline (highlights your currently selected line)
  • Adds line numbers on the left-hand side of your editor window
  • Sets the line numbers to be relative (this will make more sense later)
  • Uses true colors for the terminal

Where's the rest of it?

In many configurations you will copy from online, there will be a lot more options set. But what some of these users don't realize is that Neovim comes with a set of sensible defaults, meaning a lot of the typical settings you might need are already set internally.

If you want to add any other configuration options yourself, it's worth looking through this list to see if they are already enabled/disabled by default first.

Optional: Refactor your code

If you want to shorten each line of code, you could set up a variable to map vim.opt to a variable called opt to make each line shorter.

This is completely optional, and only affects the aesthetics of your configuration.

local opt = vim.opt

opt.cursorline = true
opt.number = true
opt.relativenumber = true
opt.termguicolors = true

Setting a Leader Key

Creating custom keymaps is common in Neovim, as many users want to download plugins with additional functionality for their editor.

Users can then use their own custom keybinds to map plugin commands to something memorable.

In Vim and Neovim, there is a special key which is intented for custom user commands called the leader key.

Remapping the Leader Key

By default, the leader is set to backslash (\). To many, this doesn't often feel very intuitive.

It is often remapped to the space key for ease of use, and because it doesn't clash with any of the default keys used in Vim's normal mode.

To remap the leader key to space, simply add the following line of code to your init.lua file:

vim.g.mapleader = " "

If you do decide to remap the leader key to something other than space, it may be worth looking up the default keys used in Neovim.

Introduction to Plugins

The plugin ecosystem is one of the many reasons people decide to use Neovim.

Plugins are user created, and add extra functionality to Neovim outside of what is possible with base program.

Plugin Managers

Plugins are usually installed and managed by a plugin manager, which is a bit like a package manager for your desktop system.

It saves you the trouble of having to dig through GitHub repositories, manually download the code for the plugin you want, make sure the scripts are in the correct place for Neovim to use, and periodically check for any new updates. Plugin managers do this for you auto-magically. 🪄

Historically, Neovim users have used third-party plugin managers developed by members of the community.

More recently, Neovim has added a built-in plugin manager called vim.pack which is still in early development. In this book, we will focus on the plugin manager lazy until the built-in plugin manager is out of nightly build.

Setting up lazy

There are many different plugin managers in the Neovim ecosystem. This book will use lazy.nvim.

To configure lazy, add the following code to start of your init.lua file.

local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
    vim.fn.system({
        "git",
        "clone",
        "--filter=blob:none",
        "https://github.com/folke/lazy.nvim.git",
        "--branch=stable", -- latest stable release
        lazypath,
    })
end
vim.opt.rtp:prepend(lazypath)

Breaking Down The Code

Here's a step-by-step breakdown of what this code does:

  1. Line 1 creates a path to the Neovim data directory:

  2. Line 2 checks whether that path exists (i.e. checks whether or not you already have lazy installed)

  3. Lines 3 - 9 clones the repo if it doesn't exist on your system (in other words, installs lazy)

  4. Line 10 adds lazy to Neovim’s runtimepath

lazy is a plugin manager and a plugin itself - lazy adds itself to the runtimepath, so it loads every time Neovim is opened. In turn, it will manage the plugins you install.

Directly after this code, the plugin manager is bootstrapped and now needs to be setup with the following line of code:

require("lazy").setup({})

Keep in mind that require is a Lua concept, not a Neovim concept.

While the first code snippet installs the plugin manager, this one runs it.

Congratulations!

You now have your very own Neovim plugin manager setup. Now it's time to install some plugins.

Installing a Colorscheme

The first thing you might want to do upon customization of your Neovim instance is to add a custom theme.

Most users will install themes using their plugin manager, and as it's just a set of colors, it works for a simple example for a first installation of a plugin.

Finding a Colorscheme

You can find a colorscheme you like on lists like Awesome Neovim, or Dotfyle.

If you're planning to write code, you will likely want a tree-sitter compatible theme (which will be explained later).

Installing a Colorscheme

Once you find a colorscheme you like, there should be instructions in the GitHub repository on how to install the theme using your plugin manager (in this case, lazy).

For example, here is the line of code used to install the Catppuccin theme.

{ "catppuccin/nvim", name = "catppuccin", priority = 1000 }

This, along with any other plugins, are added to a spec table within the setup({}) brackets of the line require("lazy").setup({}) in your init.lua file.

For example:

require("lazy").setup({
  spec = {
    { "catppuccin/nvim", name = "catppuccin", priority = 1000 }
  },
})

Setting the colorscheme

Once you've installed a colorscheme, you can set it using the colorscheme command.

Add the following line of code to your init.lua file:

vim.cmd.colorscheme("catppuccin-mocha")

Some themes may have variants, and the documentation for each theme should walk you throught the appropriate name to use to set the theme.

Setting and using multiple colorschemes

You first need to install multiple colorschemes, e.g.

{ "catppuccin/nvim", name = "catppuccin", priority = 1000 },
{ "neanias/everforest-nvim", priority = 1000 }

You can then set up keybinds to enable switching between them:

vim.keymap.set("n", "<leader>cc", "<cmd>colorscheme catppuccin-mocha<cr>")
vim.keymap.set("n", "<leader>ce", "<cmd>colorscheme everforest<cr>")

This is a simple and minimal way to switch themes, but you may want to explore other methods, or third-party plugins.

Installing Other Plugins

As mentioned in the previous chapter, to install plugins you typically need to include the name of the plugin inside of the curly brackets in your lazy.setup({}) method.

Let's take a look at an exmaple of installing a plugin, and how to set up different types of plugins.

Plugin Example: Installing Lualine

Here’s an example of how you would install the lualine plugin - a simple statusline for Neovim.

require("lazy").setup({
    { "nvim-lualine/lualine.nvim", dependencies = { 'nvim-tree/nvim-web-devicons' }, opts = {} }
})

Each plugin will have a different way to set it up, and there's a lot going on in this line of code.

The dependencies table specifies any other plugins lualine relies on. In this case, it relies on nvim-web-devicons, which you can choose to install here instead of separately.

The second part is an empty table assigned to the name opts.

What this essentially says, in terms of lazy, is "this plugin has no other options set, please set it up automatically for me".

If this part opts = {} was removed from the individual plugin table, we instead would have to write a line of code to set up the plugin manually, e.g. with:

require("lualine").setup()

Each plugin is slightly different to set up, and may have additional options you can configure inside of the opts = {} brackets.

Finding Plugins

You can find curated lists of popular plugins on Dotfyle and at Awesome Neovim.

Introduction to Tree-sitter

Tree-sitter is a parsing library that improves code syntax highlighting in Neovim. Tree sitter comes built-in to Neovim, and is relatively easy to configure.

Installing nvim-treesitter

The Neovim core team provide an official plugin which helps make using tree-sitter within Neovim a lot easier.

To install nvim-treesitter, add the following line of code to your lazy setup.

{"nvim-treesitter/nvim-treesitter", lazy = false, build = ":TSUpdate"}

Configuring Tree-sitter

For tree-sitter, there are many different modules you may wish to use or enable. Two of the most important options to set are ensure-installed and highlight.

Tree-sitter does not enable syntax highlighting by default. You need to explicitly enable it in your configuration. Here is an example configuration.

require("nvim-treesitter.configs").setup({
  ensure_installed = { "c", "lua", "vim", "vimdoc", "query" },
  highlight = {
      enable = true
  }
})

Replace the languages in ensure_installed with the relevant languages you need. The full list of languages and additional configuration options are available here.

🚨 Help! My code still looks the same!

Sometimes you won’t see any noticeable difference in your syntax highlighting until you install a language server (which we will do in the LSP section).

Tree-sitter and colorschemes

When picking a Neovim colorscheme, you may want to install a theme which is tree-sitter supported/compatible — Awesome Neovim provides a list of themes which you can use.