This is part two of a four part series. To see all the articles, click
here.

TL;DR: Vim is controlled by expressions that take the form of operator +
motion. Learning operators and motions gives flexible power to concisely edit
text in a repeatable fashion.

Last week we touched on the
idea of buffers, and some basic commands like :e, :ls, and :b that let us
open and manipulate buffers. This week, we are going to talk a little bit about
the heart of vim… editing.

Vim is designed for efficient and repeatable editing. It understands that as
you work with a document, much of your time is spent finding just the right
place to make a change, making that change, then repeating that same sort of
change in a few more places.

Vim is unusual because its commands for a sort of language. Nearly every change
you make is a repeatable algorithm that can be re-used! This “language” usually
takes the form of an
Operator followed
by a Motion.

Operators and Motions are orthogonal… if you learn a new motion, it will work
with all the operators you know, and vice versa. Listing all the operators and
motions is the job of the :help system. Instead, I’m going to list some of my
favorite combinations so that you can maybe see the power that Vim has. There
is often more than one way to do the same task, you can use the tools within
Vim that you know.

There are man pages for listing all the operators and motions available in vim,
and more operators and motions available in plugins. Rather than try to list
all of them I will group a sampling of them by the steps in a typical editing
cycle: First scanning for the right place to change, then placing the cursor in
the correct spot, finally changing or adjusting the text.

Scanning

Before you can fix the problem, you have to see it. Usually this will mean
scrolling the current window up and down the buffer as you read, or by
searching for a pattern that you know is close to the problem.

Scrolling

Scanning using <c-d> and <c-u>.

There are a number of ways to move up and down the buffer. You can use
:<line-number> to jump to a specific line (if you know where you are
going!). G jumps to the bottom of the file (good for appending when you know
you will be adding to the bottom,) and gg jumps to the top. There are a
number of other jump style motions under the prefix of g, so it’s good to
remember that g = “go.”

If I know where I’m going (I have a backtrace with a line number) I’ll use
:<number>, otherwise I typically end up using <c-d> for “down” and <c-u>
for “up”.

Searching

/Layer (no matches)

/layer (some matches)

n and N to move back and forth

You can search at any time in normal mode by typing / followed by a pattern
you are searching for. There are of course regexes and wildcards available to
you. Once you are searching, you can press n for next to cycle through the
matches, and N will cycle you in the reverse direction.

Searching has the added benefit of placing the cursor on the match, which makes
also an excellent tool for the next phase.

Placing the cursor

The next step after scanning is to place your cursor where you want to make
your changes. This step and the actual editing itself are probably the hardest
things for people new to vim, so stay with it! Eventually it will feel natural.

2j to move down two rows

fI to move to the “I”

cw to “change word”… more on that later!

I will often just use a / search to place the cursor. This works well if
there’s a relatively unique string that you can match against, especially if I
can accomplish this in two characters or less.

If there isn’t an apparent or easy search pattern, I will use a combination of
row-wise and column-wise motions to get the same effect. For vertical
(row-wise) motion, I will either jump to a line or I’ll use the default motion
keys hjkl with a count, something like 11j or 7k.

For column-wise motion, we have many many options at our disposal, but there
are two that I end up using daily: f and t.

f is for “forward”, and both it and it’s corresponding reverse motion F
move the cursor directly on top of the next character pressed (called the
target)

t is for “till”, and it does the same thing as f, execept it stops just
short of the target. It also has a corresponding reverse motion, T.

With some practice, we should be right on our target and ready to edit!

A Note About Modal Editing

Vim gives us commands all across the keyboard to communicate commands to it.
However, we still have to type sometimes… so it gives us a toggle between two
modes: Normal (command) mode, and Insert mode. We’ll talk about a few ways to
enter Insert mode in a minute, but for now, just know that once in Insert
mode, you have to hit ESC or <c-c> return to Normal mode.

This is very confusing to some people but it’s worth getting used to. We have
been talking about the process of editing: scanning the text, placing the
cursor, making a change. Of those three steps, only one of them requires
inserting text, and then it doesn’t always. More often than not you are just
removing text, adjusting indentation, changing a delimiter… all tasks that in
Vim don’t require leaving Normal mode. Therefore, Vim takes the step of making
the mode in which we are instructing the editor what to do the default Normal
mode, and gives us an Insert mode to enter and leave when required.

Changing, Adjusting, and Adding

d stands for delete. It deletes in the motion you give it, if you just hit
dd it’ll delete the current line, and D will delete from the cursor to the
end of the line (roughly equivalent to d$, where $ is the movement to the
end of a line. Regex fans will notice that that’s the part of regex that
matches an end of line, and there’s more where that came from.)

There are a number of operators that will enter insert mode.

O
|
I--i_a--A
|
o

Here are the main ones I end up using. If the cursor is on the underscore, each
operator listed will move the cursor to the spot listed. o and O are
particularly notable, because they start new lines and place the cursor there.

f( to move to the parens

ci( to change inside parens

Type in correct “bar” argument

ESC to re-enter normal mode

A to put the cursor at the end of the line

Add “:”

The operator I find myself using the most frequently when refactoring or
editing is the c or change operator. This operator deletes according to your
motion, and places the cursor in the place of the removed text. C behaves
much the same as D, except leaving you in insert mode. I have found that
together with a solid use of text-objects, c probably my most-used operator.

Tweaking

Staying in normal mode is good, it means you have the freedom to keep moving
and you are constantly teaching yourself and your editor more things about the
text you are editing. There are a bunch of commands that I call “tweaking”
commands… they are little actions just to make simple tasks easier.

> and < are operators that indent and unindent code. = will auto-indent
based on your syntax file.

<c-a> and <c-x> increment and decrement the character under the cursor…
handy for budging a number or a range of numbers.

There are a bunch of neat extended commands available in plugins and scripts,
I’m fond of one that handles encoding and decoding strings, or escaping
characters. Combined with the text-object for quotes and single quotes, very
powerful!

Text Objects

This family of motions are motions, but they tend to make more sense in the
context of an operator. Vim is aware of ranges or blocks in your text… things
like parentheses, brackets, braces, quotes, double quotes, paragraphs,
sentences, even XML tags. I use these constantly!

They are pretty easy to use too… most text objects can be accessed by using
i<delimiter> or a<delimiter> where <delimiter> is something like ({['".
It is one of the easiest to read “sentence” commands… change inside
parentheses becomes ci(.

There are also motions to move the cursor along text-objects, which can be
handy for reading or working with prose.

Step 4. Profit! (with the power of repeat)

The amazing thing about the expressions we’ve been learning, the orthogonal
combinations of operators and motions is that they are scriptable and
repeatable. The way we interact with the editor is also the way we can
“program” Vim to do a task more than once!

I experienced this power in the course of writing this very blog post. I was
refactoring the examples and putting them inside the <figure> tags you see
here, and the <modifier-key> form was being interpreted as an XML tag and
breaking the blog post. Trouble is, I had written dozens of them across the
page.

I remembered seeing an operator that would HTML encode a string, found it in
:help, (the operator is [x from vim-unimpaired) and was able to use [xit
to HTML encode the string inside the tag.

Armed with this expression, I searched for “<c-” in the file, hit n to
move to it, and hit the repeat operator (.) to fix each occurence in the blog
post. It took mere seconds to do a refactoring activity that would have taken
me probably a half an hour a few years ago when I didn’t use vim.

Example: Numbering a list

There’s always more than one way to do a task in vim… people who have been
using vim for a while will engage in vim golf, a
contest to find the fewest keystrokes to accomplish a task. It’s partly a
competition, partly a way to absorb and learn new operators and motions.

Manually typing

Here I’m just typing in the list like I would when I first starting vim. I use
I to jump to the beginning of the line and typing in a number.

use hjkl to move the cursor

I to jump to the beginning of the line

type in the new number

repeat

Using an external command

Here I’m using a trick I learned from Steve Spicer… cat -n
prints out a file with line numbers. This trick is really cool because it works
on any length file with just one line!

%! passes the buffer to an external command and reads from
stdout

cat -n takes from stdin and numbers the lines

<c-v>starts a visual block so I can select the empty
space.

d to delete the selected block.

Using some new vim magic

While researching this talk, I learned that a familiar command extra
features. I knew that <c-a>learned that a familiar
command extra features. I knew that <c-a> will increment
the integer under the cursor, but I didn’t know that
g<c-a> would incremement a block of integers and
increment each one by one more.

Therefore I used a search and replace to put a “1.” at the beginning of
every line, and used g<c-a> to increment the line
numbers.

%s/^/1. /g replaces the beginning of every line in the
buffer with the string “1.”

<c-v> allows me to select a visual block from :2 on
to G

g<c-a> increments all the integers in the selection
by one + each additional line ending.