Neovim Beginner's Guide (Part 1): Basic Configuration

In the world of programming, there are two ancient artifacts. One is called “The Editor of the Gods, Emacs”, and the other is called “The God of Editors, Vim”. These two editors, since their inception, have engaged in an ongoing holy war. Whether it’s Vim or Emacs, both are constantly evolving and developing. Gradually, a dazzling new star has emerged on the branch of Vim, and it’s called Neovim.

From its name, Neovim appears to be a new star in the Vim galaxy. According to the official description: Neovim is a fork of Vim that focuses mainly on extensibility and usability. Many Vim users have migrated to Neovim, inheriting Vim’s charm of classic shortcuts and rich plugin system, while adding new features such as built-in LSP (Language Server Protocol) and asynchronous IO.

Here are some key features and advantages of Neovim:

  1. Compatibility: Neovim is a compatible version of Vim, allowing for seamless use of existing Vim configuration files and plugins. It supports Vim commands and operations, making it easy for Vim users to switch to Neovim.
  2. Asynchronous Support: Neovim introduces mechanisms for asynchronous task processing, allowing the editor to execute long-running tasks in the background without blocking the user interface. This enables plugins and scripts to handle time-consuming operations more efficiently, improving the responsiveness of the editor.
  3. Modern Plugin System: Neovim provides a more flexible and extensible plugin system. It supports plugins written in various programming languages and provides interfaces for communication with external processes, enabling plugins to interact with other programs.
  4. Active Community: Neovim has an active community that continuously drives the development and improvement of the editor. The community offers a plethora of plugins, themes, and configuration files, as well as contributions and support for new features.

Overall, Neovim is a powerful and flexible text editor designed to provide a modern editing experience and offer users a high degree of customization. Whether you’re a beginner or an experienced Vim user, you can benefit from Neovim’s features and capabilities.

Configuration in Neovim can be done through init.vim or init.lua. Currently, most configurations use Lua. This guide will also configure Neovim using Lua. If you’re not familiar with Lua, don’t worry; Lua is easy to learn. You can directly refer to :h lua-guide for Lua tutorials.

On macOS/Linux, this configuration file is located at ~/.config/nvim/, while on Windows, it’s located at %USERPROFILE%\AppData\Local\nvim\. Neovim loads the init.lua file in this directory upon startup, so you only need to configure it in this file.

Firstly, set the file encoding to UTF-8. Simply add the following configuration in init.lua:

1
2
vim.g.encoding = "UTF-8"
vim.o.fileencoding = "UTF-8"

What do o and g mean here?

vim.o means setting options globally, while vim.g sets options globally.

Similar methods include vim.wo for window-local options, and vim.bo for buffer-local options.

Configure tab settings; by default, tabs are set to 4 spaces:

1
2
3
4
vim.o.tabstop = 4
vim.bo.tabstop = 4
vim.o.softtabstop = 4
vim.o.shiftround = true

You can add other basic configurations, such as displaying line numbers:

 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
69
70
71
72
73
-- Encoding set to UTF-8
vim.g.encoding = "UTF-8"
vim.o.fileencoding = "utf-8"
-- Preserve 8 lines around cursor when moving with jkhl
vim.o.scrolloff = 8
vim.o.sidescrolloff = 8
-- Display line numbers
vim.wo.number = true
-- Use relative line numbers
vim.wo.relativenumber = true
-- Highlight current line
vim.wo.cursorline = true
-- Show left gutter signs
vim.wo.signcolumn = "yes"
-- Right reference line
vim.wo.colorcolumn = "160"
-- Tab settings
vim.o.tabstop = 4
vim.bo.tabstop = 4
vim.o.softtabstop = 4
vim.o.shiftround = true
-- Length of indentation with >> <<
vim.o.shiftwidth = 4
vim.bo.shiftwidth = 4
-- Use spaces instead of tabs
vim.o.expandtab = true
vim.bo.expandtab = true
-- Align new lines with current line
vim.o.autoindent = true
vim.bo.autoindent = true
vim.o.smartindent = true
-- Case insensitive search unless containing uppercase
vim.o.ignorecase = true
vim.o.smartcase = true
-- Disable search highlighting
vim.o.hlsearch = false
vim.o.incsearch = true
-- Command-line height
vim.o.cmdheight = 1
-- Automatically reload files modified outside
vim.o.autoread = true
vim.bo.autoread = true
-- Disable line wrapping
vim.wo.wrap = false
-- Jump to next line when <Left><Right> at beginning/end of line
vim.o.whichwrap = "<,>,[,]"
-- Allow hiding modified buffers
vim.o.hidden = true
-- Mouse support
vim.o.mouse = "a"
-- Disable backup files
vim.o.backup = false
vim.o.writebackup = false
vim.o.swapfile = false
-- smaller updatetime
vim.o.updatetime = 300
vim.o.timeoutlen = 500
vim.o.splitbelow = true
vim.o.splitright = true
-- Auto-completion without auto-select
vim.g.completeopt = "menu,menuone,noselect,noinsert"
-- Style
vim.o.background = "dark"
vim.o.termguicolors = true
vim.opt.termguicolors = true
-- Display invisible characters; here, spaces are displayed as dots
vim.o.list = false
vim.o.listchars = "space:ยท,tab:>-"
vim.o.wildmenu = true
vim.o.shortmess = vim.o.shortmess .. "c"
-- Completion menu height
vim.o.pumheight = 10
vim.o.clipboard = "unnamedplus"

https://island-hexo.oss-cn-beijing.aliyuncs.com/neovim%E6%8C%87%E5%8D%97/neovim%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97%200148d9f0831f494fbe505a595a51c2ef/image.png

System

After years of development, Vim/Neovim remains active, and the plugin system plays a significant role. Rich plugins can turn Neovim into an IDE in minutes.

As the community develops, the Vim plugin system continues to grow. Currently, Vim’s plugins can cover almost all aspects of editing. For Neovim, you can check relevant plugins through awesome-neovim.

Neither Vim nor Neovim has a built-in plugin manager like VSCode or other editors, which allows convenient addition, removal, or updating of plugins. However, various plugin management tools have been developed by talented individuals. Currently, notable plugin managers for Neovim include packer.nvim and lazy.nvim (Note: Do not confuse with LazyVim).

This guide will use lazy.nvim as the plugin management tool. If you’re using packer.nvim for plugin management, it won’t affect your reading, and you can skip the plugin manager section.

Installing lazy.nvim, a popular plugin management tool, is quite simple. Add the following code to init.lua:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
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("lazy").setup()

https://island-hexo.oss-cn-beijing.aliyuncs.com/neovim%E6%8C%87%E5%8D%97/neovim%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97%200148d9f0831f494fbe505a595a51c2ef/image_1.png

Save and exit, then re-enter Neovim. Neovim will check whether lazy exists, and if not, it will clone it from GitHub.

Using the :Lazy command, if you see the following image, lazy.nvim is successfully installed.

https://island-hexo.oss-cn-beijing.aliyuncs.com/neovim%E6%8C%87%E5%8D%97/neovim%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97%200148d9f0831f494fbe505a595a51c2ef/image_2.png

With lazy, you can now quickly install, update, and uninstall plugins.

To verify that lazy is functioning correctly, let’s install a theme plugin. I choose catppuccin.nvim.

Refer to the catppuccin documentation on how to install it and add the plugin to the lazy configuration:

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

Exit Neovim, and upon re-entering, lazy will start downloading the related plugin.

https://island-hexo.oss-cn-beijing.aliyuncs.com/neovim%E6%8C%87%E5%8D%97/neovim%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97%200148d9f0831f494fbe505a595a51c2ef/image_3.png

After installation, you’ll notice the theme has been applied. However, upon exiting and re-entering, you may find the theme color reverted to default. Simply add the following line at the end of the configuration file to set the color scheme:

1
vim.cmd.colorscheme("catppuccin")

https://island-hexo.oss-cn-beijing.aliyuncs.com/neovim%E6%8C%87%E5%8D%97/neovim%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97%200148d9f0831f494fbe505a595a51c2ef/image_4.png

Catppuccin offers many configurations; however, they are not discussed in detail here. You can check the repository for configuration details.

With a plugin manager, you can now add different plugins.

After the basic understanding above, all configurations are currently written in init.lua. As more plugins are added, the Lua code will continue to grow. It becomes difficult to modify and reference configurations. Leveraging Lua’s features, we can split different configuration files to achieve high cohesion and low coupling.

In Lua, you can use the require function to import different Lua scripts.

Now, create a folder named lua under init.lua, and create two Lua files inside: basic.lua and plugin.lua.

1
2
3
4
5
.
โ”œโ”€โ”€ init.lua
โ””โ”€โ”€ lua
     โ”œโ”€โ”€ basic.lua
     โ””โ”€โ”€ plugin.lua

The directory structure looks as above. Afterwards, copy the configuration contents to the respective files. Place basic configurations in basic.lua and lazy-related configurations in plugin.lua.

Finally, include the relevant configuration files in init.lua:

1
2
require("basic")
require("plugin")

Also, create a theme.lua file for theme-related configurations, and don’t forget to add it in init.lua.

The final directory structure looks like this:

1
2
3
4
5
6
7
.
โ”œโ”€โ”€ init.lua
โ”œโ”€โ”€ lazy-lock.json
โ””โ”€โ”€ lua
    โ”œโ”€โ”€ basic.lua
    โ”œโ”€โ”€ plugin.lua
    โ””โ”€โ”€ theme.lua

To make Vim more convenient and efficient, it’s beneficial to bind shortcuts for various operations. This enhances your workflow efficiency. Following the configuration rules mentioned above, create a file named keybinding.lua under the Lua folder, and add require("keybinding") in init.lua.

A crucial aspect of Vim is the ability to efficiently accomplish tasks through shortcuts. In configuring keybindings, several keys are commonly used and abbreviated, including Ctrl, Alt, and Shift. These keys are often abbreviated in configurations.

KeyAbbreviation
CtrlC-
ShiftS-
AltA-

These three keys are frequently encountered in configurations. However, there are more abbreviations available, which can be seen through :h key-notations.

Additionally, macOS lacks an Alt key, so you may need to modify the Option key. Refer to the Appendix/Modify Alt Key section

.

The leader key is crucial in Vim, as it’s one of the most frequently used keys in Vim. The leader, as the name suggests, is at the forefront and is generally used as a precursor for combination shortcuts, requiring other keys to be pressed after the leader. Vim doesn’t specify who the leader is; any key can serve as the leader. Typically, keys like Space are set as leader keys.

The above provides foundational knowledge before setting up keybindings. Now, let’s start configuring keybindings.

Create a keybinding.lua file in the Lua folder, and add require("keybinding") in init.lua.

Firstly, as mentioned earlier, let’s set the leader key. Here, I’ll use Space as the leader key.

1
2
vim.g.mapleader = " "
vim.g.maplocalleader = " "

Regarding mapleader and maplocalleader differences, refer to https://luciaca.cn/posts/vimscript-learning-on-leaders for relevant documentation.

In Neovim, mappings need to be set via vim.keymap.set(). This function requires four parameters: mode, lhs, rhs, and opts.

ParameterDescription
modeMode abbreviation, common ones include n(normal), i(insert), v(view), etc.
lhsCorresponding key
rhsCorresponding functionality
optsRelated settings
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
vim.g.mapleader = " "
vim.g.maplocalleader = " "
local opt = { noremap = true, silent = true }

-- Indent code in visual mode
vim.keymap.set("v", "<", "<gv", opt)
vim.keymap.set("v", ">", ">gv", opt)

-- Switch tabs left/right
map("n", "<C-h>", ":BufferLineCyclePrev<CR>", opt)
map("n", "<C-l>", ":BufferLineCycleNext<CR>", opt)

-- Omitting other basic configurations

This way, you can customize and add related keybindings.

In the settings, go to Profiles-Keys and set Left Option Key to Esc+.

https://island-hexo.oss-cn-beijing.aliyuncs.com/neovim%E6%8C%87%E5%8D%97/neovim%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97%200148d9f0831f494fbe505a595a51c2ef/Untitled.png

Edit Alacritty’s configuration file alacritty.yml:

1
2
3
4
5
6
7
window:
  # Make `Option` key behave as `Alt` (macOS only):
  #   - OnlyLeft
  #   - OnlyRight
  #   - Both
  #   - None (default)
  option_as_alt: Both

Why Emacs and Vim are called the two great artifacts

BurntSushi/ripgrep

Related Content