-
-
Save bfrg/63e49d4a7c2d43fe9206b104e7837aff to your computer and use it in GitHub Desktop.
" Open/close/toggle the quickfix and location-list windows | |
" ------------------------------------------------------------------------------ | |
" File: autoload/qf/window.vim | |
" ------------------------------------------------------------------------------ | |
" 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() | |
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 | |
endfunction | |
" Same as :cwindow and :lwindow but resize the quickfix window automatically | |
function! qf#window#open(loclist = 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 | |
endfunction | |
function! qf#window#close() | |
if getwininfo(win_getid())[0].loclist | |
lclose | |
else | |
cclose | |
" Required only after cclose | |
wincmd p | |
endif | |
endfunction | |
" ------------------------------------------------------------------------------ | |
" File: vimrc | |
" ------------------------------------------------------------------------------ | |
" Don't scroll windows when opening new horizontal splits | |
set splitkeep=topline | |
" 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 just noticed that Vim only throws an error when there's no location list (E776), but when there's no quickfix list, it will just open an empty quickfix window after :copen
.
Yes, I don't understand the logic; do you think a simple message would be more appropriate as well:
if a:loclist
lopen 1
elseif empty(getqflist())
echomsg 'Quickfix list is empty'
else
botright copen 1
endif
How about updating the gist as a whole (including dispensing with the s:windo
s)?
I don't know if this is a bug or desired behavior. It looks inconsistent to me. Anyway, I have removed all the redundant s:windo()
invocations in the gist.
And one more note, using getqflist({'size': 1}).size == 0
is more efficient than empty(getqflist())
, since in the latter case the entire list is returned.
It looks inconsistent to me.
Yes, it is.
using getqflist({'size': 1}).size == 0 is more efficient than empty(getqflist())
I did not know, I rarely looked at the source code. Since empty()
requests little information, I hoped that Vim wouldn't bother returning redundant information. Do you have a pointer?
Good to know!
When you call getqflist()
, Vim needs to iterate through the entire list and return a copy of it. This takes a lot more time than just returning a dict containing one element as with getqflist({'size': 1})
. You can benchmark it with a larger list.
In the source code take a look at get_errorlist()
(called for getqflist()
) and qf_get_properties()
(called for getqflist({'size': 1})
).
Interesting. Surely size
is there for a reason, maybe this reason. I wonder about how common it is in other framewords or programming languages to generally supply a size
attribute. Here the Vimscript compiler would still have to be smart about getqflist()
only being called to read size
though.
get_qf_loc_list()
is the C function that is invoked when getqflist()
is called. As you can see it checks if any arguments have been passed and if so, either of the above functions are invoked, one will return an entire list (which needs to be generated), whereas the other one just returns the properties that have been passed to getqflist()
. There's really no magic going on here.
Not at all. I wonder how much one can count on such magic in other languages such as Lua, Python, Go, ...
Nice. You could also add
v:throwpoint
to yourechomsg
, then you know where the exception was thrown in one line. This gives you something like: