Before diving in, the core loop:
| Keys | What it does |
|---|---|
qa |
Start recording into register a |
q |
Stop recording |
@a |
Play register a |
@@ |
Replay the last played macro |
8@a |
Play macro a eight times |
Ctrl-A |
Increment the number under/after the cursor |
Ctrl-X |
Decrement the number under/after the cursor |
The golden rule of macros: end your macro with the cursor positioned so that
replaying it hits the next target. Usually that means finishing with j (move
down one line).
The error-stop trick: macros abort on any failed motion. If f. can't find
a . on the line, the macro stops. This is a feature — it means "run until
there's nothing left to do" via 999@a.
Open a terminal in a scratch area and launch Neovim:
mkdir -p ~/tmp/oil && cd ~/tmp/oil nvim .
You should be in an Oil buffer (:Oil if not). You'll see the directory
listing. Everything below happens from here.
Create a practice directory: type o to open a new line below the cursor,
type practice/ and hit <Esc>, then :w to save. Oil creates the directory.
Press <CR> on the practice/ line to enter it. You're now in an empty Oil
buffer — your playground.
Goal: Create file_01.txt through file_10.txt without typing each one.
Steps:
- Type the first entry manually:
ofile_01.txt<Esc> - Now record the macro:
qa(start recording into registera) yyp— yank the current line, paste below. Cursor is now on the new (duplicate) line.Ctrl-A— increment the number.file_01.txtbecomesfile_02.txt.q— stop recording.
You now have file_01.txt and file_02.txt in the buffer, and a macro in
register a that duplicates + increments.
8@a— run the macro 8 more times.
You should see file_01.txt through file_10.txt listed.
:w— save. Oil creates all 10 files on disk.
What you practiced: yy, p, Ctrl-A inside a macro, and counted replay
with 8@a.
Goal: Rename every file from .txt to .md.
Steps:
- Move to the first file line (
ggor1Gto be safe). qa— start recording into registera.f.— jump to the.in.txt.C— change from cursor to end of line (deletes.txt, enters insert mode)..md— type the new extension.<Esc>— back to normal mode.j— move down to the next line.q— stop recording.9@a— run on the remaining 9 files.:w— save. All files are now.md.
What you practiced: f. (find character), C (change to end of line), and
the j-at-the-end pattern.
Goal: Rename file_01.md to draft_file_01.md (and so on for all).
Steps:
gg— go to the first file line.qa— start recording.I— insert at the beginning of the line.draft_— type the prefix.<Esc>— back to normal mode.j— move down.q— stop recording.9@a— run on the rest.:w— save.
Note: if you have icons enabled in Oil, I might land before the icon. In
that case, use ^i instead of I (go to first non-blank, then insert), or 0w
then i. Adjust to taste.
What you practiced: I (insert at line start) in a macro.
Goal: Undo the previous exercise — turn draft_file_01.md back to
file_01.md.
Steps:
ggqa^— jump to first non-blank character (thedindraft_).df_— delete through the first_. This deletesdraft_exactly.jq9@a:w
What you practiced: df_ — the f + d combination. d + f{char} means
"delete from cursor through the next occurrence of {char}." This is a
workhorse motion for trimming prefixes of varying length.
Goal: Change file_01.md to chapter_01.md (and so on).
Steps:
ggqa^— first non-blank character.ct_— change to (but not including)_. This deletesfileand drops you into insert mode with_01.mdstill intact.chapter— type the new word.<Esc>jq9@a:w
What you practiced: ct_ — one of the most useful motions for structured
names. c + t{char} changes everything up to (but not including) the target
character.
Goal: Shift all chapter numbers up by 100 — chapter_01.md becomes
chapter_101.md, etc.
Steps:
ggqa100Ctrl-A— add 100 to the first number on this line.01becomes101.jq9@a:w
You now have chapter_101.md through chapter_110.md.
What you practiced: Counted Ctrl-A. You can use any number — 5Ctrl-A
adds 5, Ctrl-X subtracts. This is incredibly powerful for batch renumbering.
Goal: Open each file, insert a title line based on the filename, save, return to Oil, and repeat.
This is where macros in Oil get really powerful — you can script a workflow that crosses buffer boundaries.
Steps:
gg— first file.qa— start recording.^— go to start of filename.yt.— yank to the.(copieschapter_101into the default register, without the.md).<CR>— open the file.O— open a line above (oriif the file is empty —Ois safer).#— type the heading prefix.<Esc>p— escape, then paste the filename. The line now reads# chapter_101.:w<CR>— save the file.-— Oil's "go to parent directory" mapping. You're back in the Oil listing, cursor on the file you just edited.j— move down to the next file.q— stop recording.9@a
After this, every file has a heading line matching its own name.
What you practiced: cross-buffer macros, yt. (yank-to), using - to
bounce back to Oil, combining Oil navigation with file editing.
Goal: Create appendix_A.md through appendix_E.md using a macro, then add
content to each.
This time, no hand-holding — try to compose it yourself using what you've learned:
- Type
appendix_A.mdmanually on a new line. - Record a macro that duplicates the line and increments the letter. Hint:
Ctrl-Aworks on letters too when youset nrformats+=alpha— run:set nrformats+=alphafirst. 4@ato get A through E.:w- Now record a second macro (use register
b—qb) that opens each appendix file, inserts# Appendix Xas a heading (yanking the letter from the filename), saves, and returns. 4@b
Bonus: Record a macro into register c that opens each file and appends a
second line Status: draft under the heading. Chain it: 4@c.
| Motion | Meaning | Macro use | |--------|---------|-----------| | f. | Find
next . | Jump to extension | | t_ | To (before) next _ | Target delimiters
| | C | Change to end of line | Replace suffix | | I | Insert at line start
| Add prefix | | A | Append at line end | Add suffix | | df_ | Delete
through _ | Remove prefix | | ct_ | Change to _ | Replace prefix | | yt.
| Yank to . | Copy basename | | Ctrl-A / Ctrl-X | Increment / decrement |
Renumber | | j | Move down | Advance to next target |
Ask yourself: "Am I about to do the same 3+ keystrokes more than twice?"
If yes, record it the second time you do it. By the third occurrence you're already replaying instead of typing. In Oil this comes up constantly — renaming batches, restructuring directories, seeding files with boilerplate. The buffer is the filesystem, so every text macro becomes a filesystem operation.