Vim: better ways to handle macros
The @ command
The @ command is better known as a command to execute macros. But it is more generic, and it can execute Vim commands from any Vim register.
Here is what the help says:
@ @{0-9a-z".=*+} Execute the contents of register {0-9a-z".=*+} [count] times. Note that register '%' (name of the current file) and '#' (name of the alternate file) cannot be used.
And a good quote about what @ can do from the Stack Overflow post:
The @ command is probably the most obscure vi command.
@ executes the contents of a register as if it were a vi or ex command.
Example: I often use: :r!locate … to find some file on my system and read its name into my document. From there I delete any extraneous hits, leaving only the full path to the file I'm interested in.
Rather than laboriously Tab-ing through each component of the path (or worse, if I happen to be stuck on a machine without Tab completion support in its copy of vi) I just use:
- 0i:r (to turn the current line into a valid :r command), it becomes something like :r /path/to/file
- "cdd (to delete the line into the "c" register) and
- @c execute that command.
So we execute the :r /path/to/file command with @c and the file content
is inserted into the current buffer.
It is interesting that instead of using the file name completion in the minibuffer, we build the file name in the regular Vim buffer and then use that file name to read the file content.
:r!locate *.org
Manage macros in a regular buffer
In practice, it allows using the regular Vim buffer to edit and execute commands.
The command buffer : is limited and less convenient, so instead you can
prepare the command in one buffer and run it in another (or prepare, delete to
the register and run in the same buffer).
For example: do "cdd or "cyy on the line below and then @c to add // to all lines.
:% norm I//
This also means that instead of recording a macro, you can type it out and then execute it. Or you can record it, paste and edit it, then execute it.
For example:
qa- start recording into registeraq- stop recording"ap- paste the macro, edit it"ayy- yank it back into registera@a- execute
The contents of the register can also be inserted with Ctrl-R [a-z] in
insert mode (Ctrl-R a in the example above).
The norm command
Note that the :norm command is often a good alternative to macros
(or the more recent Neovim multicursors).
For example, as shown above, the :% norm I// command adds // at the beginning of
each line and :% norm A! appends ! to each line.
Combined with globals (:g and :v), this becomes a fast and flexible way
to apply similar edits in the file.
Using globals with norm
For example, :g/^For/norm A! adds ! at the end of each line that starts with For:
:g- theglobalcommand/^For/- find all lines that start (the^in Vim is the start of the line) withFornorm A!- executeA!on matching linesAmeans "append": it starts insert mode at the end of the line!inserts the "!"
Similarly, :v can be used to apply commands to lines that do not match the pattern.
For example, :v/^For/norm A! adds ! at the end of each line that does not start with For.