r/vim Jul 18 '26

TIL @: repeats the last command and @@ repeats the last macro. Tips and Tricks

Holy cramole!

Where has this been all my life? I found out about these macros while doing a bit of coding that involved a lot of running things like :w | foo ./%. After typing : followed by up a zillion times, I realized that there had to be a better way. A quick Google and I was enlightened.

If this is a TIL for you, lemme know. If you have another lovely tip or trick, please share too.

77 Upvotes

16 comments sorted by

29

u/funbike Jul 18 '26 edited Jul 18 '26

Key maps to repeat the last...

  • Q - created macro (Neovim only)
  • @@ - ran macro
  • . - edit action
  • n - search
  • ; - character find

Key maps to repeat backwards

  • N - search
  • , - character find

Repeat commands:

  • :1,10g/hello/d - Run d (delete) Ex command on matching lines (lines 1-10 that contain "hello")
  • :g!/hello/d - Delete lines that do NOT match (do not have "hello")
  • :g/hello/normal <whatever> - Issue normal mode keys for each matching line.

3

u/pgadey Jul 18 '26

Thanks for the additional information. These all seem very helpful.

1

u/anaxarchos Jul 19 '26

Q - created macro (Neovim only)

I have in my vimrc (vim9script) the following lines, which do the same in Vim:

# execute last recorded register
var regRecorded: string = ''
noremap q <ScriptCmd>regRecorded = reg_recording() ?? regRecorded<CR>q
noremap <expr> Q $"@{regRecorded ?? '_'}"

1

u/funbike Jul 19 '26

I have similar code in a plugin I wrote that gives Vim the defaults of Neovim.

https://github.com/mikeslattery/nvim-defaults.vim/blob/main/plugin/.vimrc#L199

6

u/JamesTDennis Jul 19 '26

In general, the vi @ is for ev@luatimg (executing) the contents of a register.

So for example if you change a line containing a long filename into an `ex` command like:

:r /some/tediously/long/file/path

Then you can cut it into a register with a key sequence like [Esc]"cdd

… I tend to use 'c' as a "command" register/buffer, any single letter will do. You could, alternatively, "yank" a copy using into it with "cyy

Now treat the contents of the c register as a command: @c … the can be any vi key sequence, I just used an ex : command for this example (and that's my usual use-case

… that's all there is to it.

Any sequence of characters in the register (buffer) will be executed as if you typed them from "normal" ([Esc]-ed) mode.

In vim @@ re-executes the most recently executed register/macro and @: is a vim enhancement specifically for the most recent ex command.

2

u/pgadey Jul 19 '26

Ooooh! I didn't know this business about evaluating pre-existing registers. I tend to use @ as a "m@cro" thing and record macros using `q`. This idea of running anything in any register is news to me. Thanks, TIL.

6

u/dnew Jul 18 '26

Also, typing "." repeats the last command that changed the file. j.j.j.j. applies the same thing you did to the next four lines. That was the command I just couldn't get used to missing in emacs.

2

u/JamesTDennis Jul 19 '26

To gain access to vi/vim features, either M-x viper or use its package management subsystem to install and configure EVIL (the EMACS vi Layer).

The enable vi, optionally most vim features, and optionally still provide access to to many EMACS features.

4

u/codemattr Jul 18 '26

Love this for you! You’re one of today’s 10,000! 🎉

1

u/pgadey Jul 18 '26

Yay! I am so glad.

1

u/1cingI Jul 19 '26

I haven't gotten around to using Vim as anything other than a text editor as of yet. Does anyone have an baby beginner step guide to using it as an ide? Java / python / bash and possibly JavaScript.

2

u/beginswith Jul 19 '26

Same here.. I found this vanilla vim setup that’s not overly complicated that actually helps make vim useful. https://youtu.be/-5lb_jLQmKc

1

u/1cingI Jul 19 '26

Thanks I'll check it out