假设我在vim中有一些任意的分割布局。

____________________
| one       | two  |
|           |      |
|           |______|
|           | three|
|           |      |
|___________|______|

有没有办法交换一个和两个,并保持相同的布局?在这个例子中很简单,但我正在寻找一个解决方案,将有助于更复杂的布局。

更新:

我想我应该说清楚点。我前面的例子是对实际用例的简化。有一个实际的例子:

我怎么能交换任何两个分割,保持相同的布局?

更新!3年多后……

我把sgriffin的解决方案放在一个Vim插件中,你可以轻松安装!用你最喜欢的插件管理器安装它,并尝试一下:WindowSwap.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型

瞧!交换缓冲区没有搞砸你的窗口布局!

其他回答

我从sgriffin的解决方案中有一个稍微增强的版本,您可以在不使用两个命令的情况下交换窗口,但是使用直观的HJKL命令。

事情是这样的:

function! MarkWindowSwap()
    " marked window number
    let g:markedWinNum = winnr()
    let g:markedBufNum = bufnr("%")
endfunction

function! DoWindowSwap()
    let curWinNum = winnr()
    let curBufNum = bufnr("%")
    " Switch focus to marked window
    exe g:markedWinNum . "wincmd w"

    " Load current buffer on marked window
    exe 'hide buf' curBufNum

    " Switch focus to current window
    exe curWinNum . "wincmd w"

    " Load marked buffer on current window
    exe 'hide buf' g:markedBufNum
endfunction

nnoremap H :call MarkWindowSwap()<CR> <C-w>h :call DoWindowSwap()<CR>
nnoremap J :call MarkWindowSwap()<CR> <C-w>j :call DoWindowSwap()<CR>
nnoremap K :call MarkWindowSwap()<CR> <C-w>k :call DoWindowSwap()<CR>
nnoremap L :call MarkWindowSwap()<CR> <C-w>l :call DoWindowSwap()<CR>

试着在正常节点中使用大写HJKL来移动你的窗口,这真的很酷:)

看看:h ctrl-w_ctrl-x和/或:h ctrl-w_ctrl-r。这些命令允许您在当前布局中交换或旋转窗口。

编辑:实际上,在这种情况下,这将不起作用,因为它只会交换当前列或行。您可以转到每个窗口并选择目标缓冲区,但这相当繁琐。

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

为了方便起见,您可以将所需的序列分配给键映射(参见:帮助映射)。

你也可以使用像X-monad这样的平铺窗口管理器

如果函数由于某些原因(例如,它不是你的vim)不可用,下面的方法可能会很方便。

使用:buffers命令来查找打开的缓冲区的id,导航到所需的窗口,并使用像:b 5这样的命令来打开缓冲区(在本例中是缓冲区号5)。重复两次,窗口的内容将被交换。

我“发明”了这种方法,在几次尝试记忆ctrl-w-something序列,甚至是非常简单的布局,如1-2-3在最初的问题。