Vim provides the count modifier, which is used to multiply or add iterations to a command. If you use vim, you are probably familiar with it: It allows you to write 50j
to move down 50 times.
Occasionally I manage to enter a big number without noticing, while I am actually using other applications. When I then proceed to use vim and for example type o
to begin a new line, vim naturally tries to create a huge amount of new lines, which slowly fills up the memory and then gets killed by the kernel OOM killer.
Is there any way to limit the counter or to add a confirmation if it is greater than some threshold?
This almost works:
function! UpdateCount(n) abort
let limit = get(g:, 'counter_limit', 99)
if v:count == 0
return ''.a:n
elseif v:count == limit
return ''
elseif 10 * v:count + a:n > limit
return repeat("\<Del>", strlen(v:count)).limit
else
return ''.a:n
endif
endfunction
nnoremap <expr> 0 UpdateCount(0)
nnoremap <expr> 1 UpdateCount(1)
nnoremap <expr> 2 UpdateCount(2)
nnoremap <expr> 3 UpdateCount(3)
nnoremap <expr> 4 UpdateCount(4)
nnoremap <expr> 5 UpdateCount(5)
nnoremap <expr> 6 UpdateCount(6)
nnoremap <expr> 7 UpdateCount(7)
nnoremap <expr> 8 UpdateCount(8)
nnoremap <expr> 9 UpdateCount(9)
But, unfortunately, it doesn't work for the 0
key, since Vim disables any mappings for 0
while entering a count, which makes sense since 0
by itself is the command to go to the first character of the line and if these mappings weren't disabled then a command such as nnoremap 0 ^
would break usage of 0
in counts...
So, yeah, other than patching Vim to add a limit, I don't really see a good way to fix this in general.
If this is a problem with some commands more than others (i.e. insertion commands, such as o
or i
or A
, etc.) then you might want to consider adding a mapping to those, inspecting v:count
in those and preventing them if the count is above a certain limit.
For example:
function! LimitCount(cmd) abort
let limit = get(g:, 'counter_limit', 99)
if v:count > limit
echomsg "Count ".v:count." is too large, aborting execution of '".a:cmd."' command."
" Use Ctrl-C to erase the pending count and avoid applying it to the next command.
return "\<C-C>"
else
return a:cmd
endif
endfunction
nnoremap <expr> o LimitCount('o')
nnoremap <expr> i LimitCount('i')
" And so on for other insertion commands...