Neovim: Modern Vim with LSP and Plugin Configuration
In this tutorial, you'll learn Neovim setup including Lua configuration, LSP integration, treesitter, autocompletion, and plugin management for a modern IDE-like editing experience in the terminal.
Why Neovim Matters
Modern development demands modern tooling. Neovim brings the speed and modal editing of Vim together with Language Server Protocol support, asynchronous plugins, and a Lua-based configuration system. It gives you an IDE experience inside the terminal without the bloat of Electron-based editors.
By the end of this guide, you will have a fully configured Neovim setup with LSP, autocompletion, treesitter, and a plugin manager.
What is Neovim?
Neovim is a fork of Vim that reimagines the editor for modern workflows. It introduces a Lua scripting API, an embedded terminal, a job control system, and native LSP client support.
flowchart LR A[Neovim] --> B[Lua Config] A --> C[Lazy.nvim Plugin Manager] C --> D[Treesitter] C --> E[LSP Config] C --> F[nvim-cmp Autocompletion] D --> G[Syntax Highlighting] D --> H[Code Navigation] E --> I[Diagnostics] E --> J[Go to Definition] F --> K[Completion Menu]
Installation
# macOS
brew install neovim
# Ubuntu/Debian
sudo apt install neovim -y
# Verify
nvim --version
# NVIM v0.10.0
Lua Configuration
Neovim configuration lives in ~/.config/nvim/. The main entry point is ~/.config/nvim/init.lua.
# Create the config directory
mkdir -p ~/.config/nvim
Basic init.lua
-- ~/.config/nvim/init.lua
vim.opt.number = true
vim.opt.relativenumber = true
vim.opt.tabstop = 4
vim.opt.shiftwidth = 4
vim.opt.expandtab = true
vim.opt.smartindent = true
vim.opt.wrap = false
vim.opt.swapfile = false
vim.opt.backup = false
vim.opt.undodir = os.getenv("HOME") .. "/.vim/undodir"
vim.opt.undofile = true
vim.opt.hlsearch = true
vim.opt.incsearch = true
vim.opt.ignorecase = true
vim.opt.smartcase = true
vim.opt.scrolloff = 8
vim.opt.signcolumn = "yes"
vim.opt.updatetime = 50
vim.opt.colorcolumn = "80"
Plugin Manager: Lazy.nvim
Lazy.nvim is the most popular Neovim plugin manager. It handles installation, updates, and lazy-loading.
git clone https://github.com/folke/lazy.nvim.git \
~/.local/share/nvim/lazy/lazy.nvim
Plugin Configuration
-- ~/.config/nvim/init.lua
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
vim.opt.rtp:prepend(lazypath)
require("lazy").setup({
-- Treesitter
{
"nvim-treesitter/nvim-treesitter",
build = ":TSUpdate",
config = function()
require("nvim-treesitter.configs").setup({
ensure_installed = {"lua", "python", "javascript", "typescript", "rust", "c", "cpp"},
auto_install = true,
highlight = { enable = true },
indent = { enable = true },
})
end,
},
-- LSP Configuration
{
"neovim/nvim-lspconfig",
config = function()
require("lspconfig").lua_ls.setup({})
require("lspconfig").pyright.setup({})
require("lspconfig").tsserver.setup({})
end,
},
-- Autocompletion
{
"hrsh7th/nvim-cmp",
dependencies = {
"hrsh7th/cmp-nvim-lsp",
"hrsh7th/cmp-buffer",
"hrsh7th/cmp-path",
},
config = function()
local cmp = require("cmp")
cmp.setup({
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 = "buffer" },
{ name = "path" },
}),
})
end,
},
})
LSP Configuration Details
The built-in LSP client connects to language servers for diagnostics, autocompletion, and code actions.
-- Key mappings for LSP
vim.keymap.set("n", "gd", vim.lsp.buf.definition, { desc = "Go to definition" })
vim.keymap.set("n", "K", vim.lsp.buf.hover, { desc = "Hover documentation" })
vim.keymap.set("n", "gi", vim.lsp.buf.implementation, { desc = "Go to implementation" })
vim.keymap.set("n", "gr", vim.lsp.buf.references, { desc = "Show references" })
vim.keymap.set("n", "<leader>rn", vim.lsp.buf.rename, { desc = "Rename symbol" })
vim.keymap.set("n", "<leader>ca", vim.lsp.buf.code_action, { desc = "Code action" })
vim.keymap.set("n", "[d", vim.diagnostic.goto_prev, { desc = "Previous diagnostic" })
vim.keymap.set("n", "]d", vim.diagnostic.goto_next, { desc = "Next diagnostic" })
vim.keymap.set("n", "<leader>e", vim.diagonstic.open_float, { desc = "Open diagnostic float" })
Installing Language Servers
Install language servers with your system package manager or npm:
# Python
npm i -g pyright
# TypeScript/JavaScript
npm i -g typescript typescript-language-server
# Lua
brew install lua-language-server
# Rust
brew install rust-analyzer
Treesitter
Treesitter provides better syntax highlighting and code navigation by Parsing your code into a syntax tree.
Expected Behavior
With Treesitter enabled:
- Code is highlighted more accurately than regex-based highlighting
%jumps between matching brackets and keywords[mand]mjump between function boundaries- Code folding works at the syntax level
-- Additional Treesitter features
require("nvim-treesitter.configs").setup({
incremental_selection = {
enable = true,
keymaps = {
init_selection = "gnn",
node_incremental = "grn",
node_decremental = "grm",
},
},
textobjects = {
select = {
enable = true,
lookahead = true,
keymaps = {
["af"] = "@function.outer",
["if"] = "@function.inner",
["ac"] = "@class.outer",
["ic"] = "@class.inner",
},
},
},
})
Autocompletion with nvim-cmp
nvim-cmp provides a configurable completion engine:
-- Additional completion sources
require("cmp").setup({
snippet = {
expand = function(args)
vim.fn["vsnip#anonymous"](args.body)
end,
},
window = {
completion = cmp.config.window.bordered(),
documentation = cmp.config.window.bordered(),
},
formatting = {
fields = { "kind", "abbr", "menu" },
format = function(entry, vim_item)
vim_item.menu = ({
nvim_lsp = "[LSP]",
buffer = "[Buf]",
path = "[Path]",
})[entry.source.name]
return vim_item
end,
},
})
File Explorer: Neo-tree
require("lazy").setup({
{
"nvim-neo-tree/neo-tree.nvim",
branch = "v3.x",
dependencies = {
"nvim-lua/plenary.nvim",
"nvim-tree/nvim-web-devicons",
"MunifTanjim/nui.nvim",
},
config = function()
require("neo-tree").setup({
filesystem = {
filtered_items = {
visible = false,
hide_dotfiles = false,
hide_gitignored = false,
},
},
})
vim.keymap.set("n", "<leader>e", ":Neotree toggle<CR>")
end,
},
})
Color Scheme
require("lazy").setup({
{
"catppuccin/nvim",
name = "catppuccin",
priority = 1000,
config = function()
require("catppuccin").setup({
flavour = "mocha",
transparent_background = true,
})
vim.cmd.colorscheme("catppuccin")
end,
},
})
Common Errors
| Problem | Cause | Fix |
|---|---|---|
| LSP not attaching to buffer | Language server not installed | Install the server for your language (e.g., npm i -g pyright) |
| Treesitter highlighting broken | Parser not installed | Run :TSInstall <language> |
| nvim-cmp not showing completions | Missing sources | Add cmp-nvim-lsp and configure LSP capabilities |
| Plugin not found by Lazy.nvim | Wrong directory | Ensure plugin spec is correct in require("lazy").setup() |
| Neovim hangs on startup | Corrupted plugin | Delete ~/.local/share/nvim/lazy/ and reinstall |
Practice Questions
1. Where does Neovim read its main configuration from?
~/.config/nvim/init.lua.
2. What does the nvim-treesitter plugin provide?
Better syntax highlighting, code folding, and structure-based navigation.
3. How do you go to a symbol's definition in Neovim with LSP?
Press gd in normal mode.
4. What is Lazy.nvim used for?
Plugin management: installing, updating, and lazy-loading Neovim plugins.
5. How do you install a language server for Python in Neovim?
Run npm i -g pyright, then configure it with require("lspconfig").pyright.setup({}).
Challenge
Create a Neovim configuration from scratch with LSP support for TypeScript and Python. Add Treesitter for syntax highlighting, nvim-cmp for autocompletion, and Neo-tree for file browsing. Include key mappings for go-to-definition, hover documentation, and code actions.
Real-World Task
Use your Neovim setup to work on a Git Repository for one week. Use LSP features for all navigation, Treesitter for code folding, and nvim-cmp for completions. Note how your editing speed compares to your previous editor. Configure :checkhealth to verify all components work correctly.
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro