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

How do I pass special keys like Ctrl or arrow keys to :execute normal! in a Vimscript function or mapping?

Answer

:execute "normal! \<{key}>"

Explanation

When building dynamic :execute normal! calls in Vimscript, you must use double-quoted strings with the \<key> notation so Vim interprets the special key codes. Single-quoted strings are always literal — '\<C-a>' passes six characters (\, <, C, -, a, >) instead of the actual Ctrl-A key.

How it works

  • In double-quoted strings, "\<C-a>" produces a single byte: the Ctrl-A key code
  • In single-quoted strings, '\<C-a>' is a literal 6-character sequence — NOT a key code
  • :execute evaluates the string, so it is the string quoting that determines whether the key is resolved
" Correct — Ctrl-A increments the number under the cursor
execute "normal! \<C-a>"

" Wrong — passes literal characters, nothing happens
execute 'normal! \<C-a>'

Example

A function that increments the number under cursor N times:

function! IncrementN(count)
  execute "normal! " . a:count . "\<C-a>"
endfunction

This works because "\<C-a>" is the actual keycode, concatenated correctly into the :execute string.

Tips

  • Other examples: "\<CR>" for Enter, "\<Esc>" for Escape, "\<Tab>" for Tab, "\<Up>" for the up arrow
  • When building commands with feedkeys(), the same rule applies: use "\<key>" in double-quoted strings
  • In Neovim Lua, use vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes('\<C-a>', true, false, true), 'n', false) for the equivalent

Next

How do I highlight all occurrences of a yanked word without typing a search pattern?