How to repeat the last change in Vim

February 28, 2020

How do you repeat an action in Vim?

Dot operator

You can repeat the last action by simply pressing . (dot).

Let's have a look at the example. Imagine, you'd like to remove ; from the end of the line in the following paragraph:

function f1() {}
function f2() {}
function f3() {}
function f4() {}
function f5() {}

One way to do this is to put the cursor on the first line, then press A<Backspace>Esc. Then in order to repeat the same commands on the next line press j.. Repeat on each line.

The dot operator worked here because it remembers everything you did, starting from getting into INSERT mode with A and until you press Esc to get back to normal mode. Whatever happened in the INSERT mode is considered as one indivisible operation.

The ; operator

The ; operator lets you repeat the f, and t motions. That comes handy when you need to replace a specific character, say single quotes with double quotes.

Here's another example,

Replace 'this' with 'that'.

You start at the beginning of the line, then f'r" to move the cursor to the next occurrence of ' and replace it with ". f' is a motion, r" is your dot-repeatable action.

That means that from now, you press ;. to go to the next single quote and replace it with the double quote.

Macros

Sometimes, the set of actions that you need to repeat is not that trivial. In that case, you record a macro, which is simply a way to store and repeat whatever you press on your keyboard.

To record a macros press qa. Here, you can use any other letter instead of a - it's just a register, a pocket where you can put textual data.

Imagine, you have a set of JavaScript one-liner function you would like to change to arrow function:

  function f1() { /* ... */ }
  function f2() { /* ... */ }
  function f3() { /* ... */ }
  function f4() { /* ... */ }
  function f5() { /* ... */ }

Expected:

  f1 = () => { /* ... */ }
  f2 = () => { /* ... */ }
  f3 = () => { /* ... */ }
  f4 = () => { /* ... */ }
  f5 = () => { /* ... */ }

Press qa to record a macro.

Then ^df<space>f(i<space>=<space><esc>f{i=><space>j.

Then press q to stop recording.

I know that looks like a bit too much, but there's nothing fancy going on here:

  • ^ go to the beginning of the line (or rather to the first non-space character)
  • df<space> deletes the word function
  • i<space>=<space><esc> adds = right before the first parenthesis in INSERT mode
  • f{i=><space> adds => right before the body of the function
  • j moves to the next line

If you get it right, now your cursor is on the next line, and you can pres @a to play the macro again.

Or press 4@a to play it four times, and thus change all remaining lines at once.

To wrap it up,

  1. Use . to repeat the last simple change.
  2. Use ; to repeat the last f/F/t/T motion.
  3. For more complex cases, record a macro.

I hope that was helpful.

Have a productive day!

Vim For Developers

Vim For Developers

❄️ 35% off this Christmas season! ❄️

Learn Vim and upgrade your productivity to the next level by building the IDE of your dreams.

LEARN MORE