I use the following mappings to toggle relative numbers in visual mode:

nnoremap <silent> v v:<c-u>set nonu rnu<cr>gv
nnoremap <silent> V V0:<c-u>set nonu rnu<cr>gv
nnoremap <silent> <c-v> <c-v>:<c-u>set nonu rnu<cr>gv
vnoremap <esc> <esc>:set nornu nu<cr>

I would like to use the same mappings, but add a conditional check before performing the operation to exclude certain buffers types from this behavior.

I tried adding this to a function but was not successful.

Does anyone know how I can achieve this?

  • 1
    Perhaps you could edit to show what you tried? Then we can point out the missing ideas
    – D. Ben Knoble
    Dec 13, 2020 at 19:37
  • @D.BenKnoble I'm not sure how helpful it would be. I just wrapped set nonu rnu<cr>gv into a function and tried calling it. What's the problem you're having with understanding the question?
    – Nathan
    Dec 13, 2020 at 20:04
  • 3
    I’m not misunderstanding it, per se, but it’s often easier to say “well X doesn’t work because A and B, do Y instead” then to say “do you want Z?” In this case, you need to learn the difference between the right-hand-side of map commands (happen in the mode of the mapping) and functions (always Ex commands)—but I didn’t know that’s the issue until I saw your function body
    – D. Ben Knoble
    Dec 13, 2020 at 20:12

2 Answers 2


Function bodies are pure Ex, so you need (e.g.)

normal! v
set nonumber norelativenumber
normal! gv

Though note that between :normal! v and :normal! gv, the commands aren’t like the mapping where you are literally typing : and then have to delete the range <C-u> etc.

Simpler here would just be

set nonumber norelativenumber
normal! v

However, this may not leave you in visual mode! :normal! works better with complete commands.

As a solution, you could try and expr mapping and

return 'v'

Or just insert the function call between v and gv with :<C-u>call MyFunction()<CR>.

  • Thanks @D.BenKnoble. I'll give it a shot and will report back. Much appreciated.
    – Nathan
    Dec 13, 2020 at 23:24
  • Works great. I posted my final solution in my original question. Cheers!
    – Nathan
    Dec 15, 2020 at 0:29
  • @Nathan I think it would be more appropriate if you posted that as an answer, rather than an edit of your question. There's a small drawback in the way you've implemented it, in that V and Ctrl-V will now trigger characterwise visual mode rather than linewise/blockwise... Perhaps leave the normal! v out of the function and run that in the mappings after the toggle command has been executed?
    – filbranden
    Dec 15, 2020 at 0:31
  • @filbranden sounds good. I just posted it as an answer. Would you mind showing how to run that in the mappings after the toggle command has been executed. I'm not versed enough in vimscript to understand what you mean.
    – Nathan
    Dec 15, 2020 at 0:34

Here's what I put together based on @D.BenKnoble answer (with help from @filbranden):

function! s:relativeLineNumbers()
  if (&filetype != 'coc-explorer')
    set nonu rnu
command RelativeLineNumbers call s:relativeLineNumbers()
nnoremap <silent>v v:<c-u>RelativeLineNumbers<cr>gv
nnoremap <silent>V V0:<c-u>RelativeLineNumbers<cr>gv
nnoremap <silent><c-v> <c-v>:<c-u>RelativeLineNumbers<cr>gv
vnoremap <esc> <c-c>:set nornu nu<cr>

Note: I selected his answer rather than my own however.

  • 1
    Try this: nnoremap <silent> V :ToggleRelativeLineNumbers<cr>V and remove the normal! v from the function...
    – filbranden
    Dec 15, 2020 at 0:56
  • Worked perfectly! Thank you.
    – Nathan
    Dec 15, 2020 at 1:01
  • 1
    Awesome! Please update your answer with the settings that worked for you. I'll be happy to upvote it once you do!
    – filbranden
    Dec 15, 2020 at 1:18
  • 1
    Done! Cheers!!!
    – Nathan
    Dec 16, 2020 at 2:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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