Custom Neovim config

Create your own Neovim configuration

Neovim is a highly customizable text editor that allows you to create your own configuration to suit your workflow and preferences. In this guide, I will walk through the steps to set up a custom Neovim configuration.

Step 1: Install Neovim

First, ensure that you have Neovim installed on your system. We should use most latest version which is 0.11.4 at the time of writing. It can downloaded from the official Neovim website or use a package manager like brew, apt, or chocolatey etc depending on our operating system.

Step 2: $NVIM_APPNAME

Neovim uses a specific directory for its configuration files. By default, it looks for configuration files in the ~/.config/nvim directory on Unix-like systems and %APPDATA%\nvim on Windows. We can also set the NVIM_APPNAME environment variable to change the configuration directory. For example, to set it to rdev, we can add the following line to our shell configuration file (e.g., .bashrc, .zshrc):

1
export NVIM_APPNAME="rdev-nvim"

After setting this variable, Neovim will look for configuration files in ~/.config/rdev on Unix-like systems. Starting new neovim will use this directory for configuration and we can start from clean slate without affecting our existing neovim setup.

We can verify that the variable is set correctly by running:

:echo stdpath("config") inside Neovim, which should return the path to our custom configuration directory.

Step 3: Create the Configuration Directory

Let’s create the configuration directory if it doesn’t already exist. We can do this using the following command in the terminal:

1
mkdir -p ~/.config/rdev

We can also create it directly inside neovim using :!mkdir -p ~/.config/rdev or :call mkdir(stdpath("config"), "p"). Now we have the configuration directory ready and we can start adding Lua configuration files.

Step 4: Create the init.lua File

The main configuration file for Neovim is init.lua. Let’s create this file inside our configuration directory:

1
touch ~/.config/rdev/init.lua

or inside neovim using :e ~/.config/rdev/init.lua or :exe "edit" stdpath("config") . "/init.lua". After creating the file, we can start adding our custom configurations using Lua but let’s first start by saving the file by running :w. This init.lua file will be automatically loaded when you start Neovim and will be the entry point for our custom configuration.

Step 5: Add Basic Directory Structure

To keep our configuration organized, we will create a basic directory structure inside our configuration directory.

1
mkdir -p ~/.config/rdev/lua/rdev/foundation

Step 6: Add configuration for lua formatting

To ensure that our Lua files are properly formatted, we will install and add a configuration for stylua, which is Lua formatter. Create a file named .stylua.toml inside the configuration directory:

1
touch ~/.config/rdev/.stylua.toml

Step 7: Add Lazy.nvim plugin manager

To manage our Neovim plugins, we will use lazy.nvim, a modern plugin manager. First, we need to install it by cloning the repository into the appropriate directory:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not (vim.uv or vim.loop).fs_stat(lazypath) then
  local lazyrepo = "https://github.com/folke/lazy.nvim.git"
  local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath })
  if vim.v.shell_error ~= 0 then
    vim.api.nvim_echo({
      { "Failed to clone lazy.nvim:\n", "ErrorMsg" },
      { out, "WarningMsg" },
      { "\nPress any key to exit..." },
    }, true, {})
    vim.fn.getchar()
    os.exit(1)
  end
end
vim.opt.rtp:prepend(lazypath)

vim.g.mapleader = " "
vim.g.maplocalleader = "\\"

-- Setup lazy.nvim
require("lazy").setup({
  spec = {
    -- import your plugins
    { import = "rdev.plugins" },
  },
  install = { colorscheme = { "catppuccin" } },
  checker = {
    enabled = true,
    notify = false,
  },
  change_detection = {
    notify = false,
  },
ui = {
    size = { width = 0.8, height = 0.8 },
    wrap = true,
    border = "none",
    backdrop = 60,
    title = nil,
    title_pos = "center",
    pills = true,
    icons = {
      cmd = " ",
      config = "",
      debug = "● ",
      event = " ",
      favorite = " ",
      ft = " ",
      init = " ",
      import = " ",
      keys = " ",
      lazy = "󰒲 ",
      loaded = "●",
      not_loaded = "○",
      plugin = " ",
      runtime = " ",
      require = "󰢱 ",
      source = " ",
      start = " ",
      task = "✔ ",
      list = {
        "●",
        "➜",
        "★",
        "‒",
      },
    },
})

Step 8: Add plugins

Now we can add our plugins to the! Create a directory named plugins inside the lua/rdev directory:

1
mkdir -p ~/.config/rdev/lua/rdev/plugins

Now we can add our plugins to the plugins directory. Create a file per plugin named plugin-name.lua inside the plugins directory:

1
touch ~/.config/rdev/lua/rdev/plugins/plugin-name.lua

In order to allow lazy.nvim to load our plugins we need to return lua-table in each plugin file. The table should have the following structure:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
return {
  "nvim-treesitter/nvim-treesitter",
  event = { "BufReadPre", "BufNewFile" },
  build = ":TSUpdate",
  config = function()
    -- import nvim-treesitter plugin
    local treesitter = require("nvim-treesitter.configs")

    -- configure treesitter
    treesitter.setup({ -- enable syntax highlighting
      highlight = {
        enable = true,
      },
      -- enable indentation
      indent = { enable = true },
      -- ensure these language parsers are installed
      ensure_installed = {
        "go",
        "elixir",
        "java",
        "json",
        "javascript",
        "typescript",
        "tsx",
        "yaml",
        "html",
        "css",
        "prisma",
        "markdown",
        "markdown_inline",
        "svelte",
        "graphql",
        "bash",
        "lua",
        "vim",
        "dockerfile",
        "gitignore",
        "query",
        "vimdoc",
        "c",
      },
      incremental_selection = {
        enable = true,
        keymaps = {
          init_selection = "<C-space>",
          node_incremental = "<C-space>",
          scope_incremental = false,
          node_decremental = "<bs>",
        },
      },
    })
    vim.treesitter.language.register("bash", "zsh")
  end,
}

Here we instructed lazy.nvim to load the nvim-treesitter plugin and configure it to automatically install TreeSitter parsers for some languages.

This process should be repeated for each plugin we want to install. For example my settings look like the following:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
.
├── after
│   └── plugin
│       ├── gitsigns.lua
│       ├── ibl.lua
│       ├── nvim-cmp.lua
│       ├── restore-cursor.lua
│       └── telescope.lua
├── init.lua
├── lazy-lock.json
└── lua
    └── rdev
        ├── foundation
        │   ├── init.lua
        │   ├── keymaps.lua
        │   └── options.lua
        ├── lazy.lua
        ├── lsp.lua
        ├── plugins
        │   ├── arrow.lua
        │   ├── autopairs.lua
        │   ├── barbecue.lua
        │   ├── catpuccin.lua
        │   ├── gitsigns.lua
        │   ├── ibl.lua
        │   ├── lazydev.lua
        │   ├── lazygit.lua
        │   ├── lsp
        │   │   ├── lsp.lua
        │   │   └── mason.lua
        │   ├── lspkind.lua
        │   ├── lualine.lua
        │   ├── neotree.lua
        │   ├── nerdy.lua
        │   ├── noice.lua
        │   ├── numb.lua
        │   ├── nvim-cmp.lua
        │   ├── nvim-tmux.lua
        │   ├── nvim-tree.lua
        │   ├── outline.lua
        │   ├── persistence.lua
        │   ├── rainbow-delimiters.lua
        │   ├── snacks.lua
        │   ├── telescope-symbols.lua
        │   ├── telescope.lua
        │   ├── tiny-inline-diagnostics.lua
        │   ├── treesitter.lua
        │   ├── twilight.lua
        │   ├── undotree.lua
        │   └── which-key.lua
        └── settings
            ├── ibl.lua
            └── init.lua