Question

Is there an autocmd for when the preview window is opened/closed?

I want to scroll the main window n lines up when it the preview window is opened, then n lines down when it is closed, to counteract the "moving text" effect that occurs natively.

Am I able to do this with the relevant autocmd (and what is it), or is there a better way for me to achieve this?

No correct solution

OTHER TIPS

There is no such autocmd event. But you can use WinEnter and BufDelete associated with previewwindow option to achieve something similar.

Using WinEnter you can check previewwindow; if you are on preview window, you can set a buffer variable to differ this event from subsequent events that can be generated by moving to another window and back to preview window. You can also set au BufDelete <buffer> call MyRestoreMainWindow() to call your function when preview window is closed.

I see this question asked often and always scratch my head wondering what is that window-shifting people talk about that I don't experience.

Well, today it occurred to me that two options that I've added to my ~/.vimrc a long time ago have the pleasant side effect of preventing that dreaded window-shifting:

set splitbelow
set splitright

Give it a try!

I was actually wondering the same thing except with the tab bar -- how to prevent that annoying shift from occuring when the tab bar is shown or hidden. Have you considered a wrapper function? The following seems to work for the ps example (it will still cause a shift if the preview window would obscure the cursor)

se splitbelow splitright
fun! PsWrapper(text)
     let view=winsaveview()
     exe 'ps' a:text
     call winrestview(view)
endfun

While we're here ... the tab bar case seems to require some black magic. Ie, as someone pointed out, the tabbar will cause the text to scroll down if the cursor is above the middle line (??). But this seems to work - to always show a tab bar:

let [view,g:stal]=[winsaveview(),&stal]
let [view.topline,&stal]=[view.topline+!g:stal,2]
call winrestview(view)

and to restore the original tabbar setting

let [view.topline,&stal]=[view.topline-!g:stal,g:stal]
call winrestview(view)

You can't really do this with a simple autocmd - Using the WinEnter/WinLeave/BufEnter/BufLeave auto commands all have minor quirks (stated in the vim documentation) so they won't consistently solve your problem completely.

If this happens to you when opening splits, then you can solve this like @romainl suggested, by defining in your .vimrc :

set splitright
set splitbelow

BUT... This will still happen when opening various 'preview' windows, or using the quickfix or location list windows vim has to offer. I use them a lot, and this problem really annoyed me, so I wrote a plugin to solve this.
You can check it out here: https://github.com/gillyb/stable-windows

It works by maintaining state of the cursor position and top line number of the windows open in your vim layout, and restoring them each time you switch to a different buffer.
It's relatively new (as of writing this answer) so if you find any bugs feel free to open an issue, and I will try to address them quickly.

Hope this helps! :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top