How to Treat j and k as Jumps in Vim?

The aim is to explore how we can enhance Vim’s navigation by treating j and k motions (preceded by counts) as jumps.

Pavol Kutaj

--

TL;DR > Paste the following into your .vimrc...

nnoremap <expr> k (v:count > 1 ? "m'" . v:count : '') . 'gk'
nnoremap <expr> j (v:count > 1 ? "m'" . v:count : '') . 'gj'

Why?

First, because:

When you make a jump to a position with the “G” command, Vim remembers the position from before this jump. This position is called a mark. To go back where you came from, use this command: `` … But not the character searches with “fx” and “tx” or the word movements “w” and “e”. Also, “j” and “k” are not considered to be a jump, even when you use a count to make them move the cursor quite a long way away.

https://vimhelp.org/usr_03.txt.html#03.10

Second, because:

…utilize relative numbers to race from one line to another. This method relies on using a count + directional key. So, 4j will move me down four lines from where I currently am within Vim. This seems well enough, but actually has a hidden weakness.

Understanding Vim’s Jump List. One of the great joys of Vim is its… | by Kade Killary | Medium

This is powerful in combination with relative line numbering. For a definite treatment of that subject, see https://jeffkreeftmeijer.com/vim-number/.

We’ll achieve treating <count>j and <count>k as jumps through custom mappings.

Jump Lists:

  • Vim maintains a jump list to keep track of cursor movements within a file.
  • Each time you move your cursor to a different location, Vim records these jumps.
  • The jump list is essential for efficient navigation through your editing history.

What Qualifies as a Jump?:

  • Not all cursor motions are considered jumps.
  • However, j (downward) and k (upward) are not natively treated as jumps by Vim.

The Problem with j and k:

  • Suppose you use 4j to move down four lines.
  • Vim doesn’t consider this a jump, so you can’t easily return to the previous position using the `` (backtick) command.

Custom Mappings to the Rescue:

  • We’ll create custom mappings in our .vimrc configuration file.
  • These mappings will make j and k behave like jumps, ensuring they're recorded in the jump list.

The Configuration Change:

  • Open your .vimrc (or create one if it doesn't exist).
  • Add the following lines:
nnoremap <expr> k (v:count > 1 ? "m'" . v:count : '') . 'gk'
nnoremap <expr> j (v:count > 1 ? "m'" . v:count : '') . 'gj'

Let’s break down what these mappings do:

  • nnoremap: Non-recursive mapping for normal mode.
  • <expr>: Indicates that the right-hand side of the mapping is an expression.
  • k and j: Our target keys.
  • (v:count > 1 ? "m'" . v:count : ''): This part checks if a count is provided (e.g., 4k).
  • If a count exists, it sets a mark (m') at the current position.
  • The v:count variable holds the count value.
  • 'gk' and 'gj': These are the actual motions (upward and downward).

Example Usage:

  • Suppose you move down 4 lines with 4j.
  • Pressing CTRL-o will take you back to the previous position.

--

--

Pavol Kutaj

Today I Learnt | Infrastructure Support Engineer at snowplow.io with a passion for cloud infrastructure/terraform/python/docs. More at https://pavol.kutaj.com