Lesson 4 — Text Objects
Two things happen constantly while you work with a coding agent. You mistype a word in the middle of a long prompt. And it prints cannot open "src/lib/router.ts" and you want that path for your next one.
Both have the same clumsy answer without Vim: walk to the start of the thing, then measure your way to its end, and hope you counted right. Text objects remove the measuring. You name the thing instead: the word, the quoted string, the block I am standing in — and the cursor only has to be somewhere inside it.
That is what a text object is: not a direction to travel, but a noun. Three keys, and the whole thing is yours — ciw to replace the word you are standing on, yi" to lift the path out of the error, diW to remove a URL you pasted and thought better of.
This is the lesson that pays for the course. Motions are how you get around; objects are how you change what you are writing and lift things out of what you are reading.
Inner and around
Every object is two keys: i for inner, a for around, then a letter or a delimiter saying what kind of thing you mean.
iw— the word, and nothing else.aw— the word with the space after it. That is what you want when the deletion shouldn't leave a double space behind, or when the yank is going to be pasted up against something else.
Put an operator in front and read it as a sentence. yiw is yank inner word. daW is delete around WORD. vip is select inner paragraph. yi" is yank inner quotes.
The part that feels like a trick the first time: you do not have to be at the start of the thing. Anywhere inside it will do. Land somewhere in the middle of a filename and yiW takes all of it, both directions at once. That is the whole reason objects beat motions for this errand — a motion has to start from the right place, and an object doesn't care.
The kinds of object
Everything here has both an i and an a form.
| Object | What it names | Where it works |
|---|---|---|
iw aw | a word — a run of letters and digits | Both |
iW aW | a WORD — a run of non-space. A URL is one of these | Both |
ip ap | the block you're standing in — a paragraph, or one run of output rows. ap reaches on over the blank rows after it | Both (copy and select only, in a terminal) |
i" i' and the backtick form | the quoted run | Both |
i( i) — or vim's alias ib | parentheses | Both |
i[ i] | square brackets | Both |
i{ i} — or vim's alias iB | braces | Both |
i< i> | angle brackets | Both |
Three things about the delimiters are worth knowing, because they save you keystrokes every time:
Either half of a pair names it. yi( and yi) are the same command, and so are da[ and da]. Press whichever one your thumb or your hand reaches first — there is nothing to remember.
In a terminal you don't even have to be inside the pair. If there is no pair around the cursor, the next one along the line is taken instead. Sitting at the start of a line of output and pressing yi" lifts the quoted path out of it. Landing on the right line is usually enough.
i on an empty pair takes nothing. Given () there is no inside, so nothing is yanked — rather than quietly handing you a bracket you didn't ask for. And a quote the shell escaped with a backslash isn't treated as a delimiter, so a path with an escaped quote in it still comes out whole.
Putting an operator in front
Every operator you learned in Lesson 3 takes an object, and so does v. That is the entire combination table — you already know both halves.
| To do this | Press | Where it works |
|---|---|---|
| Copy the word under the cursor | yiw | Both |
| Copy a URL | yiW | Both |
| Copy a word with its trailing space | yaw | Both |
| Copy the block an agent just printed | move up into it, then yip | Both |
| Copy that block and the gap after it | yap | Both |
| Select that block to look at it first | vip | Both |
Lift a path out of cannot open "src/x.ts" | yi" | Both |
| Copy what's inside parentheses | yi( | Both |
| Select a URL you're about to act on | viW | Both |
| Select the word under the cursor | viw | Both |
| Delete a pasted URL you don't want | diW | On the line you're typing |
| Replace the word you're on | ciw | On the line you're typing |
| Delete a word and its trailing space | daw | On the line you're typing |
| Fix a quoted string you're typing | ci' | On the line you're typing |
| Delete a bracketed section, brackets and all | da[ | On the line you're typing |
| Replace what's inside braces | ci{ | On the line you're typing |
| Select inside angle brackets | vi< | Both |
| Fix the case of a word | gUiw guiw | On the line you're typing |
Notice that nothing here is new vocabulary. c still means change, y still means yank, i still means inner. You learned the pieces separately and the combinations arrived free.
Where each of these works
The rule from Lesson 3 holds, and objects are where you feel it most.
Copying and selecting reach the whole screen. yiw, yiW, yip, yi", viW — all of these work wherever your cursor is, including far up in old output, in an error from ten commands ago, in the middle of an agent's reply while it is still thinking. Reading is always allowed.
Changing and deleting reach exactly one line — the one you are currently typing, and only while nothing is running. Put the cursor up in the output and diw simply does nothing; that output has already happened. Copying, though, works anywhere on the screen, which is what you wanted up there anyway.
dip does nothing. Use yip instead — copying a block is almost always what you meant.
A copy that crosses rows comes out whole lines at a time. yip gives you the block linewise, which is what you want when the next stop is a prompt or a chat message.
ip means the block your cursor is standing in. That is worth saying plainly, because the commonest surprise is pressing Esc then yip and getting your own prompt box: the cursor starts at the prompt, so that is the block it is in. Step up into the agent's reply first — k a few times, or { to jump a whole block — and then yip takes what you meant.
Every yank also lands on your system clipboard, so yip in a terminal on your phone can be pasted into anything else on the device.
In a code editor
Objects behave the way you expect from Vim: the same i and a forms, the same delimiters, and no restriction about which line you are on. ciw on line four hundred is as ordinary as ciw on the line you just typed, and ci( inside a function call replaces the arguments wherever they are.
The other difference is that a code editor has u. That makes it the best place to learn objects: put the cursor somewhere awkward, press daw, look at what vanished, press u, try diw instead. Five minutes of that and you will never think about the difference again.
Try it
Open a terminal with Vim keys on, and run something that prints a path in quotes — cat "no/such/file.txt" will do it, and so will any agent that has just failed at something.
- Press
Escto reach normal mode. - Move onto the line with the quoted path in it. You do not need to be inside the quotes.
- Press
yi". The path is now on your clipboard as well as in Vim's register. - Press
pto drop the path into your prompt, thenito carry on typing. That order matters:ponly means paste in normal mode. - Press
Esc, then move up into a block of output — an agent's reply, or the output of one command — and pressyipto take the whole block. - Press
ifirst —yipleft you in normal mode — then type a command with a wrong word in it. PressEsc, move onto that word and pressciw. Type the correction; you are already in the right place. - Now paste a long URL into your prompt, press
Esc, land anywhere on it, and pressdiW. Three keys, whatever its length. - For contrast, move up into old output, land on a word, and press
diw. Nothing happens — changing only reaches the line you are typing.
You now know: how to name a thing instead of measuring it — i for inner and a for around, over words, WORDs, blocks, quotes and brackets. Naming works everywhere for copying things out of output, and on the line you are typing for changing what you are writing.
Related
- Vim Mode — the full reference for both halves
- Terminals
- CLI Coding Agents
- Code Editor
- Phone Key Row — where the delimiters live under your thumb
← Lesson 3 — Operators, Counts and the Grammar · Lesson 5 — Search, Yank, Registers and Marks →