Published on

A Soy Dev Guide to Neovim

Authors

Introduction

Hold on to your soy lattes because we are about to go on an ascension journey from a mere VSCode normie to "I use vim btw" Chadhood. I promise by the end of this guide, you will go from a soy dev to a soy dev with a neckbeard. You will go from pushing buggy JavaScript code, to pushing buggy JavaScript code blazingly fast.

This guide will be broken up into two separate sections:

  1. The first section will cover the basics, installation of Neovim, LazyVim, and how to customize LazyVim's default plugins and configuration. Readers interested in setting up their own configurations is encouraged to stop here and explore LazyVim's documentation.
  2. At the end, I will provide my personal configuration files as reference for those who are interested in a more opinionated setup.

Pre-Requisites

  • Basic knowledge of Vim motions and commands.
  • Homebrew for package management
  • A working internet connection

Backup Your Configurations (Optional)

If you have an existing nvim configuration, it is recommended to back it up before proceeding.

mv ~/.config/nvim ~/.config/nvim.bak
mv ~/.local/share/nvim ~/.local/share/nvim.bak

Neovim Installation

The official neovim github repo lists the installation instructions for various platforms. For most users, installing neovim via a package manager is the easiest way to get started. I personally use homebrew as I work mainly on MacOS and Linux.

brew install neovim

After installation, you can start neovim by running nvim.

Vanilla Neovim

LazyVim Installation

LazyVim is a Neovim setup, powered by lazy.nvim. It comes with a set of very useful plugins and configuration that are designed to work out of the box. The user experience is very similar to VSCode, with features like LSP support, syntax highlighting, and fuzzy finder.

Before we continue, it is important to understand that in its default state, Neovim is no different than its older brother, Vim. The secret sauce behind Neovim's powerful features lies within the support for plugins, open source projects developed and mainted by the nvim community. With the help of these plugins, we can extend Neovim's functionality to our liking. LazyVim is simply a curated set of neatly packaged plugins. Even the plugin manager, lazy.nvim, is itself a plugin.

This means that we have full control over our Neovim configurations, even with LazyVim installed. We can add, remove, or modify any of the plugins or configurations to our liking. The lazy.nvim plugin manager is designed to make this process as easy as possible.

Install Optional Dependencies

Some of LazyVim pre-configured plugins require additional dependencies to be installed. They are optional, but highly recommended.

brew install ripgrep fd

Clone LazyVim Starter Template

git clone https://github.com/LazyVim/starter ~/.config/nvim
cd ~/.config/nvim

Remove the .git Directory

We will remove the .git directory so that you can track your own configurations in a separate git repository.

rm -rf .git

Start neovim by running nvim.

nvim

You will be greeted with LazyVim's initial setup screen.

LazyVim Initial Setup

Neovim will automatically install the required plugins and set up the configurations. Once the setup is complete, we should see the tokyonight theme applied.

LazyVim Post Initial Setup

Hitting q will close the prompt and open the dashboard.

LazyVim Dashboard

Initialize Git

Finally, let's initialize git in our configuration directory before playing around with the configurations.

~/.config/nvim
git init
git add .
git commit -m "init LazyVim"

Core Features

Besides having all the basic vim motions and functionalities, LazyVim comes with a set of features that are designed to make your life easier as a developer. In this section we will cover some of the most useful features, and in the following section we will learn how to customize them.

For a list of all available default plugins, visit LazyVim's website

Directory Explorer

File tree explorer is managed by neo-tree.nvim. To open the directory explorer, hit <leader>+e. By default, the <leader> key is mapped to the space bar.

Neo-Tree

Common neo-tree key bindings:

  • j and k to navigate up and down
  • l or Enter to open a file or directory
  • h to collapse a directory
  • r to rename a file or directory
  • d to delete a file or directory
  • a to add a new file (or a new directory by adding the / suffix)
  • ? to open the help menu and view all available key bindings

Fuzzy Finder

Fuzzy finding functionalities are provided by telescope.nvim. Telescope relies on ripgrep rg and fd to expose a set of commands that allow you to search for files, buffers, and more, in a neat modal UI. To open the fuzzy finder, hit <leader>+f (as in "find") or <leader>+s (as in "search"). The which-key plugin is also installed by default, which will show you all available key bindings.

Telescope

Common telescope key bindings:

  • <leader>+ff to find files
  • <leader>+fb to find buffers
  • <leader>+fr to find recently opened files
  • <leader>+sw to search the current word under the cursor in the current working directory
  • <leader>+sg to search for a string in the current working directory (live grep)
  • <leader>+st to search for all @todo

LSP Support

LSP support is provided by a combination of different plugins, which requires its own plugin manager, mason.nvim. We could learn more about mason.nvim and how LSP works, but our soy lattes are getting cold so LazyVim comes with a pre-configured LSP setup that works out of the box. You can open the LSP menu by using the command :LazyExtras. Would you look at that, lang.typescript is right there in the Recommended Languages section. Let's install it by hitting x on the keyboard.

LazyExtras

Now, if we open a ts file, we should see the LSP features in action. For example, we can see the type of the variable under the cursor by hitting K in normal mode. Or use the g+d key binding to jump to the definition of a symbol. As we can see below, hitting K reveals the function signature of the BentoChildContainer component.

LSP

If you're interested, you can see which LSP servers are currently attached to your buffer by using the :LspInfo command.

LSP Info

Syntax Highlighting

Syntax highlighting, indentation, and folding are all supported by nvim-treesitter. I'll be completely honest here, I'm not smart enough to understand how it works so I'll just defer you to the official documentation. But hey, it works out of the box and that's all that matters. nvim-treesitter exposes a set of vim commands prefixed with TS, for example, TSToggle to toggle treesitter on and off. I wonder if we can use them for anything useful.

Git Integration

Almost all core plugins in LazyVim have git integration. For example, in the directory explorer, we can see the git status of each file. We can also filter files by their git status or jump back and forth between them. In the fuzzy finder, we can search for files based on their git status. Most importantly, lazygit gives us a terminal git UI that we can use to stage, commit, and push changes, lazygit also provides us with more advanced capabilities such as viewing diffs and resolve merge conflicts, see commit history, and more. You can open lazygit by pressing <leader>+gg.

LazyGit

Hitting ? wil bring up the help menu and display all available key bindings, based on the current menu context.

Customizing Default Configurations

Configuration Files

Our config and plugins are managed by lazy.nvim. This guide only scratch the surface of what lazy.nvim has to offer. I implore curious on-lookers to peruse the official documentation.

If we change directory into ~/.config/nvim, we will see the following structure:

~/.config/nvim
├── lua
│   ├── config
│   │   ├── autocmds.lua
│   │   ├── keymaps.lua
│   │   ├── lazy.lua
│   │   └── options.lua
│   └── plugins
│       ├── example.lua
└── init.lua

IMPORTANT!!!: Do not require autocmds, keymaps, lazy or options under lua/config/ or lazyvim.config manually. LazyVim will load those files automatically.

Override Default Configurations

While LazyVim does come with a set of default configurations, we can override them by editing the files in ./config as they will be loaded after the default configurations. For example, LazyVim's default scrolloff is 4 lines. I prefer 8 lines, so I can override it by adding the following line to ./config/options.lua.

./lua/config/options.lua
  -- Options are automatically loaded before lazy.nvim startup
  -- Default options that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/options.lua
  -- Add any additional options here
+
+ vim.opt.scrolloff = 8

Similarly, we can update the default vim keybindings like so:

./lua/config/keymaps.lua
  -- Keymaps are automatically loaded on the VeryLazy event
  -- Default keymaps that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/keymaps.lua
  -- Add any additional keymaps here

+ -- Selet all
+ vim.keymap.set("n", "<C-A>", "gg<S-v>G")

Override Default Plugins

Finally, we can inject custom configuration for default plugins by adding new files to the ./lua/plugins directory. For example, by default, neo-tree.nvim, our directory explorer and netrw replacement, hides filtered items such as .git, node_modules, or other files and directories listed in your .gitignore.

Default Neo-Tree Behavior

I am not a fan of this behavior, and often ends up having to toggle this feature off every time I open a new nvim instance. If we head over to the neo-tree.nvim github repo, we can see that we can change this behavior by setting filtered_items.visible to true. Let's change that by adding a new file ./lua/plugins/neo-tree.lua with the following content:

~/.config/nvim/
nvim ./lua/plugins/neo-tree.lua
./lua/plugins/neo-tree.lua
+ return {
+   "nvim-neo-tree/neo-tree.nvim",
+   opts = {
+     filesystem = {
+       filtered_items = {
+         visible = true, -- show filtered items (default = false)
+       },
+     },
+   },
+ }

Adding New Plugins

We can also add new plugins not available in LazyVim by default. We can do this by adding a new file to the ./lua/plugins directory. As an example, let's add the gruvbox.nvim colorscheme plugin. Simply create a new file called gruvbox.lua in the ./lua/plugins directory with the following content:

~/.config/nvim/
nvim ./lua/plugins/gruvbox.lua
./lua/plugins/gruvbox.lua
+ return {
+   "ellisonleao/gruvbox.nvim", -- name of the plugin (usually formatted as github <author_slug>/<repo_slug>)
+   lazy = false, -- we can lazy load any plugins we do not need right away by setting this to true
+   priority = 1000, -- as well as the loading priority
+   config = true,
+
+   -- add your config below
+   -- refer to https://github.com/ellisonleao/gruvbox.nvim
+   -- for a list of all available customization options
+   opts = {},
+ }

Then, restart Neovim and run :colorscheme gruvbox to apply the new colorscheme. Look at all that turd brown chocolatey goodness.

Gruvbox Colorscheme

Optionally, instead of just returning one plugin per file, we can return a table of plugins. This is useful when we want to group related plugins together. For example, I have a set of two or three different colorscheme I enjoy switching around every so often, instead of having multiple files for each plugin, let's create a single colorscheme.lua inside the ./lua/plugins directory.

~/.config/nvim/lua/plugins/colorscheme.lua
return {
  {
    "ellisonleao/gruvbox.nvim",
    lazy = true,
    priority = 1000,
  }
  {
    "cranberry-clockworks/coal.nvim",
    lazy = true,
    priority = 1000,
  },
  {
    "craftzdog/solarized-osaka.nvim",
    lazy = true,
    priority = 1000,
    opts = function()
      return {
        transparent = true,
      }
    end,
  },
  {
    -- here we call LazyVim to load the default colorscheme we want to use on startup
    "LazyVim/LazyVim",
    opts = {
      colorscheme = "coal",
    },
  },
}

Disabling Default Plugins

Finally if you wish to disale a default LazyVim plugin entirely, we can do so by setting enabled = false. I'll use folke/flash.nvim as an example. It is a very useful plugin, but I prefer to use the built-in / search highlight feature. Using what we learned above, let's create a new file disabled.lua inside the ./lua/plugins directory, this way we can group all our disabled plugins together.

~/.config/nvim/lua/plugins/flash.lua
return {
  {
    "folke/flash.nvim",
    enabled = false,
  },
  -- add more disabled plugins here
}

Summary

If you have been following the guide so far, you have now learned how to:

  • Install Neovim and LazyVim
  • Use core features
  • Customize LazyVim's default configurations

Armed with this knowledge, you are ready to explore and customize your Neovim experience. Now that's a development environment with a bit more neck hair.

My Configurations

This guide is long enough as is, so I will not go into detail about my personal configurations. You can find them on my GitHub repository