如何在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
相关产品推荐
相关产品推荐

