In this episode you will assemble Neovim's true grammar: combining operators (d, c, y, p) with motions and text objects (ci", di(), yap) as well as leveraging marks and the jump list.

After covering modal editing and mastering basic navigation (Vim motions) in episode 2 — from hjkl, word & line motions, to searching with / and * — in this episode we will assemble the real puzzle. This is where Neovim's "grammar" takes complete shape: operator + motion, text objects, and marks/jump list.
Why is this important? Up to episode 2, you could only move — but you could not yet efficiently modify text content. In this episode you will learn to delete, change, yank, and paste at a speed that is impossible with modeless editors. Think of it like learning to cook: motions are how you hold the knife, and operators are the slicing movements. Both must be mastered together.
This is also the episode that separates true Neovim users from mere dabblers: when people ask "how are you editing so fast?", the answer is almost always here — text objects and operator+motion combinations.
Neovim's philosophy in one sentence: every editing operation is a sentence with the format operator + count + motion. Operators are the verbs (what to do), motions are the objects (what it applies to). This grammar is consistent — once you understand it, hundreds of combinations can be guessed without memorization.
| Operator | Function | Analogy |
|---|---|---|
d | Delete | "Cut" |
c | Change (delete then enter insert mode) | "Cut and replace" |
y | Yank (copy to a register) | "Photocopy" |
p | Put (paste from a register) | "Glue" |
u | Undo | "Undo" |
Ctrl+r | Redo | "Redo the undo" |
Important difference between d and c: d only deletes, while c deletes and immediately enters insert mode so you can type the replacement right away. This saves a step (d + i).
Now let's combine the grammar:
| Combination | Literal Meaning | Result |
|---|---|---|
d$ | delete to end of line | Deletes the rest of the line from the cursor |
d0 | delete to start of line | Deletes the beginning of the line from the cursor |
dd | delete line | Deletes the entire current line |
dw | delete word | Deletes one word forward |
cw | change word | Deletes one word then enters insert mode |
y3w | yank 3 words | Copies three words |
yy | yank line | Copies one line |
y$ | yank to end | Copies to the end of the line |
p | put | Pastes the yanked/deleted content below the cursor |
P | put (uppercase) | Pastes above/at the cursor position |
ddp | swap lines | Swaps two lines (delete+paste) |
Tip
Count (numbers) strengthen motions. 3w = forward 3 words, 2dd = delete 2 lines, y3w = copy 3 words. Counts apply to operators, motions, or both: 2d3w = delete twice (3 words each) = delete 6 words. This is a real example of how consistent grammar turns a complex action into a short sentence.
Imagine this line, with the cursor at the start of the word quick:
The quick brown fox jumpsVarious operations using the grammar above:
| Desired Action | Command | Result |
|---|---|---|
| Delete "quick " | dw | The brown fox jumps |
| Change "quick" to "slow" | cw then type slow then Esc | The slow brown fox jumps |
| Delete words 3 and 4 | d3w | The jumps |
| Delete the whole line | dd | empty line (register holds the line) |
| Copy the line then paste below | yy then p | duplicate line below |
| Swap two lines | ddp | line positions swapped |
Note
After dd or d$, the deleted line automatically goes into the unnamed register. That means p can paste it immediately — this is the technique that makes ddp (line swap) only 3 keys. We will go deeper into registers in episode 4.
Text objects are one of the most powerful features in Neovim — and yet the most ignored by beginners. Text objects let you operate on text structures (words, sentences, paragraphs, or content inside quotes/parens), not just characters.
i) vs Around (a)There are two families of text objects:
i (inner) — operates on the content inside a delimiter, without the delimiter itself.a (around) — operates on the content plus the delimiter.The difference is critical. For ci" on the text "hello world":
ci" (change inner) → deletes hello world, leaving "" — the cursor sits inside the quotes, ready to type.ca" (change around) → deletes "hello world" including the quotes.| Command | Object | Example |
|---|---|---|
ciw | inner word | Change one word without touching spaces |
caw | around word | Change the word + the space after it |
ci" | inner double quote | Change the content inside "..." |
ca" | around double quote | Change "..." including the quotes |
ci' | inner single quote | Content inside '...' |
di( | inner paren | Delete the content inside ( ... ) |
da( | around paren | Delete ( ... ) including the parens |
yap | around paragraph | Copy one paragraph |
dip | inner paragraph | Delete one paragraph |
ci[ | inner bracket | Content inside [ ... ] |
ci{ / ci} | inner braces | Content inside { ... } |
di< | inner angle | Content inside < ... > |
cit | inner tag | Content inside an HTML tag (<div>...</div>) |
dat | around tag | The whole <div>...</div> |
Notice the pattern: c/d/y + i/a + delimiter. Verb + (inner/around) + object. Same grammar, hundreds of combinations.
Compare two ways of replacing the content of a string argument:
const user = fetch("/api/users?name=username");ci" → type the new value → Esc. Done in 3 keys + typing.Now imagine having to change an argument inside fetch(...) across 20 different lines of code. With ci( you can do it without ever moving the cursor to a precise position — just anywhere inside the parens.
Important
The secret of text objects: you do not need to place the cursor exactly at the edge of the text. ci" works as long as the cursor is anywhere inside the quotes. This is a fundamental difference from modeless editors that demand mouse precision. Massive efficiency comes from here — memorize ciw, ci", ci(, ci{, yap, and ci[; they already cover most of your needs.
When working on long files, you will often go back and forth between two locations. Neovim provides two mechanisms: marks (manual markers) and the jump list (automatic trail).
Marks are "bookmarks" you place manually inside a file:
| Command | Function |
|---|---|
ma | Mark the current position with name a |
`a | Jump directly to mark a's position |
'a | Jump to the start of mark a's line |
:marks | List all marks |
d'a | Delete up to mark a's line |
:delm a | Delete mark a |
Marks can be lowercase letters (a–z, per-file) or uppercase letters (A–Z, global across files). When editing large files, the habit of "mark location A, move to B, then come back" (ma ... `a) is a super-fast jump.
Unlike manual marks, the jump list automatically records every big jump you make (long-distance motions, searches, cross-file jumps):
| Command | Function |
|---|---|
Ctrl+o | Go back to the previous position (out) |
Ctrl+i | Go forward to the next position (in) |
:jumps | View the jump list |
A classic usage pattern: you are reading line 500, then jump to line 20 (20G), then want to return exactly to line 500 — one press of Ctrl+o brings you back. Ctrl+o/Ctrl+i is the fastest way to alternate between locations without remembering line numbers.
| Command | Function |
|---|---|
gi | Return to the last insert mode position (and enter insert mode immediately) |
g; | Jump to the last change location (backward) |
g, | Jump to the next change location (forward) |
gf | Open the file under the cursor (go to file) |
gF | Open the file under the cursor + jump to the indicated line number |
Ctrl+^ | Switch between the last opened files |
gi and g; are very useful for repeating edits: gi returns you exactly to your last typing position — perfect after pressing Esc and browsing around for a bit. gf works on files that reference a relative path (e.g. import "./utils.ts") — place the cursor on the file name and press gf.
Tip
The most productive combination for code editing: g; to return to the last change location, g, to go forward to the next change. If you are switching between two functions to fix two bugs, g;/g, will save you dozens of navigation steps.
Create a file latihan3.txt and copy the following lines:
const name = "budi"; // TODO: ganti jadi "siti"
const url = "https://api.dev/users?filter=all";
const list = [1, 2, 3, 4, 5];
function calculate(a, b) { return a * b; }Do the following in Neovim:
"budi", press ci", type siti, Esc.?filter=all — place the cursor on ?, press d$.yy → p → p.return a + b; — cursor inside { ... }, press ci{, type return a + b;, Esc.gg (top), ma (mark), G (bottom), then `a (return).gg → 10G → $, then press Ctrl+o twice to go back, Ctrl+i to go forward.g;/g, practice — make 3 random changes, then trace their locations with g; and g,.ddp practice — swap the positions of lines 1 and 2.Tip
A practical rule for remembering i vs a: i = inside only, a = inside + surroundings. When in doubt, use i first (safer, does not delete delimiters). You can verify the difference by yanking: yi" vs ya" then p somewhere else.
Forgetting the motion, not just the operator. d alone does nothing — always follow it with a motion/object: dw, dd, d$, d'a. If you press d and get confused, press Esc and start over.
Confusing ciw vs cw. cw is change-word (delete from the cursor to the end of the word); ciw is change-inner-word (delete the entire word the cursor is in, from any position within it). To change a whole word, ciw is more predictable.
Getting i vs a wrong. ci" leaves the quotes, ca" deletes them. You will regret thinking you changed a string's content only to find the quotes are gone too (or vice versa). Practice both.
Pressing p but the paste lands in the wrong place. p pastes after the cursor, P before. For lines, p pastes below the current line, P above. If a paste looks weird, check the register (:reg) before panicking.
Overusing u. u is undo, Ctrl+r is redo. If you undo too far, Ctrl+r saves you. Neither needs to be memorized — but both must be practiced.
gf fails because the file is not found. gf needs a file that actually exists at the relative path. If you think gf is "broken", check first whether the referenced file really exists.
In episode 3 you assembled Neovim's core grammar: linking operators (d, c, y, p, u, Ctrl+r) with motions to form editing sentences (d$, cw, y3w, ddp), mastering text objects that operate on text structure (ci", di(, yap, ci{, ca}), and leveraging marks (ma/`a), the jump list (Ctrl+o/Ctrl+i), and advanced motions (gi, g;/g,, gf, Ctrl+^).
Key points to take with you:
operator + count + motion, consistent and predictable.i vs a) are the biggest efficiency differentiator — master ciw, ci", ci(, ci{, yap.Ctrl+o/Ctrl+i is the fastest way to go back and forth between locations.Now you can edit with precision. In episode 4, we will cover Registers, Macros & Efficient Editing — diving deeper into Neovim's temporary storage system (registers ", a-z, 0-9, +), recording action sequences as macros (qa...q, @a, 10@a), and mastering search & replace (:%s/old/new/g) and the dot command (.). This is the episode where you will feel the "multiplied efficiency" that modal editing promises. Stay motivated!