Operators and Combinations
Operators are the verbs of Vim's editing language. Combined with motions and text objects, they create an almost infinite vocabulary for editing.
Every operator works with every motion and every text object. Learning one new operator or motion multiplies your vocabulary. Learning both multiplies it again.
Learning Path
This chapter is both a lesson and a reference. Work through the six steps below first; treat the long command tables as lookup material, not something to memorize.
| Step | Focus | Commands | Section |
|---|---|---|---|
| 1 | Core operators + the operator/motion pattern | d, c, y, > | Core Operators |
| 2 | Essential motions | w, e, $, 0, j, k, f, t | Essential Motions |
| 3 | Operator + text objects | diw, ciw, yi", da( | Operator + Text Object |
| 4 | Counts and line-wise behavior | 3dd, d3w, line-wise vs char-wise | Counts |
| 5 | Registers and repeating | p, "0p, "add, ., u | Registers |
| 6 | Advanced reference | gq, g@, !, search motions | Advanced Reference |
The sections below are organized by operator (d, c, y) and are exhaustive. You do not need to read every row to learn the editor. Learn the {operator} {motion} pattern first, then look up specific combinations when you need them.
Core Operators
Start with the four essential operators you will use daily.
d — Delete
d is the delete operator. It removes text and stores it in a register for pasting.
d{motion} → delete from cursor to the motion target
dd → delete current line (line-wise)
D → delete from cursor to end of line (= d$)
x → delete character under cursor (= dl)
X → delete character before cursor (= dh)
dd and not just d?d must be completed by a target. dd is d (operator) + d (a line-wise motion meaning "current line"). The same logic gives you dw, d$, dip, and every other combination below.
c — Change
c is the change operator: it deletes the target and drops you into Insert mode. It is the workhorse for editing existing text.
c{motion} → delete the motion and enter Insert mode
cc → change the whole line (= S)
C → change from cursor to end of line (= c$)
s → change character under cursor (= cl)
S → change whole line (= cc)
cw behaves like cecw does not eat the trailing space. When the cursor is on a word it changes only to the word's end (same as ce), so cw on foo in foo bar leaves the space intact. Use cW to change a whole WORD.
y — Yank (Copy)
y is the yank operator. Unlike d and c, it never modifies the buffer — it only stores text in a register for pasting.
y{motion} → yank from cursor to the motion target
yy → yank current line (line-wise)
Y → yank from cursor to end of line (= y$)
> and < — Indent
>> → indent current line
<< → un-indent current line
>3j → indent current + next 3 lines
<} → un-indent to end of paragraph
>aB → indent around brace block
In Visual mode, repeat indentation with gv + >:
Vjj> → select 3 lines, indent
gv> → re-select, indent again
Other Operators
| Operator | Action | Doubled |
|---|---|---|
= | Auto-indent | == — auto-indent line |
~ | Toggle case | — |
g~ | Toggle case (motion) | g~~ — toggle line |
gU | Uppercase | gUU — uppercase line |
gu | Lowercase | guu — lowercase line |
gq | Format/wrap text | gqq — format line |
Essential Motions
These motions work with every operator. Learn them first.
Line Motions
0 → column 0 (line start)
^ → first non-blank character
$ → end of line
Word Motions
w → start of next word
W → start of next WORD
b → start of previous word
e → end of current/next word
E → end of current/next WORD
Character-Search Motions
f{char} → jump to next {char} on the line
F{char} → jump to previous {char} on the line
t{char} → jump to just before next {char}
T{char} → jump to just after previous {char}
; → repeat last f/F/t/T forward
, → repeat last f/F/t/T backward
Paragraph and Sentence Motions
{ → previous paragraph
} → next paragraph
( → previous sentence
) → next sentence
File Motions
gg → start of file
G → end of file
{N}G → jump to line N
d{N}G vs dG vs dggG is a line-wise motion (go to line), so an operator combined with it removes whole lines:
dG— delete from the current line to the last line of the file.dgg— delete from the current line to the first line of the file.d3G— delete from the current line to line 3.
Because the motion is line-wise, the deleted text pastes as complete lines, not inline characters.
Operator + Motion = Action
Combine any operator with any motion:
d$ → delete to end of line
c3w → change 3 words
>G → indent from here to end of file
=gg → auto-indent from here to file start
gU$ → uppercase to end of line
gu3j → lowercase 3 lines down
Read the ruler — the ^ marks the span the operator acts on (the cursor starts on the first character):
hello world again
^^^^^^
dw → deletes "hello " (the motion crosses the space)
hello world again
^^^^^
de → deletes "hello" (stops at the word end)
hello world again
^^^^^^^^^^^^^^^^^
d$ → deletes to the end of the line
y{ vs. yapy{ is a motion-based yank: it yanks from the cursor to the previous paragraph boundary. The result depends on where the cursor is — it does not guarantee a whole-paragraph selection.
yap is a text-object yank: it always selects the entire paragraph the cursor is in, regardless of cursor position.
Paragraph A here.
More text.
Paragraph B here.
^ cursor
y{ → yanks from cursor back to Paragraph A (partial, cursor-dependent)
yap → yanks all of Paragraph B (always the whole paragraph)
Prefer yap / dip / cip when you want to act on a whole paragraph. Use y{ / d{ / c{ only when you intentionally want a cursor-dependent partial selection.
Operator + Text Object = Precise Action
Text objects are nouns that describe chunks of text. Combine them with operators for precise, position-independent editing.
{operator} {i|a} {text-object}
i = "inner" (without surrounding whitespace/delimiters)
a = "around" (includes surrounding whitespace/delimiters)
Common Text Object Combinations
diw → delete inner word
cis → change inner sentence
yap → yank around paragraph
=iB → auto-indent inner brace block
gUiw → uppercase inner word
>ip → indent inner paragraph
The d Operator with Text Objects
diw / daw → delete inner word / around word (daw eats trailing space)
diW / daW → delete inner / around WORD
dis / das → delete inner / around sentence
dip / dap → delete inner / around paragraph
di" / da" → delete inside / around double quotes
di' / da' → delete inside / around single quotes
di` / da` → delete inside / around backticks
di( di[ di{ di< → delete inside any bracket pair
dib / dab → delete inside / around parentheses block
diB / daB → delete inside / around curly-brace block
dit / dat → delete inside / around HTML/XML tag
The c Operator with Text Objects
ciw / caw → change inner word / around word
ciW / caW → change inner / around WORD
cis / cas → change inner / around sentence
cip / cap → change inner / around paragraph
ci" / ca" → change inside / around double quotes
ci' / ca' → change inside / around single quotes
ci` / ca` → change inside / around backticks
ci( ci[ ci{ ci< → change inside any bracket pair
cib / cab → change inside / around parentheses block
ciB / caB → change inside / around curly-brace block
cit / cat → change inside / around HTML/XML tag
The y Operator with Text Objects
yiw / yaw → yank inner word / around word
yiW / yaW → yank inner / around WORD
yis / yas → yank inner / around sentence
yip / yap → yank inner / around paragraph
yi" / ya" → yank inside / around double quotes
yi' / ya' → yank inside / around single quotes
yi` / ya` → yank inside / around backticks
yi( yi[ yi{ yi< → yank inside any bracket pair
yib / yab → yank inside / around parentheses block
yiB / yaB → yank inside / around curly-brace block
yit / yat → yank inside / around HTML/XML tag
Counts
Counts modify how many times an operator or motion repeats. They follow specific rules:
- Operator count × Motion count = total repetitions.
- Text objects use the count differently than motions.
Basic Count Examples
3dd → delete 3 lines (operator count)
d3w → delete 3 words (motion count)
d2j → delete current line + 2 lines down (motion count)
Count Multiplication
When an operator and its motion both take counts, the counts multiply (see :help count):
3d2w → delete 6 words (3 × 2 = 6)
2c3e → change 6 character targets (2 × 3 = 6)
- Motions:
d3wdeletes 3 words. The count applies to the motion. - Text objects:
d2iwdeletes 2 inner words. The count selects multiple objects, not a multiplied span. - Line-wise:
3dddeletes 3 lines. The doubled operator accepts the count directly.
Do not assume every combination follows one universal rule. Test unfamiliar combinations.
Registers — Where Deleted/Yanked Text Goes
d and c cut text (store in a register). y yanks text (copies to a register). All three store text you can paste later.
The Unnamed Register
dd → delete line into the unnamed register (paste with p)
yy → yank line into the unnamed register (paste with p)
Named Registers
"add → delete into register a
"ayy → yank into register a
"aP → paste from register a
Special Registers
"_dd → delete into black-hole register (discarded, not stored)
"+dd → delete into system clipboard
"*dd → delete into primary selection (X11)
"0 → yank register (always holds the last yank)
"0 RegisterBecause "0 always keeps the last yank, you can delete freely and still paste what you copied earlier with "0p. Deletes shift the numbered registers "1–"9; they don't touch "0.
Register Summary
| Register | Purpose |
|---|---|
"" | Unnamed (default for d/c/y) |
"0–"9 | Numbered (yank history, delete history) |
"a–"z | Named (user-defined) |
"_ | Black hole (discard) |
"+ | System clipboard |
"* | Primary selection (X11) |
Line-wise vs Character-wise
This matters for how deleted text pastes back:
dd, dj, dk, dG, dgg → line-wise (whole lines)
d$, dw, df, dt, diw, d_ → character-wise (inline fragments)
- Line-wise deletes paste as new lines (
popens a line). - Character-wise deletes paste inline at the cursor.
d_ is Not the Same as dd
_ is a motion that moves to the first non-blank character of a line. Combined with d, it deletes from the cursor to the first non-blank character on the current line. It is not equivalent to dd (which deletes the entire line).
d_ → delete from cursor to first non-blank char on the line
dd → delete the entire line (line-wise)
Visual Mode Delete
v{motion}d → delete the character-wise selection
Vjd → delete the selected lines
Ctrl+v ... d → delete a rectangular block/column
Repeat and Undo
. → repeat the last change (delete, change, etc.)
u → undo the last change
Ctrl+r → redo
The Dot Command — Repeat Last Change
. repeats the entire last change (operator + motion):
ciw "new" → change inner word to "new"
w → move to next word
. → apply the same change ("new") to next word
* → find next occurrence of word under cursor
. → apply last change to it
The dot command is most powerful when combined with / search or * word search.
Practical Combination Patterns
| Goal | Command | Explanation |
|---|---|---|
| Remove a function argument | da, or di, | Delete around/inner comma-separated arg |
| Uppercase a variable name | gUiw | Uppercase inner word |
| Replace a string value | ci" + type | Change inside double quotes |
| Swap function body | yiB then p | Yank inner braces, paste elsewhere |
| Format an entire file | gg=G | Top → auto-indent all |
| Remove HTML tag content | cit | Change inner tag |
| Delete to search match | d/foo | Delete up to "foo" |
| Indent a function | =aB | Auto-indent around braces |
Operator Mastery Checklist
Before moving on to Advanced Motions, you should be able to do these without looking at the cheat sheet:
- Delete the word under the cursor using
diw - Change the word under the cursor using
ciw - Yank a quoted string's contents using
yi" - Delete the current line using
dd - Indent the current line using
>> - Repeat a previous change using
. - Paste a previously yanked value using
"0p
If any of these still need thought, redo the matching drill in practice-folder/nvim/03-text-objects-and-motions/operators-combinations-practice.md before continuing.
Advanced Reference
These operators and combinations are useful but optional. Come back to them once the checklist above feels natural.
The = Auto-Indent Operator
== → auto-indent current line
=G → auto-indent from cursor to end of file
=gg → auto-indent entire file
=aB → auto-indent around brace block (function)
=ip → auto-indent inner paragraph
gg=G → auto-indent the ENTIRE file (most common use)
gg=G is one of the most useful commands: go to the top of the file and auto-indent everything. Use it after pasting code with broken indentation.
The gU / gu Case Operators
gUiw → uppercase inner word
guiw → lowercase inner word
gU$ → uppercase to end of line
guu → lowercase current line
gUU → uppercase current line
~ → toggle case of character under cursor
g~~ → toggle case of entire line
The gq Format Operator
gq reformats text to the current textwidth (comment leaders are preserved):
gq{motion} → format the given motion's lines
gqq → format the current line
gqip → format inner paragraph (great for Markdown)
gq} / gq{ → format up to next / previous paragraph
gggqG → format the whole file
The g@ Operator
g@ runs a custom operator function set with operatorfunc. It is the extension point used by many plugins — you rarely type it directly.
g@{motion} → call the function in 'operatorfunc' over {motion}
In Lua you would set it with vim.o.operatorfunc = 'v:lua.MyFunc'; in Vimscript, :set operatorfunc=MyFunc then g@. Example mapping:
function! NumberLines(type)
call s:number_lines(a:type)
endfunction
nnoremap <silent> <leader>n :set operatorfunc=NumberLines<CR>g@
If you are not writing a plugin, you can skip g@ entirely. See :help g@ and :help operatorfunc.
Search Motions With Operators
Search works as a motion for every operator (d/foo deletes up to the next foo). This is powerful but easy to get wrong because the span depends on the search direction and cursor position.
d/pattern → delete from cursor up to the next match
c/pattern → change up to the next match
y/pattern → yank up to the next match
d?pattern → same, searching backward
Combine with n / N and the dot command for repetitive edits: d/foo then n. removes successive matches. Prefer text objects (ci", dap) when the target is structured — they are less fragile than search-based spans.
External Filtering with !
The ! operator pipes a motion or text object through a shell command and replaces the text with the command's output. The ! is an operator like d or c — it waits for a target, then opens the command line where you type the shell command and confirm it with Enter.
Before (cursor anywhere in the paragraph):
apple
cherry
banana
Steps to sort it:
- Press
!— Neovim enters operator-pending mode. - Press
ip— the inner-paragraph text object. - At the
:!prompt, typesort. - Press
Enter.
Result:
apple
banana
cherry
!ip sort{Enter} → sort the inner paragraph alphabetically
!ip sort -r{Enter} → sort in reverse
!ap column -t{Enter} → format the paragraph as columns
!ip sort is not a single sequence you type literally. After !ip, Neovim shows a :! prompt; sort is typed there, then confirmed with Enter. The text you operate on is piped to the command via stdin.
Nested Count Examples
Some combinations surprise people. Test unfamiliar ones before relying on them:
d2iw → delete 2 inner words (count applies to the text object)
d2j → delete current line + 2 lines down (count applies to the motion)
3d2w → delete 6 words (counts multiply: 3 × 2)
In LazyVim
Operators and combinations form the grammar of Vim (e.g., d + iw = diw). LazyVim fully supports this grammar.
Because LazyVim includes mini.ai, you gain more "nouns" (text objects) to combine with your "verbs" (operators). For instance, d in (delete inside next...) is made powerful out of the box.
| Aspect | Vanilla Neovim | LazyVim |
|---|---|---|
| Verbs (Operators) | c, d, y, v | Same |
| Nouns (Text Objects) | w, p, s | Expanded greatly by mini.ai |
LazyVim Key Mappings
LazyVim configs can map keys through plugins, and mappings vary between versions and setups. The s key, for example, is commonly mapped to flash.nvim, but do not assume every installation is identical.
To inspect where a normal-mode mapping comes from in your config:
:verbose nmap s
This shows the mapping's target and the file that defined it.