Editing Like Magic With Vim Operators
Motions aren’t just for moving. They can be used in combination with a series of commands called operators to edit your code at the speed of lightning.
You can use operators and motions together by following any of these patterns:
{operator}{count}{motion}
{count}{operator}{motion}
- The operator determines which action you want to perform: deleting, changing, yanking, formatting, etc.
- The count allows you to multiply the effect of an operator by performing an action a count number of times.
- The motion represents the piece of text to which to apply the action defined by the operator.
For instance, the d2w
combination allows you to delete two words almost.
d
corresponds to the delete operator. Since d
is an operator, you can follow the {operator}{count}{motion}
formula and combine it with all the motions you’ve learned thus far:
- Use
d5j
to delete 5 lines downwards - Type
df'
to delete everything in the current line from the cursor until the first occurrence of the'
character (including the character itself) - Or type
dt'
to do like the above example but excluding the character (so up until or just before the'
character) - Use
d/hello
to delete everything until the first occurrence ofhello
- Type
ggdG
to delete a complete document
Useful Operators
In addition to d
, there’s a handful more of handy operators:
c
(change): Change deletes a piece of text and then sends you into Insert mode so that you can continue typing, changing the original text into something else. The change operator is like thed
andi
commands combined into onetwo. This duality makes it the most useful operatory
(yank): Copy in Vim jargonp
(put): Paste in Vim jargong~
(switch case): Changes letters from lowercase to uppercase and back. Alternatively, usegu
to make something lowercase andgU
to make something uppercase>
(shift right): Adds indentation<
(shift left): Removes indentation=
(format code): Formats code
You can use these operators much like you used delete so that:
c/hello
changes everything until the first occurrence ofhello
.ggyG
copies a whole documentgUw
capitalizes a word
Operator Shorthand Syntax
All these operators provide additional shorthand syntax aimed at saving you typing and increasing your speed with common editing tasks:
- Double an operator to make it operate on a whole line:
dd
deletes a whole line,cc
changes a whole line, etc. - Capitalize an operator to have it perform a stronger (or alternate) version of its default behavior:
D
deletes from the cursor to the end of the line,C
changes to the end of a line,Y
likeyy
copies a complete line,P
pastes something before the cursor, etc.
Operators really shine when we combine them with a special class of motions called text-objects.
Taking Editing Up a Notch With Text Objects
Text objects are structured pieces of text or, if you will, the entities of a document domain model. What is a document composed of? Words, sentences, quoted text, paragraphs, blocks, (HTML) tags, etc. These are text objects.
The way that you specify a text object within a command is by combining the letter a
(a text object plus whitespace) or i
(inner object without whitespace) with a character that represents a text object itself:
{operator}{a|i}{text-object}
The built-in text-objects are:
w
for words
for sentence'
,"
,`
for quotesp
for paragraphb
(or(
,)
) for block surrounded by()
,B
(or{
,}
) for block surrounded by{}
<
,>
for a block surrounded by<>
[
,]
for a block surrounded by[]
t
for tag.
So in order to delete different bits of text you could any of the following commands:
daw
to delete a word (plus trailing whitespace)ciw
to change inner worddas
to delete a sentence (dis
to delete inner sentence)da"
to delete something in double quotes including the quotes themselves (di"
deletes only the content inside the quotes and spares the quotes)ci"
to change something inside double quotesdap
to delete a paragraphdab
da(
orda)
to delete a block surrounded by(
daB
da{
orda}
to delete a block surrounded by{
dat
to delete an HTML tagcit
to change the contents of an HTML tag
Combining text objects with operators is extremely powerful and you’ll find yourself relying on them very frequently. Stuff like cit
, ci"
and cib
is just brilliant.
Let’s say that we want to change the contents of this string below for something else:
const salute = 'I salute you oh Mighty Warrior'
You type ci'Hi!<ESC>
and it becomes:
const salute = 'Hi!'
Just like that. You don’t need to go grab the mouse, select the text and then write something else. You type three letters and Boom! You’re done.
Repeating The Last Change with The Dot Operator
Vim has yet another trick in store for you aimed at saving more keystrokes: The magic .
(dot) command.
The .
command allows you to repeat the last change you made. Imagine that you run dd
to delete a line of code. And now let’s say that you’ve warmed up to removing code. Removing code is good, the less code you have the less code you need to maintain. So let’s remove another line of code. How would you go about that? You could type dd
again but, even better, you could use the .
command which is just a single keystroke.
OK. You save one keystroke. So What. (Tough crowd here I see). Well, you can use the .
command to repeat any type of change, not just a single shorthand command like dd
. For instance, you could change a word for Awesome
like so cawAwesome<Enter>
, and then repeat that whole command with all those keystrokes by just typing a single dot. Think of the possibilities!
The .
command becomes even more useful if you get in the habit of using Text-objects. Text-objects are more reliable than other motions because you don’t need to care as much where the cursor is positioned. Thus, commands with text objects are far more repeatable and therefore work beautifully in tandem with the .
command.
The .
command works great in combination with the repeat search commands (;
, ,
, n
or N
). Imagine that you want to delete all occurrences of cucumber
. A possible approach would be to search for cucumber /cucumber
, delete it with daw
and, from then on, use n
to go to the next match and .
to delete it! Two keystrokes!?! Again think of the possibilities!!
More Shorthand Text Editing Commands
In addition to the operators you’ve learned in this chapter, Vim offers a series of shortcuts to operate on single characters that can be useful on occasion. They are:
x
is equivalent todl
and deletes the character under the cursorX
is equivalent todh
and deletes the character before the cursors
is equivalent toch
, deletes the character under the cursor and puts you into Insert mode~
to switch case for a single character
As usual, all of the above support counts to operate on multiple characters at once.
Undoing and Redoing
Sooner or later it will come a time when you will make a mistake. Admit it! You ain’t perfect. Nobody is. And that is alright. You needn’t worry though, because Vim has your back:
- Type
u
and you’ll undo your last change, - Type
CTRL-R
and you’ll redo it,
Pheeewww…
Summary
Motions aren’t just for moving. Used in combination with operators they let you perform operations on text with ease and amazing speed. You apply an operator on a motion by using the key melody {operator}{motion}
.
Some of the most useful and common operators are: d
for delete, c
for change, y
for yank (copy) and p
for put (paste). As you can appreciate from these operators and the motions you’ve learned thus far, Vim commands are generally easy to learn because they make sense and are easy to guess.
When you double an operator you make it operate on a line. For instance, you can use dd
to delete a complete line. In a similar fashion, when you capitalize a command it performs a stronger (or alternate) version of the original command. For example, D
deletes from the cursor to the end of a line. These are really helpful and can save you a lot of time. Learn to use them instead of their more wordy alternatives.
Counts also work with operators. You can multiply the effect of an operator motion combo by using a count like this: {operator}{count}{motion}
.
Text objects are special motions that describe the parts of a document: words, sentences, paragraphs, and such. They are incredibly useful in combination with Vim operators. Using operators with text-objects you can be very precise and command Vim to delete a word, or change the insides of a string or code block.
Text objects offers two variants: the a
(think a or all) and i
(think inner) that allow you to operate on a text object plus surrounding whitespace or only on the inner parts of a text object respectively. For example, using da"
deletes a complete quote including trailing whitespace, using di"
only deletes whatever is surrounded by quotes.
The dot command .
lets you repeat the last change and, as such, it is one of the most useful repeater commands. Operations on text-objects are great candidates for the dot operator because they are more repeatable.
A great way to take advantage of the dot command is by using it in combination with searches. When you do that you can apply changes of successive searches with just two keystrokes: n
or ;
to find the next match and .
to repeat the last change.
Sometimes you’ll make a mistake. When that happens, you can undo the last change with the u
command. If you change your mind or undo too far, type CTRL-R
to redo.
Written by Jaime González García , dad, husband, software engineer, ux designer, amateur pixel artist, tinkerer and master of the arcane arts. You can also find him on Twitter jabbering about random stuff.