How to make `Ctrl-d` and `Ctrl-u` scroll 1/3 of window height

I used to have these lines in my old vimscript config which allowed me to scroll a third of the window height (instead of the default half) with Ctrl+d and Ctrl+u:

" Scroll by a third of window height (https://stackoverflow.com/a/16574696/1706778)
execute "set scroll=" .&lines / 3
au VimResized * execute "set scroll=" . &lines / 3

I ported it to my new lua config file as follows:

-- Scroll by a third of window height (https://stackoverflow.com/a/16574696/1706778)
vim.cmd [[ execute "set scroll=" .&lines / 3 ]]
vim.cmd [[ au VimResized * execute "set scroll=" . &lines / 3 ]]

However, the VimResized event doesn’t seem to trigger.

I tried this simpler autocommand:

vim.cmd [[ au VimResized * echo "Vim Resized!" ]]

but whenever I create a horizontal split, or change the size of the window, the text is not printed.

Any idea what could be the problem?

EDIT: I’m also noticing that the scroll option is being reseted when a split window is closed, and it’s not the autocommand that I defined that’s doing it.

EDIT 2: For the question above, I did find the answer in the docs:

  				*'scroll'* *'scr'*

‘scroll’ ‘scr’ number (default: half the window height)
local to window
Number of lines to scroll with CTRL-U and CTRL-D commands. Will be
set to half the number of lines in the window when the window size
changes. This may happen when enabling the |status-line| or
‘tabline’ option after setting the ‘scroll’ option.
If you give a count to the CTRL-U or CTRL-D command it will
be used as the new value for ‘scroll’. Reset to half the window
height with “:set scroll=0”.

So it is being reseted by nvim when the window size changes. The question is: How can I override it so that it sets scroll to 33% of the current window size.

2 Likes

The VimResized event fires when the window containing Vim itself is resized, i.e. your terminal emulator or GUI window. Unfortunately, there is no event that fires when Vim’s internal windows are resized.

Before I go on, you should know that the lines option also refers to the window containing Vim, and not a window within Vim. Relying on the value of lines will not give you the result that you intended to get; you want winheight() instead. Please note that this is not the same as the winheight option.

If you want to stay on the autocommand route, you would have to use some combination of Win(Enter|Leave|New), VimEnter (for the initial window), CursorHold, and InsertLeave to keep scroll in sync. This isn’t particularly efficient, however. Instead, I would suggest remapping Ctrl+D and Ctrl+U to something like the following:

nnoremap <expr> <C-d> (winheight(0) / 3) . '<C-d>'
nnoremap <expr> <C-u> (winheight(0) / 3) . '<C-u>'

This takes advantage of the fact that giving a count to Ctrl+D or Ctrl+U sets scroll and then scrolls, as mentioned in the help snippet you referenced. This should accomplish what you want without the need to rely on autocommands.

5 Likes