如何削减Vim的缓冲区列表只包含活动缓冲区

时间:2010-06-04 12:42:31

标签: vim

如何减少缓冲区列表以仅包含当前在窗口/选项卡中打开的缓冲区?

当我长时间运行Vim时,:ls命令显示的缓冲区列表太大而无法使用。理想情况下,我想通过运行自定义命令(例如:Only)来删除选项卡或窗口中当前不可见的所有缓冲区。任何人都可以建议如何实现这个目标吗?

看起来:bdelete命令可以接受缓冲区编号列表,但我不确定如何将:ls的输出转换为{{1}可以使用的格式命令。任何帮助将不胜感激。

澄清

让我们说在我的Vim会话中我打开了4个文件。 :bdelete命令输出:

:ls

缓冲区1位于当前选项卡中,缓冲区4位于单独的选项卡中,但是 缓冲区2和3都是隐藏的。我想运行命令:ls 1 a "abc.c" 2 h "123.c" 3 h "xyz.c" 4 a "abc.h" ,然后 它将擦除缓冲区2和3,因此:Only命令将输出:

:ls

此示例不会使建议的:ls 1 a "abc.c" 4 a "abc.h" 命令看起来非常有用,但是 如果你有40个缓冲区列表,那将是非常受欢迎的。

5 个答案:

答案 0 :(得分:11)

我改编了Laurence Gonslaves solution

command! -nargs=* Only call CloseHiddenBuffers()
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 are loaded and not visible
  let l:tally = 0
  for b in range(1, bufnr('$'))
    if bufloaded(b) && !has_key(visible, b)
      let l:tally += 1
      exe 'bw ' . b
    endif
  endfor
  echon "Deleted " . l:tally . " buffers"
endfun

我将其更改为使用bwipeout而不是bdelete,并添加了消息以显示已删除了多少缓冲区。

答案 1 :(得分:7)

您在寻找:

:echo map(filter(range(0, bufnr('$')), 'bufwinnr(v:val)>=0'), 'bufname(v:val)')

或更确切地说:

exe 'bw '.join(filter(range(0, bufnr('$')), 'bufwinnr(v:val)<0'), ' ')


编辑:上一个答案没有考虑多个标签。

我似乎使用了一种复杂的方法。由于tabpagebuflist()带有:

,因此可以获得已打开和显示的缓冲区列表
let tabs = range(1, tabpagenr())
echo lh#list#unique_sort(eval(join(map(tabs, 'tabpagebuflist(v:val)'), '+')))

lh#list#unique_sort()来自lh-vim-lib,它定义了vim未提供的排序+唯一函数。

为了拥有非打开的缓冲区,它变得有点棘手。我们使用每个选项卡的循环来获取未显示的缓冲区,或者我们在前一个结果和bufexisting缓冲区之间进行区分:

let tabs = range(1, tabpagenr())
let windowed = lh#list#unique_sort(eval(join(map(tabs, 'tabpagebuflist(v:val)'), '+')))
let existing = filter(range(0,bufnr('$')), 'bufexists(v:val)')
let non_windowed = filter(copy(existing), 'match(windowed, "^".v:val."$")<0')  
echo non_windowed

答案 2 :(得分:1)

" Active Buffers
function ListActive()
    let result = ""
    silent! redir => result
    silent! exe "ls"
    redir END
    let active = ""
    for i in split(result, "\n")
      if matchstr(i, '\m[0-9][0-9]* .a.. ') != ""
        let active .= "\n".i
      endif
    endfor
    echo active
endfunction

E.g。

来自shell:

$ vim -p foo bar baz

内部vim:

:call ListActive()

输出:

1 %a   "foo"                          line 1
2  a   "bar"                          line 0
3  a   "baz"                          line 0
Press ENTER or type command to continue

关闭一个文件:

:q

:call ListActive()

输出:

2 %a   "bar"                          line 1
3  a   "baz"                          line 0
Press ENTER or type command to continue

打开另一个文件:

:split ~/.vimrc

:call ListActive()

输出:

2 #a   "bar"                          line 1
3  a   "baz"                          line 0
4 %a   "~/.vimrc"                     line 244

答案 3 :(得分:0)

如果您说4个缓冲区已打开:

:ls
1    abc.c
2    123.c
3    xyz.c
4    abc.h

你要“关闭”缓冲区3“xyz.c”:

:bd3
删除缓冲区3后的

结果:

:ls
1    abc.c
2    123.c
4    abc.h

答案 4 :(得分:0)

我不使用set hidden,因此我希望关闭任何窗口中未显示的缓冲区只是为了清除:ls的输出。这个功能就是这样:

function! CloseUnloadedBuffers()
    let lastBuffer = bufnr('$')

    let currentBuffer = 1
    while currentBuffer <= lastBuffer
        " If buffer exists, is shown in :ls output, and isn't loaded
        if bufexists(currentBuffer) && buflisted(currentBuffer) && bufloaded(currentBuffer) == 0
            execute 'bdelete' currentBuffer
        endif

        let currentBuffer = currentBuffer + 1
    endwhile
endfunction

From this Nabble thread