Как я могу поменять местами два открытых файла (в разбиениях) в vim?



предположим, что у меня есть какой-то произвольный макет расколов в vim.



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


есть ли способ замены one и two и поддерживать тот же макет? Это просто в этом примере, но я ищу решение, которое поможет для более сложных макетов.



обновление:



Я думаю, я должен быть более ясным. Мой предыдущий пример был упрощением фактического варианта использования. С фактическим экземпляром:
alt text



как я могу поменять любые два эти расколы, сохраняя тот же макет?



обновление! 3+ лет спустя...



Я поставил решение sgriffin в плагин Vim, который вы можете установить с легкостью! Установите его с вашим любимым менеджером плагинов и попробуйте: WindowSwap.ВИМ



a little demo

664   11  

11 ответов:

немного опоздал на пост, но наткнулся на этот поиск чего-то другого. Я написал две функции некоторое время назад, чтобы отметить окно, а затем поменять буферы между окнами. Это, кажется, то, что вы просите.

просто шлепнуть их в вашем .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 установлен в\) вы бы:

  1. перейти к окну, чтобы отметить для подкачки через ctrl-w движение
  2. тип \mw
  3. перейти к окну, которое вы хотите поменять
  4. тип \pw

вуаля! Поменял местами буферы, не завинчивая макет окна!

начиная с этого:

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

сделайте " три " активным окном, затем выполните команду ctrl+ wJ. Это перемещает текущее окно, чтобы заполнить нижнюю часть экрана, оставляя вас с:

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

теперь сделайте либо "один", либо " два " активным окном, а затем выполните команду ctrl+ wr. Это "вращает" окна в текущей строке, оставляя вас с:

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

теперь сделайте " два " активным окном и выполните команду ctrl+ wH. Это перемещает текущее окно, чтобы заполнить левую часть экрана, оставляя вас с:

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

как вы можете видеть, manouevre-это немного перетасовка. С 3 окнами, это немного похоже на одну из тех головоломок 'игры'. Я не рекомендую пробовать это, если у вас есть 4 или более окон - вам лучше закрыть их, а затем снова открыть их в нужное положение.

Я сделал скринкаст, демонстрирующий как работать с разделенными окнами в Vim.

посмотри :h ctrl-w_ctrl-x и/или :h ctrl-w_ctrl-r. Эти команды позволяют обмениваться или поворачивать окна в текущем макете.

Edit: на самом деле, это не будет работать в этой ситуации, потому что он будет меняться только в текущем столбце или строке. Вместо этого вы можете перейти к каждому из окон и выбрать целевой буфер, но это довольно многословно.

Ренди правильно CTRL-W x Не хотите поменять окна, которые не находятся в одном столбце/строке.

я обнаружил, что CTRL-W HJKL клавиши наиболее полезны при работе с окнами. Они выведут ваше текущее окно из его текущего местоположения и скажут ему занять весь край, указанный направлением нажатия клавиши. Смотрите :help window-moving для более подробной информации.

для вашего примера выше, если вы начинаете в окне "один", это делает что вы хотите:

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

для удобства вы можете назначить последовательности, необходимые для сопоставления клавиш (см. :help mapping).

У меня есть немного улучшенная версия от решения 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>

попробуйте переместить окно с помощью capital HJKL в обычном узле, это действительно круто :)

здание сильно на ответ @ 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>

пожалуйста, дайте мне знать, если это поведение не соответствует вашим ожиданиям.

следующий подход может быть удобен, если функции по какой-то причине недоступны (т. е. это не ваш vim).

использовать :buffers команда чтобы узнать идентификаторы открытых буферов, перейдите в нужное окно и используйте команду like :b 5 открыть буфер (в данном случае буфер номер 5). Повторите два раза, и содержимое окон поменяется местами.

я "изобрел" этот метод после нескольких попыток запомнить ctrl-w-something последовательности, даже для очень простых макетов, как один-два-три в исходном вопросе.

действительно здорово, но мое предложение для отображения заключается в использовании ^W^J вместо J (потому что все H J K L уже имеют значения), плюс также я бы вытащил на новый буфер, потому что к тому времени, когда вы хотите поменять местами, вы, вероятно, не хотите продолжать редактирование буфера, в котором вы уже находитесь. Вот так:

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>

также на основе решения sgriffin, перейдите в окно, которое вы хотите поменять, нажмите CTRL-w m, перейдите в окно, с которым вы хотите поменять местами, и нажмите CTRL-w m снова.

CTRL-w m это плохой мнемонический выбор, поэтому, если кто-нибудь придумает лучший, пожалуйста, отредактируйте это.

кроме того, я хотел бы получить обратную связь от сценария ака "окно отмечено. Пожалуйста, повторите в target", однако, будучи vimscript noob, я не знаю, как это сделать.

все, что сказал, сценарий работает хорошо, как есть

" <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>

подобный подход mark-window-then-swap-buffer, но также позволяет повторно использовать последнюю замену.

function! MarkWindowSwap()
    unlet! g:markedWin1
    unlet! g:markedWin2
    let g:markedWin1 = winnr()
endfunction

function! DoWindowSwap()
    if exists('g:markedWin1')
        if !exists('g:markedWin2')
            let g:markedWin2 = winnr()
        endif
        let l:curWin = winnr()
        let l:bufWin1 = winbufnr(g:markedWin1)
        let l:bufWin2 = winbufnr(g:markedWin2)
        exec g:markedWin2 . 'wincmd w'
        exec ':b '.l:bufWin1
        exec g:markedWin1 . 'wincmd w'
        exec ':b '.l:bufWin2
        exec l:curWin . 'wincmd w'
    endif
endfunction

nnoremap ,v :call DoWindowSwap()<CR>
nnoremap ,z :call MarkWindowSwap()<CR>

вы также можете использовать диспетчер окон листов, например X-monad

Comments

    Ничего не найдено.