How do I run a dynamically constructed Ex command or pass special keys to :normal?
Answer
:execute
Explanation
:execute evaluates a string as an Ex command, letting you build commands dynamically or embed special key sequences (like <CR> or <Esc>) as literal characters. It is the standard way to run computed commands in mappings, autocommands, and scripts.
How it works
:execute "command"— evaluates the string and runs it as an Ex command- String concatenation (
..in Vim 8+, or.in older Vim) builds the command dynamically - Special key names inside double quotes are interpreted:
"\<CR>"becomes an actual Enter key - This is the key difference from
:normal::normal ggjj<CR>cannot send a real Enter key, but:execute "normal! gg\<CR>"can
Example
Search for the word under the cursor dynamically:
:execute "normal! /" . expand('<cword>') . "\<CR>"
This constructs /keyword and sends Enter as a real keystroke — something :%s patterns or literal :normal cannot do cleanly.
Or prompt for a pattern and substitute throughout the file:
:execute "%s/" . input('Find: ') . "/" . input('Replace: ') . "/gc"
Tips
- Always use
normal!(with bang) inside execute to ignore user mappings - Use
shellescape()when building shell commands with!orsystem() executecan concatenate a list::execute join(['%s', 'foo', 'bar', 'g'], '/')- In Neovim Lua, use
vim.cmd(string.format(...))for the same pattern