2

I was very excited to see the relative line number feature in vim. Now vertical navigation would be a breeze, and instead of typing huge numbers, I can simply do 10j to move 10 lines down. However, after doing some research, it seems this way of "moving down" (I wont call it jumping) is not remembered or placed in the jumplist. My question is if there is a way for me to have this mechanism placed there so I could remember my previous cursor locations. Is there a plugin that might assist in this matter?

1 Answer 1

6

You don't need a plugin, all you need is two lines of vimscript!

If you would like every time you press 'j' or 'k' to be added to the jumplist, this is pretty easy. You could do it with this:

nnoremap <silent> j :<C-u>exe "normal! m'".v:count1."j"<cr>
nnoremap <silent> k :<C-u>exe "normal! m'".v:count1."k"<cr>

Essentially, this just makes it so when you press j or k, vim act as if you had pressed m' right before the j or k. m' is just adds your current location to the jumplist. From :help m':

                        *m'* *m`*
m'  or  m`      Set the previous context mark.  This can be jumped to
            with the "''" or "``" command (does not move the
            cursor, this is not a motion command).

However, it could be obnoxious to have every single time you press j or k to be added to the jumplist. We can make it be added to the jumplist only if you provide a count.

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

This is more convenient, since it will not clutter up your jumplist.

How it works:

So first, the obvious part. nnoremap k means, "When I press 'k', act as if I had typed this instead". The <silent> is just to prevent messages from being echoed when the command is executed.

Then, on the righthand side, we have :<C-U>execute 'normal!' (v:count > 1 ? "m'" . v:count : '') . 'k'<CR>. The <C-u> is needed for any mapping involving ex commands. You can read about what it does here. Now, the execute command allows us to execute a string as an ex command, and "'normal!' (v:count > 1 ? "m'" . v:count : '') . 'k'<CR>" evaluates to a string. v:count is a special variable that vim sets when you call a mapping with a count. So, for example, if you type 2j, it will set v:count to equal 2. Using the ternary operator, which you should be familiar with if you've done much programming, is used to evaluate this whole expression to either normal! m'<n>k if count is greater than 0, or normal! k if it is not.


Credit goes to this super user thread!

6
  • I am going to try this when i get back to my machine and post back. Thank you again for posting. This is a life saver Aug 6, 2016 at 21:22
  • @JamesFranco Glad I could help, that's exactly why I enjoy writing these answers!
    – DJMcMayhem
    Aug 6, 2016 at 21:23
  • I have no experience reading vim script but from what I understand is that you are setting up a mark when ever a count is provided with k and j is that correct ? and the marks name is the motion that was performed like 3j then the mark would be 3j ? Also I did not know that marks also show up in the jump list Aug 6, 2016 at 21:26
  • @JamesFranco Not quite. Let me post a more thorough explanation.
    – DJMcMayhem
    Aug 6, 2016 at 21:27
  • @ DJMcMayhem I would love to read a thorough explanation when ever you get a chance to write one. Aug 6, 2016 at 21:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.