In the buffer
Before:
total = price * qty
^
tax = total * 0.08
print("total:", total)
return total + tax
After typing *N to load the word as the search pattern and come back, then cgn, subtotal, <Esc>, and finally .nn..:
subtotal = price * qty
tax = subtotal * 0.08
print("total:", subtotal)
return subtotal + tax
^
The first cgn changes the match under the cursor. Each . finds the next match and changes it. The nn steps onto the label inside the string and then past it, so that one stays total.
When you would reach for it
You are renaming something that appears a dozen times, but not every occurrence should change. One is inside a string, one is in a comment that refers to the old name on purpose, and one belongs to a different variable that happens to share the word. :%s///gc works, but it takes over the screen and asks y/n for every match, including the ones you already know about. cgn lets you make the change once, then work down the file with . to accept and n to move on, looking at the real code around each match while you go.
Gotchas
ndoes not skip a match in one press.gntargets the match under the cursor if there is one, so after onenthe cursor sits on the match you wanted to keep and the next.changes it. Pressna second time to move past it, then..- If the new text contains the pattern,
.can land on text you typed a moment ago. With a pattern oftotal(no word boundaries), replacingtotalwithsubtotaland pressing.turns it intosubsubtotal. Search with*or write/\<total\>so the pattern only matches the whole word. *jumps forward before you change anything, so*cgnchanges the second occurrence and leaves the one you started on for last, reached only after the search wraps. Type*Nto return to where you started first.- The pattern comes from the last search, not from what you changed. Running any other search between presses of
.changes the target, and.then changes matches for the new pattern.
Variants
dgn
Deletes the next match instead of changing it. Set the pattern to , total and dgn removes the trailing argument from the print call. . repeats the delete.
gn
Without an operator, gn visually selects the next match. Useful for checking what cgn is about to touch before you commit to it.
cgN
The same change, searching backward. Handy when the cursor is below the matches you care about.