Is it possible to show every n relative line numbers? So for example, I can see a a (+/-) 10, 20, 30... instead of a value on every line.

If there's no current way to do it, is it possible to create? i.e. can a plugin programmically change the line numbers shown?

  • 1
    I don't think you can do it without a little bit of scripting. You can look at :h sign to know how to place a sign in the singbar and use it as the number bar
    – nobe4
    Commented Aug 12, 2015 at 14:39

2 Answers 2


I made a little script that does nearly what you do.


The core concept behind it comes directly from the vim-signature plugin. Here is a step-by-step walkthrough :

  1. Remove all previous signs from the sign bar
  2. Build a list of the lines you want to show in the sign bar
  3. For each line, create a new sign with a unique id (based on current buffer and line number)
  4. For each line, display the sign (the text of the sign will be the current line)

The code below works as a proof of concept, but I wouldn't use is. You will see if you try it that it gets all flickering when you move quickly. I think the reason behind it is that the sign bar is not intended to quickly change over time.


There are also many optimisations I though of but didn't have the time to write :

  1. Create the list from the beginning (as the file lenght will not change a lot very quickly) and reload the list only when needed.
  2. Create 10 lists with all signs created. The cursor move will only change the current list displayed.
  3. Call refresh only on row change (not on every cursor change)
  4. Obviously it display only numbers (not relative), but you cannot display more than two characters into the sign bar ...

Show me the code !

There you go :

" List of all displayed lines
let b:lines = []

" Add a line to the signbar
function! AddLine(lnum)
  " create a unique id to the current sign
  let l:id = a:lnum * 1000 + bufnr('%')

  " Create a new sign and place it
  execute 'sign define Signature_' . l:id . ' text=' . a:lnum
  execute 'sign place ' . l:id . ' line=' . a:lnum . ' name=Signature_' . l:id . ' buffer=' . bufnr('%')

function! Remove(lnum)
  " Find the sign based on it's id and remove it
  let l:id = a:lnum * 1000 + bufnr('%')
  silent! execute 'sign unplace ' . l:id

" Create a list of all lines on the document to display
function! GetLines(currentLine) abort
  let l:c = a:currentLine % 10

  while l:c <= line('$')
    call add(b:lines, l:c)
    let l:c += 10

" Get called on every cursor move, reload the signs
function! Refresh()
  for j in b:lines
      call Remove (j)
  let b:lines = []

  call GetLines(line('.'))
  for j in b:lines
      call AddLine(j)

" Call the refresh method once on every cursor move
augroup CursorMove
  autocmd CursorMoved * call Refresh()
augroup END

I made a git repo for it if you want to contribute.


You can use my DynamicSigns plugin.

First Define a function like this:

fu! CustomSignExpression(lnum, div)
    if a:lnum < line('w0') || a:lnum > line ('w$')
        return 0
    if !exists("#SignExpression#CursorMoved")
        augroup SignExpression
            au CursorMoved * :Signs
        augroup end
    let part=abs(a:lnum - line('.'))
    if part % a:div == 0
        return part > 99 ? 99 : part
        return 0

Now you simply call :SignExpression CustomSignExpression(v:lnum, 5) if you want to have every fifth line a relative number.

The autocommand is there to make sure, the signs are redrawn on cursor movement (which by default only happens on text changes to not impact performance negatively). This means, that it might affect redraw performance of your Vim especially for larger Files and screen sizes.

Your Answer

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

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