You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Vim的所有拆分窗口中轮换可见缓冲区?

在Vim混合拆分窗口中轮换缓冲区的解决方案

针对你需要跨横向+纵向混合拆分窗口轮换缓冲区的需求,以下是几种实用的实现方式:

一、全可见窗口栈式轮换缓冲区

如果接受"栈式"轮换(把最后一个窗口的缓冲区移到第一个窗口,依次后移),可以添加以下Vim脚本到你的~/.vimrc或init.vim:

function! RotateBuffersAll()
  " 收集所有有效普通窗口的缓冲区编号(排除快速修复窗口)
  let buffers = []
  for win in getwininfo()
    if win.quickfix == 0 && win.valid == 1
      call add(buffers, win.bufnr)
    endif
  endfor

  " 执行栈式轮换:将最后一个缓冲区移至头部,重新分配给窗口
  if len(buffers) > 1
    let rotated = [buffers[-1]] + buffers[:-2]
    let i = 0
    for win in getwininfo()
      if win.quickfix == 0 && win.valid == 1
        call win_gotoid(win.winid)
        execute 'buffer' rotated[i]
        let i += 1
      endif
    endfor
  endif
endfunction

" 绑定快捷键,比如按<Leader>r触发(<Leader>默认是反斜杠\)
nnoremap <Leader>r :call RotateBuffersAll()<CR>

如果想要另一种轮换方向(第一个缓冲区移到最后),只需把rotated = [buffers[-1]] + buffers[:-2]改成rotated = buffers[1:] + [buffers[0]]即可。

二、纵向拆分列间轮换缓冲区

如果只需要实现左右纵向拆分列的缓冲区互换(比如你给出的第二个示例效果),可以用以下脚本:

function! RotateBuffersVertically()
  " 按窗口位置分为左右两列,收集各自的缓冲区
  let left_bufs = []
  let right_bufs = []
  let total_width = &columns
  for win in getwininfo()
    if win.quickfix == 0 && win.valid == 1
      let is_left = (win.wincol + win.width <= total_width / 2 + 1)
      call add(is_left ? left_bufs : right_bufs, win.bufnr)
    endif
  endfor

  " 交换左右列对应位置的缓冲区
  if len(left_bufs) == len(right_bufs) && len(left_bufs) > 0
    let idx = 0
    for win in getwininfo()
      if win.quickfix == 0 && win.valid == 1
        call win_gotoid(win.winid)
        let is_left = (win.wincol + win.width <= total_width / 2 + 1)
        execute 'buffer' (is_left ? right_bufs[idx] : left_bufs[idx])
        let idx += is_left ? 1 : 0
      endif
    endfor
  endif
endfunction

" 绑定快捷键,比如<Leader>rv
nnoremap <Leader>rv :call RotateBuffersVertically()<CR>

执行后会将左列所有窗口的缓冲区和右列对应位置的窗口互换,完全匹配你给出的第二个示例效果。

三、单个缓冲区跨纵向拆分快速移动

如果需要手动交换当前窗口和对面纵向拆分窗口的缓冲区,可以用以下脚本:

function! SwapBufferWithVerticalPeer()
  let current_buf = bufnr('%')
  let total_width = &columns
  let peer_winid = -1

  " 找到当前窗口对面纵向的第一个有效窗口
  for win in getwininfo()
    if win.quickfix == 0 && win.valid == 1 && win.winid != win_getid()
      let current_is_left = (win_getid()->wininfo()[0].wincol + win_getid()->wininfo()[0].width <= total_width / 2 + 1)
      let peer_is_left = (win.wincol + win.width <= total_width / 2 + 1)
      if current_is_left != peer_is_left
        let peer_winid = win.winid
        break
      endif
    endif
  endfor

  " 交换两个窗口的缓冲区
  if peer_winid != -1
    call win_gotoid(peer_winid)
    let peer_buf = bufnr('%')
    execute 'buffer' current_buf
    call win_gotoid(win_getid())
    execute 'buffer' peer_buf
  endif
endfunction

" 绑定快捷键,比如<Leader>sv
nnoremap <Leader>sv :call SwapBufferWithVerticalPeer()<CR>

使用时只需在目标窗口按<Leader>sv,就能和对面纵向拆分的窗口互换缓冲区。

内容的提问来源于stack exchange,提问作者user3761340

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 09:34:59