Skip to main content

Vim Motions and Operators

·981 words·5 mins
Linux Learning Lab
Author
Linux Learning Lab
Writing about code, tools, and workflows.
vim-essentials - This article is part of a series.
Part 2: This Article

The Vim Grammar
#

Vim commands follow a consistent grammar:

[count] operator [count] motion/text-object

Once you learn a few operators and a few motions, you can combine them freely. This is what makes Vim scale — you’re not memorizing hundreds of commands, you’re learning a small set of composable pieces.

Operators
#

Operators are the “verbs” — what you want to do to the text:

OperatorAction
dDelete
cChange (delete and enter Insert mode)
yYank (copy)
>Indent right
<Indent left
=Auto-indent
gUUppercase
guLowercase

An operator on its own does nothing. It waits for a motion or text object to tell it what to act on.

Motions
#

Motions are the “nouns” — they define the range of text:

MotionRange
wForward to start of next word
bBack to start of word
eForward to end of word
$To end of line
0To beginning of line
^To first non-blank character
ggTo top of file
GTo bottom of file
f{char}Forward to next {char} on current line
t{char}Forward to just before next {char}
}To next blank line (paragraph)
{To previous blank line

Combining Operators and Motions
#

The power is in the combination:

CommandRead asResult
dwdelete wordDeletes from cursor to start of next word
d$delete to end of lineDeletes from cursor to end of line
d0delete to beginningDeletes from cursor to beginning of line
dGdelete to bottomDeletes from cursor to end of file
cwchange wordDeletes word, enters Insert mode
c$change to end of lineDeletes to end of line, enters Insert mode
y3wyank 3 wordsCopies the next 3 words
>}indent to next paragraphIndents all lines until next blank line
gUwuppercase wordUppercases the current word

Every new operator you learn works with every motion you already know.

Text Objects
#

Text objects define structured regions of text. They always start with i (inner — excluding delimiters) or a (around — including delimiters):

Text ObjectSelects
iwInner word (the word itself)
awA word (word plus surrounding space)
i"Inside double quotes
a"Around double quotes (includes the quotes)
i'Inside single quotes
i( or ibInside parentheses
a( or abAround parentheses
i{ or iBInside curly braces
a{ or aBAround curly braces
i[Inside square brackets
i<Inside angle brackets
itInside HTML/XML tag
atAround HTML/XML tag
ipInner paragraph
apA paragraph (includes trailing blank line)
isInner sentence

Text objects in action
#

CommandResult
ciwChange inner word (delete word, enter Insert mode)
ci"Change inside quotes (delete quoted content, stay in quotes)
da(Delete around parentheses (content + the parens)
yi{Yank inside curly braces
vatVisually select around HTML tag
>ipIndent inner paragraph
gUiwUppercase inner word

Why text objects matter
#

With motions, your cursor position matters. With text objects, you can be anywhere inside the target and it still works:

# Cursor is on the 'e' in "hello"
ci"    →  deletes "hello" and puts you in insert mode between the quotes

# Works regardless of where your cursor is inside the quotes

Counts (Multipliers)
#

Prefix any operator+motion with a number to repeat it:

CommandResult
3dwDelete 3 words
5ddDelete 5 lines
2yyYank 2 lines
4jMove down 4 lines
3>}Indent 3 paragraphs
10iabc EscInsert “abc " 10 times

Counts also work with d + count + motion:

d3w    (delete 3 words)
3dw    (same thing — delete word, 3 times)

The Dot Command
#

The . command repeats your last change. It’s the single most powerful efficiency tool in Vim.

# Change a word to "server"
ciw server Esc

# Move to another word you want to change the same way
w w w

# Repeat the change
.

The dot command works with any operator+motion or text object combination:

# Delete inside parentheses
di(

# Find the next set of parens and repeat
f(
.

Doubling an Operator
#

Doubling an operator applies it to the entire current line:

CommandResult
ddDelete line
ccChange line (delete and enter Insert mode)
yyYank line
>>Indent line
<<Unindent line
==Auto-indent line
gUUUppercase entire line

f and t — Line-Level Precision
#

f (find) and t (till) jump to a character on the current line:

CommandMovement
f;Jump to next ;
F;Jump to previous ;
t;Jump to just before next ;
T;Jump to just after previous ;
;Repeat last f/F/t/T forward
,Repeat last f/F/t/T backward

Combined with operators:

# Delete up to and including the next comma
df,

# Change everything up to (but not including) the closing paren
ct)

# Delete from cursor to the next equals sign
dt=

Practical Examples
#

Rename a variable
#

# Cursor on the variable name
ciw newName Esc

# Find next occurrence and repeat
n .
n .

Wrap content in parentheses
#

# Select the text
viw

# Delete into register, type replacement
c(Ctrl-r ")Esc

Reindent an entire function body
#

# Cursor inside the function
vi{=

Delete a function’s parameters
#

# Cursor anywhere inside the parens
di(

Change an HTML attribute value
#

# Cursor anywhere inside the quotes of class="old-value"
ci"new-value Esc

Best Practices
#

  • Think in terms of operator + text object rather than character-by-character edits
  • Learn ci and di combinations first — they cover most editing needs
  • Use f and t for precise jumps on the current line instead of repeatedly pressing w or l
  • Let the dot command do the repetition — make one good edit, then . your way through
  • When an edit feels tedious, you’re probably not using the right text object — pause and think about what you’re actually trying to select
vim-essentials - This article is part of a series.
Part 2: This Article