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 :executeevaluates 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