2

Is there a way to get 10 lines above and beneath the current cursor?

Similar to set scrolloff=10 but I only want to do it ONCE, not change the setting...

Clarification: I want at least 10 lines. If there's already 10+ lines above and below the cursor then the command shouldn't change anything. zz and z. are close but they do a little too much.

Sorry for the exacting request, I'm not sure there's an easy way to do this

  • Does z. do what you want? – Christian Brabandt May 7 at 20:39
  • @ChristianBrabandt Or zz which is the same but leaves the cursor in the same column... – filbranden May 7 at 20:53
  • 1
    Thanks for the suggestions! z. and zz are close to what I need but if the cursor is already close to center then I don't want to move it. Sorry to be choosy! @ChristianBrabandt @filbranden – NDavis May 7 at 21:13
  • 1
    @filbranden ah yes, I remember. I tend to ignore that command, because it is so close to ZZ – Christian Brabandt May 8 at 5:57
  • 1
    It can be done with a mapping and a function... If I have some time tomorrow I'll see if I can write something that does that. – filbranden May 8 at 7:11
2

The brute force way to do it:

:let scrolloff_before = &scrolloff | set scrolloff=10 | redraw | let &scrolloff = scrolloff_before | unlet scrolloff_before

This works by saving the current 'scrolloff' value in a variable, setting it to 10, redrawing the screen so the update is applied (which is necessary because we are running all the commands in a single command-line), and then resetting 'scrolloff' to the original value. Finally, we remove the variable, which isn't really necessary but it's nice to be tidy.

Obviously you don't want to type that in every time, so you can make a command by adding the following to your .vimrc:

command ScrollOff10 let s:scrolloff_before = &scrolloff | set scrolloff=10 | redraw | let &scrolloff = s:scrolloff_before

As we're now in a script, we can use script-local variables to decrease the chances of our variable overwriting a pre-existing one (and we don't bother to unlet it, as it's not visible outside the script.

Or a mapping:

nnoremap <F1> :let s:scrolloff_before = &scrolloff<CR>:set scrolloff=10<CR>:let &scrolloff = s:scrolloff_before<CR>

This version doesn't need the :redraw either, because instead of concatenating the commands with :bar, we're entering them one at a time with (mapped) presses of the Return key.

| improve this answer | |
2

This is essentially packing @Rich's solution (temporarily setting 'scrolloff') into a function, to improve readability.

I'm also defining a command and a mapping with a little bit more of flexibility (allowing a custom offset to be specified through a "count") and usability.

function! ScrollOffset(offset)
    let save_scrolloff = &l:scrolloff
    let &l:scrolloff = a:offset ? a:offset : 10
    redraw
    let &l:scrolloff = save_scrolloff
endfunction

command! -bar -count=0 ScrollOffset call ScrollOffset(<count>)

nnoremap <silent> z. :<C-u>call ScrollOffset(v:count)<CR>

You can employ it by using one of the following commands:

  • z. to scroll with a default of 10
  • :ScrollOffset does the same.
  • 5z. to scroll with a custom offset of 5 (specified as a "count" to the command)
  • :ScrollOffset 5 does the same.
  • :5ScrollOffset also does the same.
| improve this answer | |
  • 1
    thanks for putting it in the function :) – NDavis May 11 at 15:02
  • 1
    +1. Some nice refinements! – Rich May 11 at 15:23

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.