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

How do I get the current Vim mode as a string for use in expression mappings or the statusline?

Answer

mode()

Explanation

The mode() function returns a short string identifying the current editing mode — 'n' for Normal, 'i' for Insert, 'v' for Visual character-wise, 'V' for Visual line-wise, and so on. This enables conditional logic inside <expr> mappings and statusline expressions, letting a single definition adapt to context.

How it works

  • mode() returns a one- or two-character string representing the active mode
  • Common values: 'n' (Normal), 'i' (Insert), 'v' (Visual char), 'V' (Visual line), "\<C-v>" (Visual block), 'c' (Command-line), 'R' (Replace), 't' (Terminal)
  • Passing 1 as an argument (mode(1)) returns a longer string with extra info (e.g. 'niI' when i is pending)
  • Most useful inside <expr> mappings (which evaluate the RHS as an expression) and %{...} statusline segments

Example

Make <CR> insert a blank line in Normal mode but act normally in other modes:

nnoremap <expr> <CR> mode() ==# 'n' ? 'o<Esc>' : "\<CR>"

Display a human-readable mode label in the statusline:

function! ModeLabel() abort
  let l:map = {'n': 'NORMAL', 'i': 'INSERT', 'v': 'VISUAL',
             \ 'V': 'V-LINE', "\<C-v>": 'V-BLOCK', 'R': 'REPLACE', 'c': 'CMD'}
  return get(l:map, mode(), mode())
endfunction
set statusline=%{ModeLabel()}\  %f

Tips

  • Always use ==# (case-sensitive equality) when comparing mode strings — mode() values are case-sensitive
  • In Neovim, :echo mode() works interactively; entering : returns 'c', confirming the function works even in Command-line mode
  • The companion visualmode() function returns the type of the most recent Visual selection ('v', 'V', or "\<C-v>") even after you leave Visual mode — useful in operator-pending functions that need to know the selection type

Next

How do I encode and decode JSON data in Vimscript for configuration and plugin development?