Skip to main content

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.

Core Idea

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.

StepFocusCommandsSection
1Core operators + the operator/motion patternd, c, y, >Core Operators
2Essential motionsw, e, $, 0, j, k, f, tEssential Motions
3Operator + text objectsdiw, ciw, yi", da(Operator + Text Object
4Counts and line-wise behavior3dd, d3w, line-wise vs char-wiseCounts
5Registers and repeatingp, "0p, "add, ., uRegisters
6Advanced referencegq, g@, !, search motionsAdvanced Reference
How to use the reference tables

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)
Why 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 ce

cw 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
Visual Mode Indent

In Visual mode, repeat indentation with gv + >:

Vjj> → select 3 lines, indent
gv> → re-select, indent again

Other Operators​

OperatorActionDoubled
=Auto-indent== — auto-indent line
~Toggle case—
g~Toggle case (motion)g~~ — toggle line
gUUppercasegUU — uppercase line
guLowercaseguu — lowercase line
gqFormat/wrap textgqq — 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 dgg

G 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
Motion vs. Text Object: y{ vs. yap

y{ 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)
Count Behavior Varies
  • Motions: d3w deletes 3 words. The count applies to the motion.
  • Text objects: d2iw deletes 2 inner words. The count selects multiple objects, not a multiplied span.
  • Line-wise: 3dd deletes 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)
The "0 Register

Because "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​

RegisterPurpose
""Unnamed (default for d/c/y)
"0–"9Numbered (yank history, delete history)
"a–"zNamed (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 (p opens 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​

GoalCommandExplanation
Remove a function argumentda, or di,Delete around/inner comma-separated arg
Uppercase a variable namegUiwUppercase inner word
Replace a string valueci" + typeChange inside double quotes
Swap function bodyyiB then pYank inner braces, paste elsewhere
Format an entire filegg=GTop → auto-indent all
Remove HTML tag contentcitChange inner tag
Delete to search matchd/fooDelete up to "foo"
Indent a function=aBAuto-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)
tip

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
tip

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:

  1. Press ! — Neovim enters operator-pending mode.
  2. Press ip — the inner-paragraph text object.
  3. At the :! prompt, type sort.
  4. 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
warning

!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​

LazyVim Context

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.

AspectVanilla NeovimLazyVim
Verbs (Operators)c, d, y, vSame
Nouns (Text Objects)w, p, sExpanded greatly by mini.ai

LazyVim Key Mappings​

Check Your 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.


What's Next​