【问题标题】:How do I close all buffers that aren't shown in a window in vim?如何关闭所有未显示在 vim 窗口中的缓冲区?
【发布时间】:2010-12-04 19:47:46
【问题描述】:

我在 vim 中打开了大量缓冲区,其中只有少数在拆分窗口或其他选项卡中打开。有没有办法关闭除当前在其中一个拆分或选项卡中可见的所有内容之外的所有内容?

【问题讨论】:

  • 作为参考,我在遇到这个 SO Q&A 之前找到了这个Yahoo Vim Group thread。这里的答案更好,因为它们处理标签页。
  • Artem Nezvigin 已将以下无数解决方案改编成一个插件,wipeout.vim

标签: vim


【解决方案1】:

对此还有另一种看法。使用tabpagebuflist() 的 Vim 帮助中给出的示例来获取出现在选项卡或窗口中的缓冲区列表。我的.vimrc中有以下内容

function! DeleteInactiveBufs()
    "From tabpagebuflist() help, get a list of all buffers in all tabs
    let tablist = []
    for i in range(tabpagenr('$'))
        call extend(tablist, tabpagebuflist(i + 1))
    endfor

    "Below originally inspired by Hara Krishna Dara and Keith Roberts
    "http://tech.groups.yahoo.com/group/vim/message/56425
    let nWipeouts = 0
    for i in range(1, bufnr('$'))
        if bufexists(i) && !getbufvar(i,"&mod") && index(tablist, i) == -1
        "bufno exists AND isn't modified AND isn't in the list of buffers open in windows and tabs
            silent exec 'bwipeout' i
            let nWipeouts = nWipeouts + 1
        endif
    endfor
    echomsg nWipeouts . ' buffer(s) wiped out'
endfunction
command! Bdi :call DeleteInactiveBufs()

【讨论】:

  • 这会破坏 CommandT。在运行 Bdi 后第一次激活 CommandT 时,我得到“Vim::DeletedBufferError:尝试引用已删除的缓冲区”。下次我尝试 CommandTs 键绑定时,什么也没有发生,我的其他几个键绑定也停止工作。
  • @bobpaul 我不使用 CommandT,但您可以尝试在函数中使用 bdelete 而不是 bwipeout。这可能会让 CommandT 不那么沮丧。
  • 嗨 atomicules,我正在尝试你的功能,我收到了一堆这样的错误:trusktr.io:7777/isowiyirid.rb。有什么想法吗?
  • @trusktr 抱歉,刚刚看到您的评论。您链接到的页面现在是空白的。从 .rb 扩展我猜这是另一个 CommandT 冲突?如果是这样,真的无能为力,因为我不使用它。
  • @atomicules 哎呀,我猜我的服务器会在某个时间后删除粘贴(这不是一个坏主意,也许我可以添加一个选项来锁定它)。我正在尝试您的功能并遇到错误。哦,好吧,现在没时间。
【解决方案2】:

您可以在.vimrc 中找到另一种解决方案:

function! Wipeout()
  " list of *all* buffer numbers
  let l:buffers = range(1, bufnr('$'))

  " what tab page are we in?
  let l:currentTab = tabpagenr()
  try
    " go through all tab pages
    let l:tab = 0
    while l:tab < tabpagenr('$')
      let l:tab += 1

      " go through all windows
      let l:win = 0
      while l:win < winnr('$')
        let l:win += 1
        " whatever buffer is in this window in this tab, remove it from
        " l:buffers list
        let l:thisbuf = winbufnr(l:win)
        call remove(l:buffers, index(l:buffers, l:thisbuf))
      endwhile
    endwhile

    " if there are any buffers left, delete them
    if len(l:buffers)
      execute 'bwipeout' join(l:buffers)
    endif
  finally
    " go back to our original tab page
    execute 'tabnext' l:currentTab
  endtry
endfunction

使用:call Wipeout()

【讨论】:

  • 这会删除修改过的缓冲区吗?
  • atomicules 的答案有效,这个删除了选项卡中的缓冲区,似乎有奇怪的行为。
  • 小心 - Wipeout() 认为其他选项卡(当前不可见选项卡的选项卡)中的窗口不可见。
【解决方案3】:

将此添加到您的 .vimrc:

function! CloseHiddenBuffers()
  let i = 0
  let n = bufnr('$')
  while i < n
    let i = i + 1
    if bufloaded(i) && bufwinnr(i) < 0
      exe 'bd ' . i
    endif
  endwhile
endfun

然后你可以这样做来关闭隐藏缓冲区:

:call CloseHiddenBuffers()

(您可能希望将键或命令绑定到它。)

更新:

这是一个更新版本以支持标签页。 (我自己不使用标签页,所以我没有意识到 bufwinnr 只适用于当前页面上的窗口)。

function! CloseHiddenBuffers()
  " figure out which buffers are visible in any tab
  let visible = {}
  for t in range(1, tabpagenr('$'))
    for b in tabpagebuflist(t)
      let visible[b] = 1
    endfor
  endfor
  " close any buffer that's loaded and not visible
  for b in range(1, bufnr('$'))
    if bufloaded(b) && !has_key(visible, b)
      exe 'bd ' . b
    endif
  endfor
endfun

【讨论】:

  • 我的问题可能措辞不正确——我正在尝试清理 :ls 的输出,而这个函数似乎没有这样做。
  • 是缺少标签页支持还是其他原因?我在上面添加了一个支持标签页的版本。
  • 在什么方面不起作用? (另外,你用的是什么版本的vim?)
  • /me 假装 1.5 年还没有过去...我正在运行 vim 7.3。我没有看到任何后台缓冲区随着您的函数而消失 - 运行 :ls :call CloseHiddenBuffers :ls 导致 ls 输出没有变化。
【解决方案4】:

我知道为什么第二个脚本不能正常工作。

这是由于 bufloaded() 函数必须是 bufexits() !

确实,没有加载要删除的缓冲区!只需删除此条件即可,但当我们尝试清除未使用的缓冲区时它会发出一些警告,因此我们必须使用 bufexists(b)。

最终解决方案如下:

function! CloseHiddenBuffers()
    " Tableau pour memoriser la visibilite des buffers                                                                                      
    let visible = {}
    " Pour chaque onglet...
    for t in range(1, tabpagenr('$'))
        " Et pour chacune de ses fenetres...
        for b in tabpagebuflist(t)
            " On indique que le buffer est visible.
            let visible[b] = 1
        endfor
    endfor
    " Pour chaque numero de buffer possible...
    for b in range(1, bufnr('$'))
        " Si b est un numero de buffer valide et qu'il n'est pas visible, on le
        " supprime.
        if bufexists(b) && !has_key(visible, b)
            " On ferme donc tous les buffers qui ne valent pas 1 dans le tableau et qui
            " sont pourtant charges en memoire.
            execute 'bwipeout' b
        endif
    endfor
endfun

谢谢你。

【讨论】:

  • 如果“bufloaded(b)”对于我们想要关闭的缓冲区是假的,为什么不只是“if !bufloaded(b)”?
  • 这成功了,但我很喜欢:Wipeout 非常吸引人command! -nargs=? Wipeout call CloseHiddenBuffers()
【解决方案5】:

有一个插件可以做到这一点,而且还有更多功能!

查看close-buffers.vim

【讨论】:

  • 太棒了。 :CloseHiddenBuffers
【解决方案6】:

如果您使用的是 fzf,这里有一种选择要删除的缓冲区的方法:

" fzf delete buffers
function! s:list_buffers()
  redir => list
  silent ls
  redir END
  return split(list, "\n")
endfunction
function! s:delete_buffers(lines)
  execute 'bwipeout' join(map(a:lines, {_, line -> split(line)[0]}))
endfunction
command! BD call fzf#run(fzf#wrap({
  \ 'source': s:list_buffers(),
  \ 'sink*': { lines -> s:delete_buffers(lines) },
  \ 'options': '--multi --reverse --bind ctrl-a:select-all+accept'
  \ }))

【讨论】:

    猜你喜欢
    • 2011-05-16
    • 2011-05-23
    • 2010-11-19
    • 2012-05-29
    • 1970-01-01
    • 1970-01-01
    • 2011-09-26
    • 1970-01-01
    • 2011-03-02
    相关资源
    最近更新 更多