You don’t need more than one cursor in vim

nnoremap <silent> @R :set operatorfunc=MacroRepeat<CR>g@
xnoremap <silent> @   :<C-u>call <SID>MacroRepeat()<CR>
function! s:MacroRepeat(...)
    execute (a:0 ? "'[,']" : "'<,'>") . 'normal @' . nr2char(getchar())
endfunction

When you hit @R in normal mode, Vim will set the value of the operatorfunc option to MacroRepeat and then hit the operator g@. g@ is an operator which waits for a motion. Once you provide one, Vim should automatically put the marks '[ and '] around the text covered by the motion (it always does so for the last text object you used) and call the function whose name is stored inside operatorfunc, in this case MacroRepeat, passing as an argument the type of motion ('char' for characterwise, 'line' for linewise, and 'block' for blockwise).

The function does the following thing:

it tests whether it received any extra arguments (a:0 ?), if there are it means the function was called from normal mode, so it uses the marks '[ and ']. Otherwise it means the function was called from visual mode (you can see in the visual mapping that no argument is passed to MacroRepeat()), and in this case it uses the visual marks '< and '> which Vim also sets automatically for you whenever you visually select some text.

So (a:0 ? "'[,']" : "'<,'>") is equal to '[,'] if the function was called from normal mode, or '<,'> if it was called from visual mode. It's a range you can use before the :normal command to tell it to replay a sequence of keystrokes on all the lines inside the range.

getchar() is a function which asks for a character and returns its ASCII value, and nr2char(getchar()) converts back this number into the original character. So execute (a:0 ? "'[,']" : "'<,'>").'normal @'.nr2char(getchar()) will evaluate to execute '[,']normal @{the character you type} in normal mode and to execute '<,'>normal @{the character you type} in visual mode.

The result is your macro should be replayed by the :normal command on all the lines covered by {motion} in normal mode, and on all the selected lines in visual mode.

To replay the macro q on all the lines inside the current paragraph from normal mode, you would hit @Ripq (because ip is a text object which covers the whole paragraph).
To replay the macro q on all the lines inside the current block of code (inside curly braces) from normal mode, you would hit @RiBq (because iB is a text object which covers a block of code). To replay the macro q on all the selected lines from visual mode, you would hit @q.

If you find the code a little too confusing, then maybe you would prefer this simple mapping:

xnoremap <silent> <expr> @ ':normal @' . nr2char(getchar()) . "\r"

With this last mapping, you would replay your macro only from normal mode. To replay the macro q on all the lines inside the current paragraph, you would hit vip@q (because vip will select the current paragraph).
To replay the macro q on all the lines inside the current block of code, you would hit viB@q (because viB will select the current block of code).

/r/vim Thread Parent Link - medium.com