24

A problem I've been having with Vim in general is that when I switch buffers in a window (either :[n]b or MiniBufExpl) the cursor position stays the same, but the window always positions itself so the row the cursor on is in the middle.

This is really annoying me since I visually remember where the top/bottom parts of the window are, not where they would be should the cursor be positioned in the middle of the window.

Is there a setting I can change to preserve a window's position over a buffer?

andrew
  • 2,819
  • 24
  • 33

2 Answers2

39

It's interesting to note that it didn't bother me until I've read your question, lol.

Try this:

if v:version >= 700
  au BufLeave * let b:winview = winsaveview()
  au BufEnter * if(exists('b:winview')) | call winrestview(b:winview) | endif
endif
dnets
  • 1,022
  • 14
  • 11
  • 1
    It didn't bother me, either. However I used to have this mapping: `nmap :bn''` – tungd Nov 23 '10 at 16:02
  • Nice work, @poisonedbit, could you perhaps recommend a programming manual for VIM? – Art Sep 08 '11 at 06:43
  • 1
    @Art Try `:h usr_41.txt` in Vim; plus Steve Losh's [Learn Vimscript the Hard Way](http://learnvimscriptthehardway.stevelosh.com/). – echristopherson Dec 14 '13 at 19:51
  • with vertical diffing this creates an issue, since each file now has its own cursor position to jump to, doing `C-w-w` takes me to some random position in the other file and since the files are `scrollbind` both the files move which is really frustrating and confusing. – justrajdeep Nov 14 '17 at 18:50
7

That script posted by @dnets always sets the cursor at the top of the screen for me, albeit at the same position in the file.

I changed it to this (copied from http://vim.wikia.com/wiki/Avoid_scrolling_when_switch_buffers)

" Save current view settings on a per-window, per-buffer basis.
function! AutoSaveWinView()
    if !exists("w:SavedBufView")
        let w:SavedBufView = {}
    endif
    let w:SavedBufView[bufnr("%")] = winsaveview()
endfunction

" Restore current view settings.
function! AutoRestoreWinView()
    let buf = bufnr("%")
    if exists("w:SavedBufView") && has_key(w:SavedBufView, buf)
        let v = winsaveview()
        let atStartOfFile = v.lnum == 1 && v.col == 0
        if atStartOfFile && !&diff
            call winrestview(w:SavedBufView[buf])
        endif
        unlet w:SavedBufView[buf]
    endif
endfunction

" When switching buffers, preserve window view.
if v:version >= 700
    autocmd BufLeave * call AutoSaveWinView()
    autocmd BufEnter * call AutoRestoreWinView()
endif

And it now works as I want, screen and cursor position saved.

Adamski
  • 3,585
  • 5
  • 42
  • 78