Skip to content

Instantly share code, notes, and snippets.

@bfrg
Last active May 29, 2024 18:07
Show Gist options
  • Save bfrg/63e49d4a7c2d43fe9206b104e7837aff to your computer and use it in GitHub Desktop.
Save bfrg/63e49d4a7c2d43fe9206b104e7837aff to your computer and use it in GitHub Desktop.
Toggle the quickfix and location-list windows without scrolling the windows
" 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>
@Konfekt
Copy link

Konfekt commented May 29, 2024

It's hard to come up with :botright copento prevent the quickfix list from appearing in the bottom right of the right split window.

@bfrg
Copy link
Author

bfrg commented May 29, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment