-
-
Save bfrg/63e49d4a7c2d43fe9206b104e7837aff to your computer and use it in GitHub Desktop.
" Open/close/toggle the quickfix and location-list windows without changing the | |
" window layout | |
" ------------------------------------------------------------------------------ | |
" File: autoload/qf/window.vim | |
" ------------------------------------------------------------------------------ | |
" Save and restore view of current window | |
function! s:winview(mode) abort | |
if a:mode == 0 | |
let w:qf_winview = winsaveview() | |
elseif a:mode == 1 && exists('w:qf_winview') | |
call winrestview(w:qf_winview) | |
unlet w:qf_winview | |
endif | |
endfunction | |
" Save and restore views of all windows in current tabpage | |
function! s:windo(mode) abort | |
for winnr in range(1, winnr('$')) | |
call win_execute(win_getid(winnr), printf('call s:winview(%d)', a:mode)) | |
endfor | |
endfunction | |
" Toggle quickfix or location-list window | |
function! qf#window#toggle(loclist = 0) | |
" Check if quickfix window is open in current tabpage, or if current | |
" window's location-list window is open | |
let is_open = getwininfo() | |
\ ->filter('v:val.tabnr == tabpagenr()') | |
\ ->filter({_,info -> a:loclist | |
\ ? info.loclist && info.winid == getloclist(0, {'winid': 1}).winid | |
\ : !info.loclist && info.quickfix | |
\ }) | |
\ ->len() | |
" Save current view of all windows | |
call s:windo(0) | |
if is_open | |
execute a:loclist ? 'lclose' : 'cclose' .. (&filetype ==# 'qf' ? '| wincmd p' : '') | |
else | |
let size = a:loclist ? getloclist(0, {'size': 1}).size : getqflist({'size': 1}).size | |
if size | |
" See https://github.com/vim/vim/issues/5037 | |
execute a:loclist ? 'lopen 1' : 'botright copen 1' | |
execute 'resize' min([10, size]) | |
endif | |
endif | |
" Restore views of all windows | |
call s:windo(1) | |
endfunction | |
" Same behavior as cwindow and lwindow but restore views of all windows | |
function! qf#window#open(loclist = 0) | |
call s:windo(0) | |
let size = a:loclist ? getloclist(0, {'size': 1}).size : getqflist({'size': 1}).size | |
if !size | |
execute a:loclist ? 'lclose' : 'cclose' | |
else | |
execute a:loclist ? 'lopen 1' : 'botright copen 1' | |
execute 'resize' min([10, size]) | |
endif | |
call s:windo(1) | |
endfunction | |
function! qf#window#close() | |
call s:windo(0) | |
if getwininfo(win_getid())[0].loclist | |
lclose | |
else | |
cclose | |
" Required only after cclose | |
wincmd p | |
endif | |
call s:windo(1) | |
endfunction | |
" ------------------------------------------------------------------------------ | |
" File: vimrc | |
" ------------------------------------------------------------------------------ | |
" Toggle quickfix and location-list windows | |
nnoremap <silent> goc :<c-u>call qf#window#toggle(0)<cr> | |
nnoremap <silent> gol :<c-u>call qf#window#toggle(1)<cr> | |
augroup quickfix | |
autocmd! | |
autocmd QuickFixCmdPost [^l]* ++nested call qf#window#open(0) | |
autocmd QuickFixCmdPost l* ++nested call qf#window#open(1) | |
autocmd VimEnter * ++nested call qf#window#open(0) | |
augroup END | |
" ------------------------------------------------------------------------------ | |
" File: after/ftplugin/qf.vim | |
" ------------------------------------------------------------------------------ | |
" Close quickfix window | |
nnoremap <silent> <buffer> gq :<c-u>call qf#window#close()<cr> |
I completely forgot about this gist. Note that nowadays we have :h splitkeep
which makes the calls of s:windo(0)
and s:windo(1)
redundant. Just add set splitkeep=topline
to your vimrc and then whenever you split a window, the buffer won't be scrolled.
Thank you, that's good to know
I particularly appreciate botright copen
, that's a natural way to open the quickfix list, whereas the simple copen
sometimes ended up with a crammed split window.
It's hard to come up with :botright copen
to prevent the quickfix list from appearing in the bottom right of the right split window.
It's hard to come up with :botright copen to prevent the quickfix list from appearing in the bottom right of the right split window.
It's actually explained under :help :botright
. There's also :h :topleft
in case you want to open a window at the top.
This is convenient, thank you! I did not mind the message that there's no location list, so postponed the size check to