Learn Practice Daily golf Reference
Foundations·Lesson 4 of 6·9 min·0/8 exercises

Six ways into Insert mode

i a I A o O each start typing in a different place, so you rarely need to move first.

Scene

3:07 a.m. Your phone lights up the bedroom. The shiny new auto-formatter has run for the first time, taken one look at orders.ts, and eaten it. First letters: gone. Semicolons: gone. One comment now just says // TOD.

The build is red, the lunch rush starts at noon, and you're the only one awake who knows Vim. Grab a coffee. Tonight you learn the six doors into Insert mode.

From memory

Warm-up from earlier chapters

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

Three words forward, in two keys.
press the keys…2 keys
1 of 2
Three words forward, in two keys.

Before or after the cursor

You already know i inserts before the cursor. Its twin a appends after it. Same doorway, other side of the frame: pick whichever puts you at the gap with less walking.

1const tota = cart.sum();
NORMALLoading the editor…1:10
Try it

Fill the gaps

Two letters went missing. Move to each gap and insert the letter with i or a.

1 of 2Type a where it's shown in green
1const totl = cart.sum();
1const dicount = 0.1;
NORMALLoading the editor…1/20.0s1:1

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

A: the door at the far end

Missing semicolons go at the end of a line. Walking there word by word and then pressing a works, but it's a long walk on a long line. A is the door at the far end of the line: one key, from anywhere on the line, that takes you to the end and into Insert mode.

1const total = cart.sum()
NORMALLoading the editor…1:1
Try it

Semicolon patrol

The formatter stole these semicolons. Put them back with A.

1 of 4Type ; where it's shown in green
1export class Kitchen {
1 private queue: Order[] = [];
2 private busy = false;
3
4 enqueue(order: Order) {
5 this.queue.push(order);
6 this.startNext()
7 }
8
9 startNext() {
10 if (this.busy || this.queue.length === 0) return
11 this.busy = true;
12 const next = this.queue.shift();
13 cook(next).then(() => this.finish())
14 }
15}
NORMALLoading the editor…1/40.0s1:1

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

I: the front door

I is the front door. It starts typing at the first real character of the line, stepping over the indentation the way you'd step over a doormat.

1 onst order = createOrder(cart);
NORMALLoading the editor…1:28
Try it

Lost first letters

Some lines lost their first letter. I puts you right where it belongs.

1 of 4Type e where it's shown in green
1xport const menu = [
1 { id: "al-pastor", name: "Al Pastor", price: 9.5, spicy: true },
2 { id: "veggie", name: "Garden Veggie", price: 8.25, spicy: false },
3 { id: "carnitas", name: "Carnitas", price: 10, spicy: false },
4];
5
6xport function findItem(id: string) {
7 const item = menu.find((m) => m.id === id);
8 if (!item) throw new Error("not on the menu: " + id);
9 eturn item;
10}
NORMALLoading the editor…1/40.0s1:1

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

o and O: a door to a new line

o opens a door onto a brand-new line below the cursor and steps you through, already indented to match. O opens one above. Both work from anywhere on the line, so there's no walking to the end first.

1 const order = await save(cart);
1 return order.id;
NORMALLoading the editor…1:3
1 const order = await save(cart);
2 return order.id;
NORMALLoading the editor…2:3
Try it

Leave a trail

Add the log line below the insert, then a TODO above the total.

1 of 2Add the green line log("placed", order.id);
2export async function placeOrder(cart: Cart, user: User) {
1 const total = cart.items.reduce((sum, i) => sum + i.price, 0);
3 const order = await db.orders.insert({ userId: user.id, total });
+ log("placed", order.id);
1 return order.id;
2}
NORMALLoading the editor…1/20.0s3:3

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

All six doors

Three pairs. The lowercase door and its capital always mirror each other: one before or above, one after or below.

Opens ontoBefore / aboveAfter / below
the cursori before ita after it
the lineI its first character, past the indentA its end
a new lineO aboveo below
From memory

Six doors, from memory

Where do you want to start typing? Press the door.

Right before the cursor.
scroll here, then press the keys
1 of 6
Right before the cursor.
Challenge

Patch the build

The formatter hit every file: missing semicolons and missing first letters, eight repairs across the codebase before the 9 a.m. stand-up. Each one is marked; pick the door that takes you straight there.

Stuck? Show a hintA;<Esc> for a lost semicolon, I + the letter + <Esc> for a lost first letter
1 of 8Type e where it's shown in green
1// delivery zones: where riders go, and what it costs to get there
1xport const ZONES = [
2 { name: "Little Havana", lat: 25.7656, lng: -80.219, fee: 2.5 },
3 { name: "Brickell", lat: 25.7663, lng: -80.1917, fee: 2 },
4 { name: "Wynwood", lat: 25.8005, lng: -80.1994, fee: 3 },
5 { name: "Coral Way", lat: 25.7505, lng: -80.2409, fee: 3.5 },
6 { name: "Downtown", lat: 25.7743, lng: -80.1937, fee: 1.5 },
7 { name: "Edgewater", lat: 25.8001, lng: -80.1887, fee: 3 },
8];
9
10xport function zoneFor(lat: number, lng: number) {
11 return ZONES.find((z) => Math.abs(z.lat - lat) < 0.01 && Math.abs(z.lng - lng) < 0.01);
12}
NORMALLoading the editor…1/80.0s1:1

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

Boss round

Repair the function

One function, seven wounds, three minutes until the build server checks again. Top to bottom: the first letter of function, three lost semicolons, the missing s at the end of the second item, a new line under the price line that adds the tip (sum += item.tip;), and a note above return: // tax included. The marks show what goes where. Pick the door that needs the least walking each time.

Stuck? Show a hintI · A · a after the word · A · o · A · O (each ends with <Esc>)
1 of 7Type f where it's shown in green
1unction total(items) {
1 let sum = 0
2 for (const item of item) {
3 sum += item.price
4 }
5 return sum
6}
NORMALLoading the editor…1/70.0s1:1

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

GreenFinish the exercise above to see it.

Extra practice optional

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

Endless

Formatter cleanup

Replays of the night's damage, from the build logs: endless repairs, in bigger batches as you go. How long can you keep the build green?

Level 1Type e where it's shown in green
1// delivery zones: where riders go, and what it costs to get there
1xport const ZONES = [
2 { name: "Little Havana", lat: 25.7656, lng: -80.219, fee: 2.5 },
3 { name: "Brickell", lat: 25.7663, lng: -80.1917, fee: 2 },
4 { name: "Wynwood", lat: 25.8005, lng: -80.1994, fee: 3 },
5 { name: "Coral Way", lat: 25.7505, lng: -80.2409, fee: 3.5 },
6 { name: "Downtown", lat: 25.7743, lng: -80.1937, fee: 1.5 },
7 { name: "Edgewater", lat: 25.8001, lng: -80.1887, fee: 3 },
8];
9
10export function zoneFor(lat: number, lng: number) {
11 return ZONES.find((z) => Math.abs(z.lat - lat) < 0.01 && Math.abs(z.lng - lng) < 0.01)
12}
NORMALLoading the editor…lv 1 · 0 done0.0s1:1

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