The Ultimate Vim j/k Binding

As a user of relativenumber, I get a bit more mileage out of j and k than many Vim users. It enables me to quickly see how far away I am from a line, making jumps like 28j easy and practical. However, relativenumber works with lines delimited by newline characters, not the lines you see on the screen. And if a line wraps, j and k will move by text lines, not visual lines, causing awkward jumps. Because of this, may users have this in their .vimrcs:

nnoremap j gj
nnoremap k gk

But, since j and k no longer act on text lines, 23j may no longer go the the line marked 23 in the gutter. If there is a wrapped line between the cursor and the target, it will actually take multiple presses of j to pass that line, meaning that the cursor's end position will be too high. A good way to get around this would be to have single presses of j and k act as gj and gk while j and k with a count would act normally.

The other issue that bothered me was that large j and k jumps didn't get added to the jumplist, meaning that there was no easy way to undo and redo them. That can be fixed by automatically setting the ' mark if j or k is executed with a count.

So, without further ado, this is what I've come up with:

nnoremap <silent> k :<C-U>execute 'normal!' (v:count > 1 ? "m'" . v:count : 'g') . 'k'<CR>
nnoremap <silent> j :<C-U>execute 'normal!' (v:count > 1 ? "m'" . v:count : 'g') . 'j'<CR>

This does the following:

It's not perfect - in visual mode, j and k revert to their normal definitions, but I'm really enjoying its more intuitive behaviour in normal mode.

comments powered by Disqus