Neovim
Modern Vim fork with Lua configuration and built-in LSP.
Official WebsiteFeatures
Installation
brew install neovimapt install neovimpacman -S neovimcargo install nvimWhy Use Neovim?
Neovim was born as a Vim fork in 2014 and actively incorporates features needed for modern development environments. While maintaining Vim compatibility, it provides innovative features like Lua configuration and built-in LSP.
Lua Configuration
Write configuration in Lua, a fast and readable language. More intuitive than VimScript, with a rich Lua ecosystem available.
Built-in LSP
Native Language Server Protocol support. Code completion, jump to definition, refactoring comparable to VSCode.
Asynchronous Processing
Plugins run in the background. Comfortable editing experience without freezing during heavy operations.
Tree-sitter
Accurate syntax highlighting through advanced parsing. Also improves code folding and text objects.
Installation
# macOS (Homebrew)
brew install neovim
# Ubuntu/Debian (stable)
sudo apt install neovim
# Ubuntu (latest - PPA)
sudo add-apt-repository ppa:neovim-ppa/unstable
sudo apt update
sudo apt install neovim
# Fedora
sudo dnf install neovim
# Arch Linux
sudo pacman -S neovim
# Windows (Chocolatey)
choco install neovim
# Windows (Scoop)
scoop install neovim
# AppImage (Linux)
curl -LO https://github.com/neovim/neovim/releases/latest/download/nvim.appimage
chmod u+x nvim.appimage
./nvim.appimage
# Check version
nvim --versionMode Explanation
Neovim is a modal editor like Vim. Basic modes are shared with Vim.
Normal Mode (Default)
Mode for navigation, text manipulation, and command execution.
Press Esc to return to this mode from other modesInsert Mode
Mode for typing text. LSP completion also works in this mode.
Press i, I, a, A, o, or O to enterVisual Mode
Mode for selecting text. Smart selection with Tree-sitter is also available.
Press v (character), V (line), or Ctrl+v (block) to enterTerminal Mode
Mode that runs in the built-in terminal. This is unique to Neovim.
Open with :terminal, return to Normal mode with Ctrl+\ Ctrl+nBasic Operations
# Open a file
nvim filename.txt
# Open multiple files (tabs)
nvim -p file1.txt file2.txt
# Open in diff mode
nvim -d file1.txt file2.txt
# Skip configuration on startup
nvim --clean
# Use specific configuration file
nvim -u ~/.config/nvim/minimal.lua
# Health check (environment diagnostics)
nvim +checkhealth
# Execute commands in headless mode
nvim --headless -c 'echo "Hello"' -c 'qa'Frequently Used Commands
Neovim-Specific Commands
| Command | Description |
|---|---|
:checkhealth | Diagnose environment and plugins |
:terminal | Open built-in terminal |
:lua print("hi") | Execute Lua code |
:LspInfo | Check LSP status |
:LspStart | Start LSP |
:TSInstall lang | Install Tree-sitter parser |
LSP-Related Key Mappings (Common Configuration)
| Key | Description |
|---|---|
gd | Jump to definition |
gr | Show references |
K | Show hover documentation |
<leader>rn | Rename |
<leader>ca | Code action |
[d / ]d | Move to previous / next diagnostic |
Configuration File
Write Neovim configuration in ~/.config/nvim/init.lua. The traditional init.vim is also available.
-- Basic settings
vim.opt.number = true -- Show line numbers
vim.opt.relativenumber = true -- Relative line numbers
vim.opt.cursorline = true -- Highlight cursor line
vim.opt.termguicolors = true -- True Color support
vim.opt.signcolumn = "yes" -- Always show sign column
-- Indentation settings
vim.opt.tabstop = 2 -- Tab width
vim.opt.shiftwidth = 2 -- Auto-indent width
vim.opt.expandtab = true -- Convert tabs to spaces
vim.opt.smartindent = true -- Smart indent
-- Search settings
vim.opt.hlsearch = true -- Highlight search results
vim.opt.incsearch = true -- Incremental search
vim.opt.ignorecase = true -- Case-insensitive search
vim.opt.smartcase = true -- Case-sensitive if uppercase present
-- Clipboard
vim.opt.clipboard = "unnamedplus"
-- Backup
vim.opt.backup = false
vim.opt.swapfile = false
vim.opt.undofile = true
-- Scroll
vim.opt.scrolloff = 8 -- Keep 8 lines above/below cursor
vim.opt.sidescrolloff = 8
-- Key mappings
vim.g.mapleader = " " -- Set leader key to space
vim.g.maplocalleader = " "
-- Keymap helper function
local keymap = vim.keymap.set
local opts = { noremap = true, silent = true }
-- Save and quit
keymap("n", "<leader>w", ":w<CR>", opts)
keymap("n", "<leader>q", ":q<CR>", opts)
-- Window navigation
keymap("n", "<C-h>", "<C-w>h", opts)
keymap("n", "<C-j>", "<C-w>j", opts)
keymap("n", "<C-k>", "<C-w>k", opts)
keymap("n", "<C-l>", "<C-w>l", opts)
-- Buffer navigation
keymap("n", "<S-l>", ":bnext<CR>", opts)
keymap("n", "<S-h>", ":bprevious<CR>", opts)
-- Clear search highlight
keymap("n", "<Esc>", ":nohlsearch<CR>", opts)
-- Move lines (Visual mode)
keymap("v", "J", ":m '>+1<CR>gv=gv", opts)
keymap("v", "K", ":m '<-2<CR>gv=gv", opts)
-- Escape to Normal mode in Terminal mode
keymap("t", "<Esc>", "<C-\><C-n>", opts)Plugin Management (lazy.nvim)
lazy.nvim is currently the most popular Neovim plugin manager. It features lazy loading and fast startup.
Setting up lazy.nvim
-- lazy.nvim bootstrap
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",
lazypath,
})
end
vim.opt.rtp:prepend(lazypath)
-- Plugin configuration
require("lazy").setup({
-- Color scheme
{
"folke/tokyonight.nvim",
lazy = false,
priority = 1000,
config = function()
vim.cmd([[colorscheme tokyonight]])
end,
},
-- File explorer
{
"nvim-neo-tree/neo-tree.nvim",
branch = "v3.x",
dependencies = {
"nvim-lua/plenary.nvim",
"nvim-tree/nvim-web-devicons",
"MunifTanjim/nui.nvim",
},
keys = {
{ "<leader>e", "<cmd>Neotree toggle<cr>", desc = "Toggle Explorer" },
},
},
-- Fuzzy finder
{
"nvim-telescope/telescope.nvim",
branch = "0.1.x",
dependencies = { "nvim-lua/plenary.nvim" },
keys = {
{ "<leader>ff", "<cmd>Telescope find_files<cr>", desc = "Find Files" },
{ "<leader>fg", "<cmd>Telescope live_grep<cr>", desc = "Live Grep" },
{ "<leader>fb", "<cmd>Telescope buffers<cr>", desc = "Buffers" },
{ "<leader>fh", "<cmd>Telescope help_tags<cr>", desc = "Help Tags" },
},
},
-- Git integration
{
"lewis6991/gitsigns.nvim",
event = { "BufReadPre", "BufNewFile" },
config = true,
},
-- Status line
{
"nvim-lualine/lualine.nvim",
dependencies = { "nvim-tree/nvim-web-devicons" },
config = function()
require("lualine").setup({
options = { theme = "tokyonight" },
})
end,
},
-- Tree-sitter (syntax highlighting)
{
"nvim-treesitter/nvim-treesitter",
build = ":TSUpdate",
event = { "BufReadPost", "BufNewFile" },
config = function()
require("nvim-treesitter.configs").setup({
ensure_installed = {
"lua", "vim", "vimdoc", "javascript", "typescript",
"python", "rust", "go", "html", "css", "json", "yaml",
},
highlight = { enable = true },
indent = { enable = true },
})
end,
},
-- LSP configuration
{
"neovim/nvim-lspconfig",
dependencies = {
"williamboman/mason.nvim",
"williamboman/mason-lspconfig.nvim",
},
config = function()
require("mason").setup()
require("mason-lspconfig").setup({
ensure_installed = { "lua_ls", "tsserver", "pyright" },
})
local lspconfig = require("lspconfig")
local on_attach = function(_, bufnr)
local opts = { buffer = bufnr }
vim.keymap.set("n", "gd", vim.lsp.buf.definition, opts)
vim.keymap.set("n", "K", vim.lsp.buf.hover, opts)
vim.keymap.set("n", "<leader>rn", vim.lsp.buf.rename, opts)
vim.keymap.set("n", "<leader>ca", vim.lsp.buf.code_action, opts)
end
lspconfig.lua_ls.setup({ on_attach = on_attach })
lspconfig.tsserver.setup({ on_attach = on_attach })
lspconfig.pyright.setup({ on_attach = on_attach })
end,
},
-- Auto-completion
{
"hrsh7th/nvim-cmp",
event = "InsertEnter",
dependencies = {
"hrsh7th/cmp-nvim-lsp",
"hrsh7th/cmp-buffer",
"hrsh7th/cmp-path",
"L3MON4D3/LuaSnip",
"saadparwaiz1/cmp_luasnip",
},
config = function()
local cmp = require("cmp")
cmp.setup({
snippet = {
expand = function(args)
require("luasnip").lsp_expand(args.body)
end,
},
mapping = cmp.mapping.preset.insert({
["<C-b>"] = cmp.mapping.scroll_docs(-4),
["<C-f>"] = cmp.mapping.scroll_docs(4),
["<C-Space>"] = cmp.mapping.complete(),
["<CR>"] = cmp.mapping.confirm({ select = true }),
}),
sources = cmp.config.sources({
{ name = "nvim_lsp" },
{ name = "luasnip" },
}, {
{ name = "buffer" },
}),
})
end,
},
})lazy.nvim Commands
:Lazy " Open plugin management UI
:Lazy install " Install plugins
:Lazy update " Update plugins
:Lazy sync " Install, update, and clean in one command
:Lazy clean " Remove unused plugins
:Lazy health " Health check
:Lazy profile " Profile startup timeConfiguration Directory Structure
When your configuration grows, it's recommended to organize files separately.
~/.config/nvim/
├── init.lua # Entry point
├── lua/
│ ├── config/
│ │ ├── options.lua # vim.opt settings
│ │ ├── keymaps.lua # Key mappings
│ │ ├── autocmds.lua # Auto commands
│ │ └── lazy.lua # lazy.nvim bootstrap
│ └── plugins/
│ ├── colorscheme.lua
│ ├── telescope.lua
│ ├── treesitter.lua
│ ├── lsp.lua
│ └── cmp.lua
└── after/
└── ftplugin/ # File type-specific settings
├── lua.lua
└── python.luaTips
- •Run
:checkhealthregularly to discover environment issues early. - •Mason makes it easy to install LSP servers, formatters, and linters. Open the UI with
:Mason. - •Take advantage of lazy.nvim's lazy loading (
event,keys,ft) to reduce startup time. - •Starting with Kickstart or curated distributions (LazyVim, AstroNvim, NvChad) is also a good choice.
- •With Tree-sitter, you can install major languages all at once with
:TSInstall all. - •Identify startup time bottlenecks with
:Lazy profile. - •Since it's compatible with Vim, you can also load existing .vimrc files with
source ~/.vimrc.