Neovim is a modern, extensible fork of Vim that keeps full backward compatibility while adding first-class Lua scripting, a built-in LSP client, Tree-sitter integration, and asynchronous job control. It is designed for developers who want a fast, keyboard-driven editor that can be shaped into a full IDE.
Modes
Neovim is a modal editor — the meaning of each key depends on which mode you are in. Understanding modes is the single most important concept for productive editing.
| Mode | Enter with | Purpose |
|---|---|---|
| Normal | Esc | Navigate, delete, copy, paste, run commands |
| Insert | i / a / o | Type text into the buffer |
| Visual | v / V / Ctrl-v | Select text (character, line, or block) |
| Command-line | : | Execute Ex commands, search & replace |
| Terminal | :terminal | Run a shell inside a Neovim buffer |
Motions & Operators
Neovim commands follow the grammar operator + [count] + motion. Learning a handful of operators and motions gives you a combinatorial explosion of editing power.
Common Operators
| Operator | Action |
|---|---|
| d | Delete |
| c | Change (delete + enter Insert mode) |
| y | Yank (copy) |
| > | Indent right |
| < | Indent left |
| gq | Format / rewrap text |
| gu / gU | Lowercase / uppercase |
Common Motions
w / b → forward / backward by word
e → end of word
0 / $ → start / end of line
gg / G → top / bottom of file
f{char} → jump to next {char} on the line
t{char} → jump to just before {char}
/{pattern} → search forward
?{pattern} → search backward
% → matching bracketCombine them: d2w deletes two words, ci" changes the text inside quotes, yG yanks from the cursor to the end of the file.
Text Objects
Text objects let you operate on structured chunks of text. Prefix with i for inner (contents only) or a for around (including delimiters).
iw / aw
Inner / around word
diwi" / a"
Inside / around double quotes
ci"i( / a(
Inside / around parentheses
da(i{ / a{
Inside / around curly braces
yi{it / at
Inside / around HTML/XML tag
citip / ap
Inner / around paragraph
dapRegisters
Registers are named storage slots for yanked or deleted text. Prefix a command with "{reg} to target a specific register.
| Register | Description |
|---|---|
| " | Default (unnamed) register |
| 0 | Last yank |
| 1-9 | Last 9 deletes (stack) |
| a-z | Named registers (you choose) |
| + | System clipboard |
| _ | Black hole (discard) |
| . | Last inserted text |
| % | Current filename |
| : | Last command-line command |
Example: "ayy yanks the current line into register a, and "ap pastes it. Use "+y to copy to the system clipboard.
Buffers, Windows & Tabs
Neovim separates the concepts of files (buffers), viewports (windows), and layouts (tabs). A single file can be displayed in multiple windows across multiple tabs.
# Buffers :e file.lua Open a file in a new buffer :bnext / :bprev Navigate buffers :ls List all buffers :bd Close current buffer # Windows (splits) :split / :vsplit Horizontal / vertical split Ctrl-w h/j/k/l Move between windows Ctrl-w = Equalize window sizes Ctrl-w o Close all other windows # Tabs :tabnew New tab gt / gT Next / previous tab
Built-in LSP Client
Neovim ships with a built-in Language Server Protocol client that provides IDE features like go-to-definition, autocomplete, hover docs, rename, and diagnostics — all without plugins.
-- init.lua: minimal LSP setup (Neovim 0.11+)
vim.lsp.enable('lua_ls') -- enable lua-language-server
vim.lsp.enable('ts_ls') -- enable typescript-language-server
-- Common keymaps (set in an LspAttach autocmd)
vim.keymap.set('n', 'gd', vim.lsp.buf.definition)
vim.keymap.set('n', 'gr', vim.lsp.buf.references)
vim.keymap.set('n', 'K', vim.lsp.buf.hover)
vim.keymap.set('n', '<leader>rn', vim.lsp.buf.rename)
vim.keymap.set('n', '<leader>ca', vim.lsp.buf.code_action)
vim.keymap.set('n', '[d', vim.diagnostic.goto_prev)
vim.keymap.set('n', ']d', vim.diagnostic.goto_next)For automatic server installation, the popular mason.nvim and mason-lspconfig.nvim plugins can manage language server binaries for you.
Tree-sitter
Neovim integrates Tree-sitter for fast, accurate syntax highlighting and code-aware text objects. Instead of regex-based highlighting, Tree-sitter builds a real parse tree of your code.
-- Install parsers (via nvim-treesitter plugin) :TSInstall lua typescript python rust -- Tree-sitter powered text objects (with nvim-treesitter-textobjects) -- vaf → select outer function -- vic → select inner class -- ]m → jump to next method
Configuration with Lua
Neovim uses init.lua (or the legacy init.vim) located in ~/.config/nvim/. Lua is the recommended language for all new configuration.
-- ~/.config/nvim/init.lua
-- Options
vim.opt.number = true -- line numbers
vim.opt.relativenumber = true -- relative line numbers
vim.opt.tabstop = 2 -- tab width
vim.opt.shiftwidth = 2 -- indent width
vim.opt.expandtab = true -- spaces instead of tabs
vim.opt.signcolumn = 'yes' -- always show sign column
vim.opt.clipboard = 'unnamedplus' -- use system clipboard
vim.opt.ignorecase = true -- case-insensitive search
vim.opt.smartcase = true -- unless uppercase is used
-- Leader key
vim.g.mapleader = ' '
-- Keymaps
vim.keymap.set('n', '<leader>w', ':w<CR>')
vim.keymap.set('n', '<leader>q', ':q<CR>')
vim.keymap.set('n', '<Esc>', ':nohlsearch<CR>')Plugin Management
lazy.nvim is the de facto standard plugin manager. It supports lazy loading, lockfiles, a UI dashboard, and automatic dependency resolution.
-- Bootstrap lazy.nvim (place at top of init.lua)
local lazypath = vim.fn.stdpath('data') .. '/lazy/lazy.nvim'
if not vim.uv.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)
require('lazy').setup({
{ 'nvim-telescope/telescope.nvim', -- fuzzy finder
dependencies = { 'nvim-lua/plenary.nvim' } },
{ 'nvim-treesitter/nvim-treesitter', build = ':TSUpdate' },
{ 'neovim/nvim-lspconfig' }, -- LSP configs
{ 'hrsh7th/nvim-cmp' }, -- autocompletion
})Essential Plugins
telescope.nvim
Fuzzy finder for files, grep, buffers, and more
:Telescope find_filesnvim-cmp
Autocompletion engine with LSP, snippet, and path sources
Ctrl-n / Ctrl-poil.nvim
File explorer as an editable buffer
:Oilgitsigns.nvim
Git signs in the gutter, inline blame, hunk actions
:Gitsigns preview_hunkconform.nvim
Formatter integration (prettier, stylua, etc.)
:ConformFormatnvim-lint
Async linter integration (eslint, ruff, etc.)
Runs on saveMacros
Record a sequence of keystrokes and replay them. This is one of Neovim's most powerful features for repetitive edits.
q{reg} Start recording into register {reg}
q Stop recording
@{reg} Play macro from register {reg}
@@ Repeat last played macro
5@a Play macro 'a' five times
# Example: wrap each line in quotes
qa Record into register a
0i"<Esc> Go to start, insert "
A"<Esc> Go to end, append "
j Move to next line
q Stop recording
99@a Apply to next 99 linesSee the Neovim Cheat Sheet for a quick reference of common keybindings.