
Neovim has powerful built-in features that most people never discover. Here are some native tips that might save you a plugin install or two!
Multiline Editing
Visual block mode is powerful, but there’s an even better way to run commands on multiple lines. Select lines with V, then press : to prefill the command range. After that, run any normal command with '<,'>norm <cmd>.
For special keys like Ctrl combos or Esc, press <C-v> plus the key.
Example: change var to let and add semicolons:
" Before
var a = 1;
var b = 2;
var c = 3;
" Visual select lines, run: :'<,'>norm ciwlet^[A;
" After
let a = 1;
let b = 2;
let c = 3;
^[ is inserted automatically when you press <C-v><Esc>.
Surround Text Without Plugins
You don’t need a surround plugin. Use registers instead:
" Start with:
hello world
" Select text, run: c"<C-r>"<Esc>
" Result:
"hello world"
<C-r> pastes from registers in insert mode. Try <C-r>a to paste register a, or <C-r>= to evaluate expressions.
Smarter Search and Replace
Omit the Search Term
After searching with /, ?, *, or #, omit the pattern in substitute:
%s//replaced/g
Add live preview with vim.o.inccommand = "split".
Better Find and Confirm Workflow
Instead of %s/find/replace/gc, search first with /, then use gn to select the next match visually. Move through results with n/N, and press . to repeat the replacement.
Store Commands in Plain Text
Execute literal commands stored in registers with :@<reg>:
" Save to register a
"ay
" Execute register a
:@a
You can build little scripts in plain text:
%s/foo/bar/g
g/^#/d
set number
normal! gg=G
Select lines, yank them into a register, and execute anywhere. Neovim runs all commands sequentially.
Split Lines with Regex
Join lines with J (or gJ without spaces). To split, use substitution:
" Before
cookies, milk, rice, beans, beer
" Run: :.s/, */,\r/g
" After
cookies,
milk,
rice,
beans,
beer
.s runs substitute on the current line only.
jkkkkkkkkkkjjjjjjjjjjjjjkjkjkjjjj
For vertical file movement, if you don’t know exactly what you’re looking for:
}/{— Move between paragraphs (blank line-separated blocks)]]/[[— Jump to next/previous code section (filetype-dependent)]}/[{— Jump to end/start of current{}block%— Jump between matching pairs{},(),[]<C-d>/<C-u>— Half-page down/up (faster than line-by-line)<C-o>/<C-i>— Move back/forward in jumplist
If you know the line number, go there directly: 44G jumps to line 44.
As a bonus for reaching the end of the post, here’s the :h holy-grail!