vertical two open change layout editor split vim

layout - two - vim split vertical



¿Cómo puedo intercambiar posiciones de dos archivos abiertos(en splits) en vim? (12)

Supongamos que tengo un diseño arbitrario de splits en vim.

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

¿Hay alguna forma de intercambiar one y two y mantener el mismo diseño? Es simple en este ejemplo, pero estoy buscando una solución que ayude a diseños más complejos.

ACTUALIZAR:

Supongo que debería ser más claro. Mi ejemplo anterior fue una simplificación del caso de uso real. Con una instancia real:

¿Cómo podría intercambiar dos de esas divisiones, manteniendo el mismo diseño?

¡Actualizar! 3+ años después ...

¡Pongo la solución de sgriffin en un plugin Vim que puedes instalar fácilmente! Instálelo con su administrador de complementos favorito y pruébelo: WindowSwap.vim


A partir de esto:

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

Haga que ''tres'' sea la ventana activa, luego emita el comando ctrl + w J. Esto mueve la ventana actual para llenar la parte inferior de la pantalla, dejándole con:

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

Ahora haga que ''uno'' o ''dos'' sea la ventana activa, luego ejecute el comando ctrl + w r . Esto ''rota'' las ventanas en la fila actual, dejándote con:

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

Ahora haga ''dos'' la ventana activa, y ejecute el comando ctrl + w H. Esto mueve la ventana actual para llenar la parte izquierda de la pantalla, dejándole con:

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

Como puede ver, la maniobra es un poco aleatoria. Con 3 ventanas, es un poco como uno de esos rompecabezas de "juegos de fichas". No recomiendo probar esto si tiene 4 o más ventanas. Será mejor que las cierre y las abra de nuevo en las posiciones deseadas.

Hice un screencast demostrando cómo trabajar con ventanas divididas en Vim .


Eche un vistazo a :h ctrl-w_ctrl-x y / o :h ctrl-w_ctrl-r . Estos comandos le permiten intercambiar o rotar ventanas en el diseño actual.

Edición: En realidad, esto no funcionará en esta situación porque solo se intercambiará en la columna o fila actual. En su lugar, podría ir a cada una de las ventanas y seleccionar el búfer de destino, pero eso es bastante detallado.


El siguiente enfoque puede ser conveniente si las funciones no están disponibles por algún motivo (si no es su vim).

Use el comando :buffers para averiguar los ID de los buffers abiertos, navegue a la ventana deseada y use el comando como :b 5 para abrir un buffer (buffer 5 en este caso). Repetir dos veces y los contenidos de las ventanas se intercambian.

"Inventé" este método después de varios intentos de memorizar secuencias de ctrl-w-something incluso para diseños muy simples como uno-dos-tres en la pregunta original.


Enfoque similar marca-ventana-luego-intercambio-búfer, pero también le permite reutilizar el último intercambio.

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>


Realmente genial, pero mi propuesta para el mapeo es usar ^ W ^ J en lugar de J (porque todos los HJKL ya tienen significados), además, también obtendré el nuevo búfer, porque para el momento en que quieras intercambiarte Probablemente no quiera continuar editando el búfer en el que se encuentra. Aquí va:

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>


Sobre la base de la respuesta de @ sgriffin, aquí hay algo aún más cercano a lo que estás pidiendo:

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>

Por favor, hágame saber si el comportamiento no coincide con sus expectativas.


También basado en la solución de sgriffin, vaya a la ventana que desea intercambiar, presione CTRL-w m , vaya a la ventana con la que desea intercambiar y presione CTRL-w m nuevamente.

CTRL-w m es una opción mnemotécnica deficiente, por lo que si alguien encuentra una mejor, edítela.

Además, me gustaría recibir comentarios del script, también conocido como "Ventana marcada. Por favor, repita en target". Sin embargo, al ser un noob vimscript, no sé cómo hacerlo.

Todo lo dicho, el guión funciona bien como está

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


También puedes usar un administrador de ventanas de mosaico como X-monad


Tengo una versión ligeramente mejorada de la solución de sgriffin, puedes cambiar ventanas sin usar dos comandos, pero con comandos intuitivos HJKL.

Así que aquí es cómo va:

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>

Intente mover su ventana usando HJKL de capital en un nodo normal, es realmente genial :)


Todas las respuestas anteriores son excelentes, desafortunadamente, estas soluciones no funcionan bien en combinación con las ventanas QuickFix o LocationList (corrí en este problema al intentar que el búfer de mensajes de error de Ale funcionara con esto).

Solución

Por lo tanto, agregué una línea de código adicional para cerrar todas estas ventanas antes de hacer el intercambio.

exe '':windo if &buftype == "quickfix" || &buftype == "locationlist" | lclose | endif''

El código total se ve como;

" Making swapping windows easy function! SwapWindowBuffers() exe '':windo if &buftype == "quickfix" || &buftype == "locationlist" | lclose | endif'' if !exists("g:markedWinNum") " set window marked for swap let g:markedWinNum = winnr() :echo "window marked for swap" else " mark destination let curNum = winnr() let curBuf = bufnr( "%" ) if g:markedWinNum == curNum :echo "window unmarked for swap" else 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 :echo "windows swapped" endif " unset window marked for swap unlet g:markedWinNum endif endfunction nmap <silent> <leader>mw :call SwapWindowBuffers()<CR>

Créditos para la función de intercambio a Brandon Orther

Por que se necesita

La razón por la que las funciones de intercambio no funcionan correctamente sin eliminar primero todas las ventanas de QuickFix (QF) y LocationList (LL) es porque si el principal del búfer QF / LL se oculta (y no se muestra en ninguna ventana), el QF Se quita la ventana / LL acoplada a ella. Esto no es un problema en sí mismo, pero cuando la ventana se oculta, todos los números de las ventanas se reasignan y el intercambio se desordena ya que el número guardado de la primera ventana marcada ya no existe (potencialmente).

Para poner esto en perspectiva:

Primera marca de ventana

____________________ | one | -> winnr = 1 marked first g:markedWinNum=1 | | -> bufnr = 1 |__________________| | two (QF window | -> winnr = 2 | coupled to one | |__________________| | three | -> winnr = 3 | | -> bufnr = 2 |__________________|

Segunda marca de ventana

____________________ | one | -> winnr = 1 g:markedWinNum=1 | | -> bufnr = 1 |__________________| | two (QF window | -> winnr = 2 | coupled to one) | |__________________| | three | -> winnr = 3 marked second curNum=3 | | -> bufnr = 2 curBuf=2 |__________________|

Primer interruptor de búfer, la ventana uno se llena con el búfer de la ventana tres. Por lo tanto, la ventana QF se elimina porque ya no tiene ninguna ventana principal. Esto reorganiza los números de las ventanas. Tenga en cuenta que curNum (el número de la segunda ventana seleccionada) apunta a una ventana que ya no existe.

____________________ | three | -> winnr = 1 g:markedWinNum=1 | | -> bufnr = 2 |__________________| | three | -> winnr = 2 curNum=3 | | -> bufnr = 2 curBuf=2 |__________________|

Así que cuando se cambia el segundo búfer, intenta seleccionar la ventana de curNum, que ya no existe. Así que lo crea y cambia el búfer, lo que da como resultado que una ventana no deseada se abra aún.

____________________ | three | -> winnr = 1 g:markedWinNum=1 | | -> bufnr = 2 |__________________| | three | -> winnr = 2 | | -> bufnr = 2 |__________________| | one | -> winnr = 3 curNum=3 | | -> bufnr = 1 curBuf=2 |__________________|


Un poco tarde para el post, pero encontré esto buscando algo más. Hace un tiempo escribí dos funciones para marcar una ventana y luego intercambiar buffers entre ventanas. Esto parece ser lo que estás pidiendo.

Solo golpea estos en tu .vimrc y mapea las funciones como mejor te parezcan:

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>

Para usar (asumiendo que su mapleader está configurado en /) usted debería:

  1. Mover a la ventana para marcar para el intercambio a través del movimiento ctrl-w
  2. Escriba / mw
  3. Mueve a la ventana que quieres intercambiar.
  4. Tipo / pw

Voila! Intercambiar buffers sin estropear el diseño de su ventana!


Randy''s razón en que CTRL-W x no quiere intercambiar ventanas que no estén en la misma columna / fila.

Descubrí que las CTRL-W HJKL son más útiles al manipular ventanas. Forzarán su ventana actual fuera de su ubicación actual y le indicarán que ocupe todo el borde indicado por la dirección de la tecla que presiona. Ver :help window-moving para :help window-moving para más detalles.

Para su ejemplo anterior, si comienza en la ventana "uno", esto hace lo que quiere:

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

Para su comodidad, puede asignar las secuencias que necesita a las asignaciones de teclas (consulte :help mapping ).