假设我在vim中有一些任意的分割布局。
____________________
| one | two |
| | |
| |______|
| | three|
| | |
|___________|______|
有没有办法交换一个和两个,并保持相同的布局?在这个例子中很简单,但我正在寻找一个解决方案,将有助于更复杂的布局。
更新:
我想我应该说清楚点。我前面的例子是对实际用例的简化。有一个实际的例子:
我怎么能交换任何两个分割,保持相同的布局?
更新!3年多后……
我把sgriffin的解决方案放在一个Vim插件中,你可以轻松安装!用你最喜欢的插件管理器安装它,并尝试一下:WindowSwap.vim
以@sgriffin的回答为基础,这里有一些更接近你要求的东西:
function! MarkWindow()
let g:markedWinNum = winnr()
endfunction
function! SwapBufferWithMarkedWindow()
" Capture current window and buffer
let curWinNum = winnr()
let curBufNum = bufnr("%")
" Switch to marked window, mark buffer, and open current buffer
execute g:markedWinNum . "wincmd w"
let markedBufNum = bufnr("%")
execute "hide buf" curBufNum
" Switch back to current window and open marked buffer
execute curWinNum . "wincmd w"
execute "hide buf" markedBufNum
endfunction
function! CloseMarkedWindow()
" Capture current window
let curWinNum = winnr()
" Switch to marked window and close it, then switch back to current window
execute g:markedWinNum . "wincmd w"
execute "hide close"
execute "wincmd p"
endfunction
function! MoveWindowLeft()
call MarkWindow()
execute "wincmd h"
if winnr() == g:markedWinNum
execute "wincmd H"
else
let g:markedWinNum += 1
execute "wincmd s"
execute g:markedWinNum . "wincmd w"
execute "wincmd h"
call SwapBufferWithMarkedWindow()
call CloseMarkedWindow()
endif
endfunction
function! MoveWindowDown()
call MarkWindow()
execute "wincmd j"
if winnr() == g:markedWinNum
execute "wincmd J"
else
execute "wincmd v"
execute g:markedWinNum . "wincmd w"
execute "wincmd j"
call SwapBufferWithMarkedWindow()
call CloseMarkedWindow()
endif
endfunction
function! MoveWindowUp()
call MarkWindow()
execute "wincmd k"
if winnr() == g:markedWinNum
execute "wincmd K"
else
let g:markedWinNum += 1
execute "wincmd v"
execute g:markedWinNum . "wincmd w"
execute "wincmd k"
call SwapBufferWithMarkedWindow()
call CloseMarkedWindow()
endif
endfunction
function! MoveWindowRight()
call MarkWindow()
execute "wincmd l"
if winnr() == g:markedWinNum
execute "wincmd L"
else
execute "wincmd s"
execute g:markedWinNum . "wincmd w"
execute "wincmd l"
call SwapBufferWithMarkedWindow()
call CloseMarkedWindow()
endif
endfunction
nnoremap <silent> <Leader>wm :call MarkWindow()<CR>
nnoremap <silent> <Leader>ws :call SwapBufferWithMarkedWindow()<CR>
nnoremap <silent> <Leader>wh :call MoveWindowLeft()<CR>
nnoremap <silent> <Leader>wj :call MoveWindowDown()<CR>
nnoremap <silent> <Leader>wk :call MoveWindowUp()<CR>
nnoremap <silent> <Leader>wl :call MoveWindowRight()<CR>
如果你的行为不符合你的期望,请告诉我。
Randy是正确的,CTRL-W x不想交换不在同一列/行中的窗口。
我发现CTRL-W HJKL键在操作窗口时最有用。它们将迫使您的当前窗口离开其当前位置,并告诉它占据您按下的键方向所指示的整个边缘。有关更多细节,请参阅:帮助窗口移动。
对于上面的例子,如果你从窗口“one”开始,这就是你想要的:
CTRL-W K # moves window "one" to be topmost,
# stacking "one", "two", "three" top to bottom
CTRL-W j # moves cursor to window "two"
CTRL-W H # moves window "two" to be leftmost,
# leaving "one" and "three" split at right
为了方便起见,您可以将所需的序列分配给键映射(参见:帮助映射)。
从这个开始:
____________________
| one | two |
| | |
| |______|
| | three|
| | |
|___________|______|
将“three”设置为活动窗口,然后发出命令ctrl+w j,这将移动当前窗口以填充屏幕底部,留给你:
____________________
| one | two |
| | |
|___________|______|
| three |
| |
|__________________|
现在将'one'或'two'作为活动窗口,然后发出命令ctrl+w r。这将'旋转'当前行中的窗口,留下你:
____________________
| two | one |
| | |
|___________|______|
| three |
| |
|__________________|
现在将“two”设置为活动窗口,并发出ctrl+w h命令,这将移动当前窗口以填充屏幕左侧,留下:
____________________
| two | one |
| | |
| |______|
| | three|
| | |
|___________|______|
如你所见,这个动作有点乱。它有3个窗口,有点像“瓷砖游戏”谜题。如果你有4个或更多的窗口,我不建议你尝试这个方法——你最好关闭它们,然后在需要的位置重新打开它们。
我做了一个视频演示如何在Vim中使用分割窗口。
有点晚了,但在寻找其他东西时看到了这个。我写了两个函数来标记一个窗口,然后在窗口之间交换缓冲区。这似乎就是你想要的。
只要把这些放在你的.vimrc中,然后映射你认为合适的函数:
function! MarkWindowSwap()
let g:markedWinNum = winnr()
endfunction
function! DoWindowSwap()
"Mark destination
let curNum = winnr()
let curBuf = bufnr( "%" )
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
endfunction
nmap <silent> <leader>mw :call MarkWindowSwap()<CR>
nmap <silent> <leader>pw :call DoWindowSwap()<CR>
要使用(假设您的mapleader设置为\),您将:
移动到窗口以标记交换通道
ctrl-w运动
类型\兆瓦
移动到要交换的窗口
\ pw型
瞧!交换缓冲区没有搞砸你的窗口布局!