Как я могу поменять местами два открытых файла (в разбиениях) в vim?
предположим, что у меня есть какой-то произвольный макет расколов в vim.
____________________
| one | two |
| | |
| |______|
| | three|
| | |
|___________|______|
есть ли способ замены one и two и поддерживать тот же макет? Это просто в этом примере, но я ищу решение, которое поможет для более сложных макетов.
обновление:
Я думаю, я должен быть более ясным. Мой предыдущий пример был упрощением фактического варианта использования. С фактическим экземпляром:

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

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 установлен в\) вы бы:
- перейти к окну, чтобы отметить для подкачки через ctrl-w движение
- тип \mw
- перейти к окну, которое вы хотите поменять
- тип \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>
Comments