jwd
jwd

Reputation: 11114

Vim: save a macro inside a mapping

I have a mapping, like <leader>x and inside that mapping it does some moderately complex work. I'd like that mapping, as part of its work, to save a macro, so that I can then use @z (or whatever) afterwards to repeat it.

I know it's a bit odd to want a shortcut for something that is already a shortcut, but bear with me (:

My real example is a bit complicated, so let's just use a simple one here:

Here's a working mapping:

nnoremap <expr> <leader>x 'mz' . v:count . 'Ax<ESC>' . v:count . 'Ix<ESC>`z'

I can use this by typing 10,x in normal mode, and it will both append and prepend 10 x characters to the current line, returning me to where I was.

That works fine.

What I'd like to do is this: First run 10,x, as before, but then have that sequence of work be stored in the q register as a macro, so I can run @q to repeat it.

I tried this, but it does not work:

nnoremap <expr> <leader>x 'qqmz' . v:count . 'Ax<ESC>' . v:count . 'Ix<ESC>`zq'

As you can see, I just added qq at the start (to begin recording a macro in the q register), and a final q at the end, to stop the macro recording.

If I type out these commands by hand, it works fine.

But when I have them inside nnoremap, it does not work.

What's going on here?

Upvotes: 0

Views: 1143

Answers (2)

DJMcMayhem
DJMcMayhem

Reputation: 7679

You've already figured out why this approach isn't working for you, because of q being disabled in mappings. Here is how you can get around it:

nnoremap <leader>x :<C-u>let @q='mz'.v:count.'Ax<C-v><ESC>'.v:count.'Ix<C-v><ESC>`z'<CR>@q

This simply enters the command you want directly into register 'q', and then afterwards runs it.

Upvotes: 3

jwd
jwd

Reputation: 11114

Ah, I missed this in the docs:

The 'q' command is disabled while executing a register, and it doesn't work inside a mapping and |:normal|.

(from :help q)

I guess what I want is just not possible without getting into vimscript, etc.

Upvotes: 1

Related Questions