Learn Practice Daily golf Reference
The Vim Way·Lesson 5 of 7·6 min·0/7 exercises

Act, repeat, reverse

; and n each have a partner that goes back the other way, , and N, so overshoot freely. A change doesn't travel; u takes it back.

Scene

4:45 p.m. On your way to the order form you search for qty, press n, n, n, and sail one past the line you wanted. Going all the way round the file again would take a dozen presses.

Remember the remote from day one? Look closer: the buttons come in pairs.

From memory

Warm-up from earlier chapters

Two from earlier chapters, from memory, before the new idea. Two wrong tries show the answer.

Search for the word under the cursor.
press the keys…
1 of 2
Search for the word under the cursor.

Every button has a partner

On a remote, next to the button that skips forward sits one that skips back. Vim's travel keys work the same way: ; and n each have a partner that goes the other way. So repeat freely. If you go one too far, one press of the partner brings you back.

You want toActRepeatReverse
find a character on the linef t F T;,
find the word under the cursor* #nN

The comma skips back

You met the first pair on day two: ; skips on to the next copy of the character you found, in the same direction, and , skips back the other way. Overshot by one comma? ,, and you're there.

1notify(user.phone, order.id, rider.name, eta, "on its way");
NORMALLoading the editor…1:1
Check yourself

One too far

1fn(a, b, c, d, e)
NORMAL
Keys pressed: f,;;;,

You wanted the comma after c. You pressed f,, then ; three times: one too many. Now you press ,. Where are you?

Pick an answer (or press its number), then watch the engine prove it.
Try it

Back one

Targets on the line, some just behind where your last find left you. When the target is one copy back, , is the cheapest way there.

1 of 6Move the cursor onto the
1notify(user.phone, order.id, rider.name, eta, "on its way");
1assign(order, nearest, { rush: true }, eta, "bike");
NORMALLoading the editor…1/60.0s1:1

This exercise needs a keyboard. Read on, and play it at your computer.

n and N

The search buttons pair up the same way. n repeats your last search in the same direction and N goes the other way: after * that's down and up the file, after # it flips. So after a * that went one too far, the order form is one N away.

1const qty = item.qty;
1const total = item.price * qty;
2log("qty", qty);
NORMALLoading the editor…1:7
Try it

Both directions

Each target is a word you can line up with * or #. Then n and N skip forward and back through its copies.

1 of 6Move the cursor onto the
1export async function placeOrder(cart: Cart, user: User) {
1 const total = cart.items.reduce((sum, i) => sum + i.price, 0);
2 const discount = user.isStudent ? total * 0.1 : 0;
3 const order = await db.orders.insert({ userId: user.id, total, discount });
4 await notify(user.phone, "Your burrito is on its way!");
5 return order.id;
6}
NORMALLoading the editor…1/60.0s1:1

This exercise needs a keyboard. Read on, and play it at your computer.

Changes don't travel

Changes are different. . doesn't go anywhere: it makes the change again where you stand, so there's no other way to press. What a change has is a way back: u takes the last one off, as it did with this morning's wrong stamp. Stamped one copy too many? u, then let n carry you past it. The next lesson looks at undo properly.

Try it

One stamp too many

The order form is renaming cnt to count, but the kitchen's note quotes cnt and has to stay as written. Your last n . wrapped round to the top and stamped the quote. Take that stamp back, then fix the copy that's left.

1 of 2The last stamp landed in the kitchen's quote. Take it back.
1// kitchen: "count on the ticket means plates" (quote it exactly)
1export function orderForm(cnt: number) {
2 const plates = count ?? 1;
3 return { plates, count };
4}
NORMALLoading the editor…1/20.0s1:18

This exercise needs a keyboard. Read on, and play it at your computer.

From memory

Find the partner

Read the situation, press the key.

One comma too far. Back to the previous one.
scroll here, then press the keys
1 of 4
One comma too far. Back to the previous one.
Challenge

Overshoot recovery

Twelve stops across the order code. Finds, searches, and their partners: whichever reaches each stop in the fewest keys, forwards or back.

1 of 12Move the cursor onto the
1const MAX_DISTANCE_KM = 8;
1const riders = await loadRiders({ online: true });
2const nearest = riders.sort((a, b) => a.distance - b.distance)[0];
3if (!nearest || nearest.distance > MAX_DISTANCE_KM) {
4 return refund(order, "No rider nearby, sorry!");
5}
6assign(order, nearest);
7log("assigned", order.id, nearest.name);
NORMALLoading the editor…1/120.0s1:1

This exercise needs a keyboard. Read on, and play it at your computer.

Extra practice optional

The chapter is done. These rounds keep going as long as you like: stop whenever it stops being useful.

Endless

Both ways, forever

Endless stops. Forward or back, find or search: pick the pair that gets there first.

Level 1Move the cursor onto the
1const MAX_DISTANCE_KM = 8;
1const riders = await loadRiders({ online: true });
2const nearest = riders.sort((a, b) => a.distance - b.distance)[0];
3if (!nearest || nearest.distance > MAX_DISTANCE_KM) {
4 return refund(order, "No rider nearby, sorry!");
5}
6assign(order, nearest);
7log("assigned", order.id, nearest.name);
NORMALLoading the editor…lv 1 · 0 done0.0s1:1

This exercise needs a keyboard. Read on, and play it at your computer.