Vim Tips Wiki
 
(Extend logic to allow clicking in inactive window to work.)
Tag: Visual edit
 
(13 intermediate revisions by 9 users not shown)
Line 1: Line 1:
  +
{{TipImported
{{review}}
 
{{Tip
 
 
|id=1375
 
|id=1375
  +
|previous=1373
|title=preserve screen *visual* line when switching buffers
 
  +
|next=1376
|created=October 31, 2006 16:42
+
|created=2006
 
|complexity=intermediate
 
|complexity=intermediate
 
|author=Yakov Lerner
 
|author=Yakov Lerner
|version=n/a
+
|version=7.0
 
|rating=97/28
 
|rating=97/28
  +
|category1=Usage
|text=
 
  +
|category2=
When switching buffers (especially with Ctrl-^ and :bp), vim might change the *visual* line position. Even when vim preserves the line number realtive to file, it might reposition the screen view such that, for example, before switching, current line (line 1234 of the file) was top line of the screen, after :bn :bp current line becomes center line of the screen (but still line 1234 relative to file).
 
 
}}
  +
When switching buffers using the <code>Ctrl-^</code> and <code>:bp</code> commands, Vim will keep the cursor on the line number where it was before switching the buffer but it might change the position of the current line relative to the screen. For example, the cursor may be in line 1234 of the file, with that line at the top of the screen. The user may switch to another buffer, then switch back (<code>:bn :bp</code>), and find that the current line has been repositioned to the middle of the screen.
   
 
If the line number is restored correctly, but the shift in screen view is bothersome, add the following to the .vimrc file to restore the screen view correctly:
   
  +
<pre>
  +
" 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.
If your line number is restored correctly but the shift in screen view bothers you, you
 
  +
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.
can use following autocommands to restore screen view exactly when switching buffers:
 
 
if v:version >= 700
  +
autocmd BufLeave * call AutoSaveWinView()
  +
autocmd BufEnter * call AutoRestoreWinView()
 
endif
  +
</pre>
  +
The above logic works around a couple of issues with the simpler original logic below. First, the view is restored only when the cursor is at start-of-file during the <code>BufEnter</code> event. This prevents old saved settings from overriding a newly selected cursor position when the user scrolls an inactive window with the mouse wheel and clicks in that inactive window. When switching buffers within one window, Vim first sets the cursor position to the start of the file, then fires a <code>BufEnter</code> event; afterward, if no <code>autocmd</code> has changed the cursor position, Vim restores the cursor position based on values saved in its internal data structures. In contrast, when switching to another window the cursor position is not forced to the start of the file; this includes the case when the user scrolls and clicks with the mouse. The logic in <code>AutoRestoreWinView()</code> therefore restores the view only when the cursor is at start-of-file.
   
  +
Secondly, the view settings are stored on a per-buffer, per-window basis, allow the user to maintain two independent cursor positions for one buffer displayed in two windows.
   
  +
Here is the original logic for historical reference:
   
  +
<pre>
" when switching buffers, preserve window view
 
  +
" When switching buffers, preserve window view.
  +
if v:version >= 700
  +
au BufLeave * if !&diff | let b:winview = winsaveview() | endif
 
au BufEnter * if exists('b:winview') && !&diff | call winrestview(b:winview) | unlet! b:winview | endif
  +
endif
  +
</pre>
   
  +
Alternatively a user can <code>:set scrolloff=999</code> which keeps the current line vertically centered.
if v:version &gt;= 700
 
   
  +
==See also==
au BufLeave * let b:winview = winsaveview()
 
  +
*{{Help|'nosol'}}
  +
*[[VimTip80]]
  +
*{{Help|'viminfo'}}
  +
*{{help|last-position-jump}}
   
 
==Comments==
au BufEnter * if(exists('b:winview')) | call winrestview(b:winview) | endif
 
  +
Removed stale b:winview to avoid bugs as the [https://github.com/garbas/vim-snipmate/issues/161 one] reported in snipmate. - May 29, 2014
   
  +
As noted by [[User:JohnBackett|JohnBackett]] the autocommands should not be run in diff mode, this is accomplished with the "&diff" if test - Sep 21, 2012
endif
 
   
   
  +
This tip results in a [http://vim.1045645.n5.nabble.com/Cursor-anomoly-apparent-and-actual-positions-differ-td5673900.html display bug] that hasn't been patched yet, and there's no mention of a vimscript workaround. - Sep 21, 2012
   
  +
I had some weirdness with this. But after renaming the var it worked fine! - Jun 30, 2014
This requires vim7.
 
 
The other possibility is to use ':set scrolloff=999' (which keeps current line
 
 
vertically centered). Check out also 'set nosol'. (not needed if above autocommands are used).
 
 
 
 
If you have problem with restoration of file-relative line numbers, then
 
 
check out tip [[VimTip80]] , and
 
 
[http://vimplugin.sf.net/cgi-bin/help?tag={{urlencode:'viminfo'}} :help 'viminfo'], [http://vimplugin.sf.net/cgi-bin/help?tag={{urlencode:last-position-jump}} :help last-position-jump]
 
 
 
 
Yakov
 
 
 
}}
 
 
== Comments ==
 
<!-- parsed by vimtips.py in 0.518291 seconds-->
 

Latest revision as of 16:24, 15 November 2014

Tip 1375 Printable Monobook Previous Next

created 2006 · complexity intermediate · author Yakov Lerner · version 7.0


When switching buffers using the Ctrl-^ and :bp commands, Vim will keep the cursor on the line number where it was before switching the buffer but it might change the position of the current line relative to the screen. For example, the cursor may be in line 1234 of the file, with that line at the top of the screen. The user may switch to another buffer, then switch back (:bn :bp), and find that the current line has been repositioned to the middle of the screen.

If the line number is restored correctly, but the shift in screen view is bothersome, add the following to the .vimrc file to restore the screen view correctly:

" 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

The above logic works around a couple of issues with the simpler original logic below. First, the view is restored only when the cursor is at start-of-file during the BufEnter event. This prevents old saved settings from overriding a newly selected cursor position when the user scrolls an inactive window with the mouse wheel and clicks in that inactive window. When switching buffers within one window, Vim first sets the cursor position to the start of the file, then fires a BufEnter event; afterward, if no autocmd has changed the cursor position, Vim restores the cursor position based on values saved in its internal data structures. In contrast, when switching to another window the cursor position is not forced to the start of the file; this includes the case when the user scrolls and clicks with the mouse. The logic in AutoRestoreWinView() therefore restores the view only when the cursor is at start-of-file.

Secondly, the view settings are stored on a per-buffer, per-window basis, allow the user to maintain two independent cursor positions for one buffer displayed in two windows.

Here is the original logic for historical reference:

" When switching buffers, preserve window view.
if v:version >= 700
  au BufLeave * if !&diff | let b:winview = winsaveview() | endif
  au BufEnter * if exists('b:winview') && !&diff | call winrestview(b:winview) | unlet! b:winview | endif
endif

Alternatively a user can :set scrolloff=999 which keeps the current line vertically centered.

See also[]

Comments[]

Removed stale b:winview to avoid bugs as the one reported in snipmate. - May 29, 2014

As noted by JohnBackett the autocommands should not be run in diff mode, this is accomplished with the "&diff" if test - Sep 21, 2012


This tip results in a display bug that hasn't been patched yet, and there's no mention of a vimscript workaround. - Sep 21, 2012

I had some weirdness with this. But after renaming the var it worked fine! - Jun 30, 2014