6

When executing an ex command I can use the variable v:count to get the count which was given to this command. From :h v:count, if I create this mapping:

:map _x :<C-U>echo "the count is " . v:count<CR>

And use 12_x I'll get a message

the count is 12

How can I do the same with a macro?

When calling a macro 12 times with 12@a how can I know that the current execution is the nth of the 12?


So far I tried to create a macro which show the count like like:

qaa<C-r>=v:count<CR><Esc>q

But when I play it with 12@a; I simply get 12 zeros:

000000000000

Which makes me think that the variable v:count is not used by macros.

  • As a first comment, the :h [count] help gives an insight that repeating a macro is no different than repeating any other command, e.g. 3D. – nobe4 Oct 28 '16 at 8:51
  • @nobe4 That's what I thought but see my edit, it seems like v:count isn't used in a macro. – statox Oct 28 '16 at 9:03
  • You could try remapping @ so that it takes a char with getchar, and then run the text from getreg – DJMcMayhem Oct 28 '16 at 16:37
  • @DJMcMayhem that would be a possibility but I'm surprised there is not a built-in way to do so. – statox Nov 2 '16 at 8:38
  • v:prevcount would give you the count for that particular macro, but only for the first run. v:count is giving you the count for the a, not the @a. – Antony Jan 27 '17 at 0:36
4

It seems that there is no built-in way to do what I want. So I came up with this small chunk of code following @DjMcMayhem comment. It is not extensively tested but it seems to be working.

First let's remap @ to call our custom function:

nnoremap <silent> @ :<C-U>call MacroWithCount()<CR>

And the function:

function! MacroWithCount()
    # Get the content of a register given by the user
    let registerContent = getreg(nr2char(getchar()))
    let macroCount = v:count1

    for i in range(macroCount)
        execute "normal! " . registerContent
        let macroCount = macroCount - 1
    endfor
endfunction

First we use getreg() combined with getchar() to get the content of a register given by the user.

Then we create the macroCount variable which will be the variable to use in the macro to get the current count.

Finally we execute the macro and update macroCount each time the macro has been executed once.

Now if I record this macro:

qaa<C-r>=macroCount<CR> <Esc>q

I get:

 12 11 10 9 8 7 6 5 4 3 2 1

Note that the function still needs a major improvement: it doesn't understand @@ as execute the last executed macro. so far I haven't found a way to get the content of the last executed macro (I thought that it was what v:register was for but it seems that I was wrong)

The related help topics:

0

This is a bit of a hack but does what you asked :)

y3w:exec 'norm!' getreg('"') == "the count is " ? "3w\<c-a>`[3b" : "ithe count is 1\<esc>3b"

Save this to register a and when you 12@a it will print

the count is 12

Since there is no way to pass the count to the macro (that I know of), the macro is still run n times but it will only increment the number after the first run.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.