欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

如何在vim中交换两个打开文件(在拆分中)的位置?

程序员文章站 2022-05-24 15:30:25
...

本文翻译自:How can I swap positions of two open files (in splits) in vim?

Assume I've got some arbitrary layout of splits in vim. 假设我在vim中有一些任意分割布局。

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

Is there a way to swap one and two and maintain the same layout? 有没有办法交换onetwo并保持相同的布局? It's simple in this example, but I'm looking for a solution that will help for more complex layouts. 在这个例子中它很简单,但我正在寻找一种有助于更复杂布局的解决方案。

UPDATE: 更新:

I guess I should be more clear. 我想我应该更清楚。 My previous example was a simplification of the actual use-case. 我之前的例子是对实际用例的简化。 With an actual instance: 使用实际的实例: 如何在vim中交换两个打开文件(在拆分中)的位置?

How could I swap any two of those splits, maintaining the same layout? 我怎么能交换任何两个分裂,保持相同的布局?

Update! 更新! 3+ years later... 3年多以后......

I put sgriffin's solution in a Vim plugin you can install with ease! 我把sgriffin的解决方案放在你可以轻松安装的Vim插件中! Install it with your favorite plugin manager and give it a try: WindowSwap.vim 使用您喜欢的插件管理器安装它并尝试一下: WindowSwap.vim

如何在vim中交换两个打开文件(在拆分中)的位置?


#1楼

参考:https://stackoom.com/question/AqzY/如何在vim中交换两个打开文件-在拆分中-的位置


#2楼

Building heavily on @sgriffin's answer, here's something even closer to what you're asking for: 在@ 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>

Please let me know if the behavior doesn't match your expectations. 如果行为与您的期望不符,请告诉我。


#3楼

The following approach may be convenient if functions are not available for some reason (fe it's not your vim). 如果功能由于某种原因不可用,则以下方法可能很方便(因为它不是你的vim)。

Use :buffers command to find out id's of open buffers, navigate to desired window and use command like :b 5 to open a buffer (buffer number 5 in this case). 使用:buffers命令查找打开缓冲区的id,导航到所需的窗口并使用如下命令:b 5打开缓冲区(在这种情况下为缓冲区编号5)。 Repeate two times and contents of windows are swapped. 重复两次,交换窗口内容。

I "invented" this method after several attempts to memorise ctrl-w-something sequences even for very simple layouts like one-two-three in original question. 经过多次尝试记忆ctrl-w-something序列后,我“发明了”这种方法,即使对于非常简单的布局,如原始问题中的一两三。


#4楼

I have a slightly enhanced version from sgriffin's solution, you can swap windows without using two commands, but with intuitive HJKL commands. 我从sgriffin的解决方案中获得了一个略微增强的版本,您可以在不使用两个命令的情况下交换窗口,但使用直观的HJKL命令。

So here is how it goes: 所以这是怎么回事:

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>

Try to move your window by using capital HJKL in normal node, it is really cool :) 尝试在正常节点中使用大写HJKL移动窗口,这真的很酷:)


#5楼

Really cool, but my proposal for the mapping is to use ^W^J instead of J (because all of HJKL already have meanings), plus also I'd pull in the new buffer, because by the time you want to swap around you probably don't want to continue editing the buffer you are already on. 真的很酷,但我对映射的建议是使用^ W ^ J而不是J(因为所有的HJKL已经有意义),而且我还会拉新缓冲区,因为当你想要在你周围交换时可能不想继续编辑你已经在的缓冲区。 Here goes: 开始:

function! MarkSwapAway()
    " marked window number
    let g:markedOldWinNum = winnr()
    let g:markedOldBufNum = bufnr("%")
endfunction
function! DoWindowToss()
    let newWinNum = winnr()
    let newBufNum = bufnr("%")
    " Switch focus to marked window
    exe g:markedOldWinNum . "wincmd w"
    " Load current buffer on marked window
    exe 'hide buf' newBufNum
    " Switch focus to current window
    exe newWinNum . "wincmd w"
    " Load marked buffer on current window
    exe 'hide buf' g:markedOldBufNum
    " …and come back to the new one
    exe g:markedOldWinNum . "wincmd w"
endfunction
nnoremap <C-w><C-h> :call MarkSwapAway()<CR> <C-w>h :call DoWindowToss()<CR>
nnoremap <C-w><C-j> :call MarkSwapAway()<CR> <C-w>j :call DoWindowToss()<CR>
nnoremap <C-w><C-k> :call MarkSwapAway()<CR> <C-w>k :call DoWindowToss()<CR>
nnoremap <C-w><C-l> :call MarkSwapAway()<CR> <C-w>l :call DoWindowToss()<CR>

#6楼

Also based on sgriffin's solution, go to the window you want to swap, press CTRL-w m , go to the window you want to swap with and press CTRL-w m again. 同样基于sgriffin的解决方案,转到要交换的窗口,按CTRL-w m ,转到要交换的窗口,然后再次按CTRL-w m

CTRL-w m is a poor mnemonic choice, so if anybody comes up with a better one, please edit this. CTRL-w m是一个很差的助记符选择,所以如果有人想出一个更好的助记符,请编辑它。

Also, I'd like to receive a feedback from the script aka "Window marked. Please repeat on target", however being a vimscript noob, I do not know how to do that. 此外,我想收到脚本的反馈,即“标记窗口。请重复目标”,但是作为vimscript noob,我不知道该怎么做。

All that said, the script works well as is 总而言之,脚本运行良好

" <CTRL>-w m : mark first window
" <CTRL>-w m : swap with that window
let s:markedWinNum = -1

function! MarkWindowSwap()
    let s:markedWinNum = winnr()
endfunction

function! DoWindowSwap()
    "Mark destination
    let curNum = winnr()
    let curBuf = bufnr( "%" )
    exe s: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

function! WindowSwapping()
    if s:markedWinNum == -1
        call MarkWindowSwap()
    else
        call DoWindowSwap()
        let s:markedWinNum = -1
    endif
endfunction

nnoremap <C-w>m :call WindowSwapping()<CR>