Mappings โ€” :map, :noremap, and Friends

How to bind a keystroke to a command in every mode, and what the modifiers actually do.

Keys: :map, :nmap, :nnoremap, :vnoremap, :xnoremap, :onoremap, :inoremap, :cnoremap

Vim has one mapping system with a per-mode entry point. :nnoremap is the workhorse โ€” non-recursive normal-mode map. <silent>, <expr>, and <buffer> are the three modifiers that cover 90% of real mappings.

Mappings

A mapping binds a keystroke (or short sequence) to a command. It's how you build a personal layer on top of Vim's grammar โ€” leader shortcuts, plugin bindings, language-specific helpers. The mapping system has more knobs than most people realize, and most of the bugs in handwritten vimrcs come from picking the wrong knob.

Per-mode commands

Mappings are scoped to a mode. Picking the right command (instead of bare :map) is the single most important habit.

Command Mode it affects When to use
:nmap Normal Bindings that act on the buffer from rest. The default for almost every leader mapping.
:imap Insert Live-while-typing shortcuts โ€” autopairs, abbreviation-like helpers, completion triggers.
:vmap Visual and Select Rarely what you want; the Select half eats keystrokes meant as text. Prefer xmap.
:xmap Visual only (not Select) Visual-mode bindings (e.g. > to indent and re-select).
:smap Select only Almost never. Select mode behaves like a text-replacing selection (think other editors).
:omap Operator-pending Custom motions and text objects. After d/c/y, your map fires.
:cmap Command-line Bindings on the : / / / ? prompt.
:tmap Terminal-job Bindings inside :terminal buffers (Neovim and newer Vim).
:map Normal + Visual + Select + Op-pending The bare form. Almost always too broad.
:map! Insert + Command-line The other broad form. Sometimes useful for Ctrl-chords you want everywhere you type.

map vs noremap โ€” the one you almost always want

Every mode has a nore variant: :nnoremap, :inoremap, :vnoremap, etc. The nore prefix means non-recursive: the right-hand side is interpreted using Vim's built-in commands, not other mappings.

Without nore, your mapping can be re-mapped by another mapping. :nmap j gj then :nmap gj jjj will loop. With :nnoremap j gj, the gj on the right is the built-in gj, and the mapping is safe. Use nore everywhere unless you have a specific reason not to. "Specific reason" is almost always: you want to invoke another plugin's mapping deliberately.

The three modifiers that matter

Modifier What it does When to use
<silent> Don't echo the right-hand side on the command line as the mapping runs. Almost always for mappings that call commands. Without it, the :somecmdEnter flicker is visible every keystroke.
<expr> Evaluate the right-hand side as a Vimscript expression; the result is what gets typed. Conditional mappings โ€” "if the popup menu is visible, do X; otherwise do Y." The classic <expr> use-case is wiring Tab for completion.
<buffer> Mapping applies only in the current buffer. Stored on the buffer, gone when the buffer is wiped. Filetype-specific mappings set from ftplugin/. Keeps your Python bindings out of your Markdown buffers.

Modifiers go before the keystroke, in any order:

nnoremap <silent> <leader>w :write<CR>
inoremap <silent> <expr> <Tab> pumvisible() ? "\<C-n>" : "\<Tab>"
nnoremap <silent> <buffer> <leader>r :!python %<CR>

See also: Operator-Pending Mode, Vim Configuration, Setting Options ({key::set})