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

How do I make j and k navigate display lines normally but physical lines when given a count?

Answer

nnoremap <expr> j v:count == 0 ? 'gj' : 'j'

Explanation

By default, j and k move by physical lines (newline-delimited), which jumps over the entire visual span of a long wrapped line in a single keystroke. The <expr> mapping attribute lets the right-hand side be a Vimscript expression evaluated at key-press time, so you can switch behavior based on whether a count was given.

How it works

  • nnoremap <expr> creates a normal-mode mapping whose RHS is a Vimscript expression
  • v:count holds the numeric count prefix typed before the key (0 if none was given)
  • When no count is given (v:count == 0), the expression returns 'gj' to move by display line
  • When a count is given (e.g., 5j), it returns 'j' to move by physical line — essential for jumping to a specific relative line number

Add both mappings to your vimrc:

nnoremap <expr> j v:count == 0 ? 'gj' : 'j'
nnoremap <expr> k v:count == 0 ? 'gk' : 'k'

Example

With a long paragraph that wraps across three display lines:

  • j — moves down one display line within the paragraph (same as gj)
  • 3j — jumps exactly 3 physical lines, bypassing display-line logic

Tips

  • Pair with set relativenumber so count-based jumps (5j, 12k) align with the displayed line numbers
  • Extend to visual mode: vnoremap <expr> j v:count == 0 ? 'gj' : 'j'
  • The same pattern works for any key that should behave differently with vs without a count prefix

Next

How do I define custom fold marker strings instead of the default {{{ }}} in Vim?