2

I use (Neo)Vim with mouse=a and scrolloff=5.

Clicking on one of the top or bottom five lines with the mouse causes the screen to jump (so that the new cursor position is more centered), which distracts me.

Is there any way to disable "so=5" for mouse-clicking only?

6
  • I'm not sure how that could work: scrolloff set a minimal number of lines below or above the cursor line. Disabling the option "only for mouse click" would mean that you don't have this minimal number of lines between the cursor line and the edge of the screen but how would vim know when to set this minimal number of lines again?
    – statox
    Apr 7, 2019 at 17:25
  • @statox preferably at the next vertical movement
    – 0x539
    Apr 7, 2019 at 17:25
  • 1
    I'm pretty sure it's not possible to do what you want. You could try to use a mapping like nnoremap <leftmouse> :set scrolloff=0<CR><leftmouse> to disable scrolloff when you click and then remap the motion you want to reenable the option but that seems very impractical.
    – statox
    Apr 7, 2019 at 17:29
  • Do you need the answer to be a setting in vimrc or you need it to be a mouse-and-keyboard combination?
    – tivn
    Jun 22, 2019 at 12:50
  • @tivn preferably a vimrc setting, but a mouse-and-keyboard combination would help too.
    – 0x539
    Jun 22, 2019 at 13:18

4 Answers 4

2

One of the beautiful things about Vim is that often this kind of customisation is not only possible, but relatively straightforward:

function! DisableScrollOff() abort
  " Save the current scrolloff
  let w:current_scrolloff = &scrolloff

  " Disable scrolloff
  setlocal scrolloff=0
endfunction

function MouseScrollOffAutocommand() abort
  let w:current_line = line('.')
 
  " Set up an autocommand to reenable scrolloff
  augroup mouse_scrolloff
    autocmd!
    autocmd CursorMoved * call ReenableScrollOff()
  augroup END
endfunction

function ReenableScrollOff() abort
  if ShouldReenable()
    let &l:scrolloff = w:current_scrolloff
  endif
endfunction

function ShouldReenable() abort
  return exists('w:current_scrolloff') &&
    \ winline() > w:current_scrolloff &&
    \ winline() <= winheight(0) - w:current_scrolloff

  return line('.') != w:current_line
endfunction

nnoremap <LeftMouse> :call DisableScrollOff()<CR><LeftMouse>:call MouseScrollOffAutocommand()<CR>

This works by making a note of the current 'scrolloff' when you click with the mouse and then disabling it. It then reenables 'scrolloff' once you have moved the cursor back out of the area where the option usually applies.

I think this is less jarring than enabling it as soon as you move the cursor vertically, especially with larger values of 'scrolloff'.

Disclaimer: I wrote the above several months if not years ago. I can't remember if I just didn't get around to posting it as an answer, or if there was some edge case I wanted to fix before doing so. If you discover any problems with it, please let me know!

0

Try the following: hold down shift key before you press mouse button.

6
  • Since I use neovim in the terminal this results in my terminal trying to select text.
    – 0x539
    Jun 22, 2019 at 14:23
  • what’s the purpose you need to click there?
    – tivn
    Jun 22, 2019 at 14:29
  • What’s the purpose of “Clicking on one of the top or bottom five lines” ?
    – tivn
    Jun 22, 2019 at 14:33
  • usually the purpose is to move the cursor to that line.
    – 0x539
    Jun 22, 2019 at 14:34
  • That’s of course would not possible :-)
    – tivn
    Jun 22, 2019 at 14:35
0

If you want to avoid test scrolling when you mouse-click at edges of the window, you can simply set scrolloff to 0, see comments in /usr/share/vim/vim80/defaults.vim(ubuntu 1804):

" Show a few lines of context around the cursor.  Note that this makes the
" text scroll if you mouse-click near the start or end of the window.
set scrolloff=5

Note that you have to set scrolloff=0 after sourcing the above defaults.vim if you are using .vimrc copied from vimrc_example.vim, on Ubuntu for example, set it like:

" Get the defaults that most users want.
source $VIMRUNTIME/defaults.vim
set scrolloff=0
1
  • 1
    Hi, welcome! The OP wants to set scrolloff to a non-zero value. Thus, I'm not quite sure your answer is relevant.
    – Biggybi
    Feb 23, 2021 at 12:23
0

This occurs to me:

nnoremap <leftmouse> :let oldso = &scrolloff <bar> let &scrolloff = 0<CR><leftmouse>:let &scrolloff = oldso <bar> unlet oldso<CR>

Save the old value, set to 0; do the mouse click; restore the value.

2
  • This seems to produce identical results to regular <leftmouse>. Am I missing something?
    – 0x539
    Mar 25, 2021 at 19:50
  • I see the problem @0x539 : because scrolloff is restored immediately afterwards, there is still a jump. You could leave off the restore and define another mapping/command to restore (e.g., command RestoreScroll let &scrolloff = oldso | unlet oldso), but you would have to call it yourself when you wanted it.
    – D. Ben Knoble
    Mar 25, 2021 at 19:53

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.