jwd
jwd

Reputation: 11134

vim: strange v:count behavior in normal-mode mapping

I'm working on a normal-mode mapping, and stumbled upon some surprising behavior:

First, here is a mapping that works, and does what I want:

nnoremap <expr> <leader>_ ':<C-U>normal' . v:count . 'Ix<ESC>'

So I can type 3,_ (, is my leader character) and insert 3 x characters.

No problem. However, I would expect this simpler one to work, too:

nnoremap <expr> <leader>_ v:count . 'Ix<ESC>'

But with that, if I type 3,_, it inserts 33 x characters. If I use 4,_, I get 44, etc.

What's going on, here?

More importantly, does anybody know a good way to debug this stuff, so I can see how that expression is getting expanded, and not have to ask on SO every time I have an issue like this?

Upvotes: 1

Views: 287

Answers (1)

Peter Rincker
Peter Rincker

Reputation: 45157

First here is your fixed mapping:

nnoremap <leader>_ Ix<ESC>

The {count} will be passed into the I command by default. Unless the count is being passed into a different part of your mapping you can often just leave it out.

Why does the following mapping work?

nnoremap <expr> <leader>_ ':<C-U>normal' . v:count . 'Ix<ESC>'

The count is being passed into the :normal command here, but this mapping is using <c-u> to clear out the {count}/range. You can see count in action by doing 3: vs 3:<c-u>. So without the <c-u> this mapping would yield:

:.,+2normal 3Ix<ESC>

With the <c-u> your mapping will yeild:

:normal 3Ix<ESC>

Why does the following mapping not work?

nnoremap <expr> <leader>_ v:count . 'Ix<ESC>'

Simply using v:count does not clearing the current {count}. You need to clear the {count} directly or create a mapping that takes advantage of it. As this is an expression mapping the following 3,_ will convert to 33Ix<ESC>. Where the first 3 is given count and 3Ix<ESC> is what the expression returned.

Upvotes: 1

Related Questions