How do I run normal mode commands in a script without triggering user-defined key mappings?
Answer
:normal! {cmd}
Explanation
When you use :normal {cmd} in a Vimscript function, macro, or Ex command, Vim expands any keys through the user's current mappings first. This can break scripts if the user has remapped common keys like j, k, w, dd, or even <Esc>. Adding ! — writing :normal! {cmd} — bypasses all user and plugin mappings and executes the raw, default Vim commands instead.
How it works
:normal {cmd}— runscmdin normal mode, applying user mappings:normal! {cmd}— runscmdin normal mode, ignoring all user mappings
For example, if a user has nnoremap j gj (for display-line movement), then :normal j executes gj, while :normal! j executes the real j (line-based movement). In a script doing range processing, the difference can break everything.
Example
A function to delete trailing whitespace on every line:
" Fragile: breaks if user remapped $ or d
function! TrimTrailing()
:%normal $d
dendfunction
" Correct: always uses default $ and d
function! TrimTrailing()
:%normal! $"_d
dendfunction
Or in a one-liner Ex command to jump to first non-blank on the last line:
:normal! G^
Tips
- Always use
:normal!in scripts, plugins, and functions unless you intentionally want to trigger the user's custom mappings - The same rule applies to
feedkeys(): usefeedkeys('cmd', 'n')to bypass mappings :normal!can still be limited byoperatorfuncand other hooks — for fully raw input,feedkeyswith the'x'flag is the ultimate escape hatch