If you want your Vim line numbers to be relative and/or not relative at the correct times, I recommend installing the myusuf3/numbers.vim plugin.
When editing text in a Vim window, I use relative numbers to help me use motions across text relative to my cursor. However, when I have multiple windows open, relative numbers look pretty weird in windows that I am not currently editing. It would be nice for Vim to intelligently alternate between relativenumber and norelativenumber based on my Vim cursor location. Base Vim does not have this capability, so we have three options:
- Accept a suboptimal workflow
- Wrap our own solution in our .vimrc
- Find a Plugin
I lived with option 1 for a while, but eventually grew too annoyed. I then tried researching plugins, but thought I understood the problem well-enough to write my own solution. So I went straight to option 2 and tried wrapping my own solution.
Wrapping my own solution
The following code represents my original solution:
1 function! ToggleRelativeNumber() 2 if &rnu 3 set norelativenumber 4 else 5 set relativenumber 6 endif 7 endfunction 8 9 function! RNUInsertEnter() 10 if &rnu 11 let w:line_number_state = 'rnu' 12 set norelativenumber 13 else 14 let w:line_number_state = 'nornu' 15 endif 16 endfunction 17 18 function! RNUInsertLeave() 19 if w:line_number_state == 'rnu' 20 set relativenumber 21 else 22 set norelativenumber 23 let w:line_number_state = 'nornu' 24 endif 25 endfunction 26 27 function! RNUWinEnter() 28 if exists('w:line_number_state') 29 if w:line_number_state == 'rnu' 30 set relativenumber 31 else 32 set norelativenumber 33 endif 34 else 35 set relativenumber 36 let w:line_number_state = 'rnu' 37 endif 38 endfunction 39 40 function! RNUWinLeave() 41 if &rnu 42 let w:line_number_state = 'rnu' 43 else 44 let w:line_number_state = 'nornu' 45 endif 46 set norelativenumber 47 endfunction 48 49 " autocmd that will set up the w:created variable 50 autocmd VimEnter * autocmd WinEnter * let w:created=1 51 autocmd VimEnter * let w:created=1 52 set number relativenumber 53 augroup rnu_nu 54 autocmd! 55 "Initial window settings 56 autocmd WinEnter * if !exists('w:created') | 57 \setlocal number relativenumber | 58 \endif 59 autocmd User Startified setlocal number relativenumber 60 " Don't have relative numbers during insert mode 61 autocmd InsertEnter * :call RNUInsertEnter() 62 autocmd InsertLeave * :call RNUInsertLeave() 63 " Set and unset relative numbers when buffer is active 64 autocmd WinEnter * :call RNUWinEnter() 65 autocmd WinLeave * :call RNUWinLeave() 66 augroup end
The solution worked for most windows and tabs, most of the time.
The code is a bit involved and it takes a little time to explain to others.
- It relies on window-local variables (w:line_number_state, etc). These exacerbate Vim's already-difficult state-management woes.
- Several global functions are defined
- There are some quirks I don't fully understand around the creation of variables during Vim startup (hence lines 50 and 51).
Despite these mild downsides, I was pretty proud that the solution mostly worked. That is, until I wasn't.
The back-breaking straw
My custom solution did not work appropriately with some of my plugins. Namely, it didn't play well with majutsushi/tagbar, which I use frequently enough for this feature-dearth to become royally annoying. Therefore, after learning the ins-and-outs of window-specific variables and every Vim autocmd, I went back to the Plugin ecosystem to see if I'd missed anything...
The Game-Changing Plugin
Turns out a wonderful developer already solved this problem for me. Assuming you use junegunn/vim-plug to manage your plugins, place the following code in your .vimrc
call plug#begin('~/.vim/plugged') " Relative Numbering Plug 'myusuf3/numbers.vim' " Put the rest of your plugins below... call plug#end() " Now, exclude the plugins you don't want numbers to deal with let g:numbers_exclude = ['startify', 'gundo', 'vimshell']
This will give you a great editing experience. See below for a screencast:
Numbers.vim provides a usable line-numbering solution with minimal required configuration. I regret nothing about my bespoke journey, but I'm glad that Numbers.vim is my destination.