Todas as respostas acima são ótimas, infelizmente essas soluções não funcionam bem em combinação com as janelas QuickFix ou LocationList (eu corri nesse problema ao tentar fazer com que o buffer da mensagem de erro do Ale funcionasse com isso).
Solução
Portanto, adicionei uma linha extra de código para fechar todas essas janelas antes de fazer a troca.
exe ':windo if &buftype == "quickfix" || &buftype == "locationlist" | lclose | endif'
O código total se parece;
" Making swapping windows easy
function! SwapWindowBuffers()
exe ':windo if &buftype == "quickfix" || &buftype == "locationlist" | lclose | endif'
if !exists("g:markedWinNum")
" set window marked for swap
let g:markedWinNum = winnr()
:echo "window marked for swap"
else
" mark destination
let curNum = winnr()
let curBuf = bufnr( "%" )
if g:markedWinNum == curNum
:echo "window unmarked for swap"
else
exe g:markedWinNum . "wincmd w"
" switch to source and shuffle dest->source
let markedBuf = bufnr( "%" )
" hide and open so that we aren't prompted and keep history
exe 'hide buf' curBuf
" switch to dest and shuffle source->dest
exe curNum . "wincmd w"
" hide and open so that we aren't prompted and keep history
exe 'hide buf' markedBuf
:echo "windows swapped"
endif
" unset window marked for swap
unlet g:markedWinNum
endif
endfunction
nmap <silent> <leader>mw :call SwapWindowBuffers()<CR>
Créditos para a função de swap para Brandon Orther
Por que é necessário
A razão pela qual as funções de troca não funcionam corretamente sem remover todas as janelas QuickFix (QF) e LocationList (LL) é porque, se o pai do QF / LL armazena o buffer em oculto (e não é mostrado em nenhum lugar em uma janela), o QF / LL acoplada a ele é removida. Isso não é um problema em si, mas quando a janela oculta todos os números de janela são reatribuídos e a troca é confusa, pois o número salvo da primeira janela marcada é (potencialmente) que não existe mais.
Para colocar essa perspectiva:
Primeira marca da janela
____________________
| one | -> winnr = 1 marked first g:markedWinNum=1
| | -> bufnr = 1
|__________________|
| two (QF window | -> winnr = 2
| coupled to one |
|__________________|
| three | -> winnr = 3
| | -> bufnr = 2
|__________________|
Segunda marca da janela
____________________
| one | -> winnr = 1 g:markedWinNum=1
| | -> bufnr = 1
|__________________|
| two (QF window | -> winnr = 2
| coupled to one) |
|__________________|
| three | -> winnr = 3 marked second curNum=3
| | -> bufnr = 2 curBuf=2
|__________________|
Primeiro comutador de buffer, a janela um é preenchida com o buffer da janela três. Assim, a janela QF é removida, pois não tem mais janela pai. Isso reorganiza os números do Windows. Observe que curNum (o número da janela selecionada em segundo lugar) está apontando para uma janela que não existe mais.
____________________
| three | -> winnr = 1 g:markedWinNum=1
| | -> bufnr = 2
|__________________|
| three | -> winnr = 2 curNum=3
| | -> bufnr = 2 curBuf=2
|__________________|
Portanto, ao alternar o segundo buffer, ele tenta selecionar a janela curNum, que não existe mais. Portanto, ele o cria e alterna o buffer, resultando em uma janela indesejada a ser aberta ainda.
____________________
| three | -> winnr = 1 g:markedWinNum=1
| | -> bufnr = 2
|__________________|
| three | -> winnr = 2
| | -> bufnr = 2
|__________________|
| one | -> winnr = 3 curNum=3
| | -> bufnr = 1 curBuf=2
|__________________|