vimtricks.wiki Concise Vim tricks, one at a time.

How do I create a normal mode mapping that correctly captures and passes a count prefix to a function?

Answer

nnoremap <key> :<C-u>call MyFunc(v:count)<CR>

Explanation

When writing custom mappings that call Vimscript functions, a common pitfall is that any count you type before the key (e.g., 5<Leader>j) gets prepended to the command line as a number, corrupting the command. The fix is <C-u>, which clears the command line before the : command runs, while v:count still holds the count you typed.

How it works

  • v:count — set by Vim to whatever count was typed before the mapping key (0 if none)
  • v:count1 — same but defaults to 1 instead of 0 when no count is given
  • <C-u> in command mode — deletes everything from the cursor to the start of the line, clearing any numeric prefix that Vim inserted
  • Without <C-u>: typing 5<key> produces :5call MyFunc(5) which is a range command — not what you want

Example

" Scroll down N half-pages, defaulting to 1
nnoremap <Leader>d :<C-u>call ScrollHalf(v:count1)<CR>

function! ScrollHalf(count)
  execute 'normal! ' . (a:count * &lines / 2) . 'j'
endfunction

Pressing 3<Leader>d calls ScrollHalf(3). Pressing <Leader>d alone calls ScrollHalf(1).

Tips

  • Use v:count1 (minimum 1) instead of v:count (minimum 0) when the count should default to 1
  • This pattern is essential for plugin mappings that accept counts
  • The same issue applies when calling execute 'normal! ...' — use <C-u> consistently

Next

How do I get just the filename without its path or extension to use in a command?