Customizing neovim

After working for a while with vim, I’m currently giving a try to neovim. This blog post contains notes on my first steps and discovery of plugins. I believe I will pretty quickly forget about the steps I followed to set this up :)

The rc file of neovim is a lua script init.lua you find in .config/nvim/init.lua. Mine is bascially only containing the plugin manager Lazy.nvim :

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)

require("vim-options")
require("lazy").setup("plugins")

This will also trigger loading the .config/nvim/lua/vim-options.lua and .config/nvim/lua/plugins.lua files. The vim-options file contains some shortcuts, definitions of tabstop, expandtab, etc..

The plugins file only contains return {} but I believe will trigger loading all the plugins in the .config/nvim/lua/plugins directory.

Installing plugins is easy. You just add the lua files, close and reopen nvim and they will be cloned/installed/configured.

Installing a Nerd Font

We can have very nice icons within nvim, especially with the Neotree plugin, after having installed a patched font from the Nerd font project. In my case, I just download the Ubuntu Nerd font. You have to :

  • download the zip
  • extract the zip into .fonts/
  • run the command fc-cache -fv

and that’s it. Combined with the nvim-neo-tree, you get a nice file explorer. For the configuration of neo-tree, here is the plugins/neo-tree.lua file :

return {
	"nvim-neo-tree/neo-tree.nvim",
	branch = "v3.x",
	dependencies = {
		"nvim-lua/plenary.nvim",
		"nvim-tree/nvim-web-devicons",
		"MunifTanjim/nui.nvim",
	},
	config = function()
		vim.keymap.set("n", "<C-n>", ":Neotree filesystem reveal left<CR>", {})
		vim.keymap.set("n", "<leader>o", ":Neotree buffers reveal float<CR>", {})
	end,
}

Where my <leader>o shows the buffer list. I believe it is devicons that display the icons embedded in the patched font.

Greeting page with alpha

The alpha-nvim plugin configures the starting page of nvim

Color theme

The catpuccin.nvim plugin offers a nice color theme. I’m using the mocha one, defined in the plugins/catppuccin.lua script :

return {
  {
    "catppuccin/nvim",
    lazy = false,
    name = "catppuccin",
    priority = 1000,
    config = function()
      vim.cmd.colorscheme "catppuccin-mocha"
    end
  }
}

Language Server Protocols

LSP are the way to have custom functionalities depending on the language you are coding with. I used nvim-lspconfig with mason.nvim and mason-lspconfig doing the bridge. Following the README of mason-lspconfig and adding few LSP by default leads to the following plugins/lsp-config.lua

return
{
    "mason-org/mason-lspconfig.nvim",
    opts = {
      ensure_installed = { "lua_ls", "rust_analyzer", "basedpyright" }
    },
    dependencies = {
        { "mason-org/mason.nvim", opts = {} },
        "neovim/nvim-lspconfig",
    },
}

Here some language servers are defined by default by you can obviously add more. Just defining them there and, tadam, they auto install with the magic of these plugins.

The plugin none-ls.nvim is also setup. I’m not yet sure but it allows to use pure lua scripts as LSP sources. I used the configuration I found somewhere, see below, I still need to dig into it.

return {
  "nvimtools/none-ls.nvim",
  config = function()
    local null_ls = require("null-ls")
    null_ls.setup({
      sources = {
        null_ls.builtins.formatting.stylua,
        null_ls.builtins.formatting.prettier,
        null_ls.builtins.diagnostics.erb_lint,
        null_ls.builtins.diagnostics.rubocop,
        null_ls.builtins.formatting.rubocop,
      },
    })

    vim.keymap.set("n", "<leader>gf", vim.lsp.buf.format, {})
  end,
}

The lsp server will raise warning and errors. An easy way to see these warnings is to use the trouble.nvim plugin for which I defined the proposed configuration in plugins/trouble.lua :

return {
  "folke/trouble.nvim",
  opts = {}, -- for default options, refer to the configuration section for custom setup.
  cmd = "Trouble",
  keys = {
    {
      "<leader>xx",
      "<cmd>Trouble diagnostics toggle<cr>",
      desc = "Diagnostics (Trouble)",
    },
    {
      "<leader>xX",
      "<cmd>Trouble diagnostics toggle filter.buf=0<cr>",
      desc = "Buffer Diagnostics (Trouble)",
    },
    {
      "<leader>cs",
      "<cmd>Trouble symbols toggle focus=false<cr>",
      desc = "Symbols (Trouble)",
    },
    {
      "<leader>cl",
      "<cmd>Trouble lsp toggle focus=false win.position=right<cr>",
      desc = "LSP Definitions / references / ... (Trouble)",
    },
    {
      "<leader>xL",
      "<cmd>Trouble loclist toggle<cr>",
      desc = "Location List (Trouble)",
    },
    {
      "<leader>xQ",
      "<cmd>Trouble qflist toggle<cr>",
      desc = "Quickfix List (Trouble)",
    },
  },
}

Edit your filesystem as a nvim buffer with oil

The oil.nvim allows to edit (rename, create files, etc..) your filesystem as you would do in a normal buffer. You can configure it with plugins/oil.lua :

return {
  "stevearc/oil.nvim",
  config = function()
    local oil = require("oil")
    oil.setup()
    vim.keymap.set("n", "-", oil.toggle_float, {})
  end,
}

Then raise nvim as nvim . to open the current directory. You can navigate with <CR> or -, go into insert mode, change characters, etc.. and validate all these changes.

Fuzzy find with telescope

Using telescope.nvim for fuzzy things :)

Tools for programming

In addition to LSP, I also configured nvim-treesitter. I need to experiment with it.

What about completion ? I’m using several plugins I found configured on one repo . I also need to customize this, maybe to have python snippets for example.

The plugins/completions.lua is for now :

return {
  {
    "hrsh7th/cmp-nvim-lsp"
  },
  {
    "L3MON4D3/LuaSnip",
    dependencies = {
      "saadparwaiz1/cmp_luasnip",
      "rafamadriz/friendly-snippets",
    },
  },
  {
    "hrsh7th/nvim-cmp",
    config = function()
      local cmp = require("cmp")
      require("luasnip.loaders.from_vscode").lazy_load()

      cmp.setup({
        snippet = {
          expand = function(args)
            require("luasnip").lsp_expand(args.body)
          end,
        },
        window = {
          completion = cmp.config.window.bordered(),
          documentation = cmp.config.window.bordered(),
        },
        mapping = cmp.mapping.preset.insert({
          ["<C-b>"] = cmp.mapping.scroll_docs(-4),
          ["<C-f>"] = cmp.mapping.scroll_docs(4),
          ["<C-Space>"] = cmp.mapping.complete(),
          ["<C-e>"] = cmp.mapping.abort(),
          ["<CR>"] = cmp.mapping.confirm({ select = true }),
        }),
        sources = cmp.config.sources({
          { name = "nvim_lsp" },
          { name = "luasnip" }, -- For luasnip users.
        }, {
          { name = "buffer" },
        }),
      })
    end,
  },
}

Interfacing with GIT

You can use gitsigns to have indications for modification, suppression, addition. You can also directly trigger blame, etc..

You can also display what has chaned into the trouble plugin window, like with :Gitsigns setloclist. Within this window, you can switch from one modification to another.




Enjoy Reading This Article?

Here are some more articles you might like to read next:

  • Adb commands over wifi
  • Rethinking deep vision interpretability
  • Atomic auto-encoders for learning sparse representations
  • Job token permissions to access registries
  • Regularized gradient descent