如何在Vim中删除所有空缓冲区?

22

我现在在Vim中打开了大约120个缓冲区。其中约50%的缓冲区是空文件。我想通过某种方式使用:bufdo!命令关闭所有空的缓冲区。我该如何做到:

:bufdo! ‹cmd›

如果当前缓冲区的长度/大小为零,则 :bdelete 条件命令会删除该缓冲区,其中 ‹cmd› 是该命令。


请注意,:bufdo 参数命令不能添加或删除缓冲区(请参阅 :help :bufdo)。 - ib.
3个回答

17

由于使用:bufdo参数命令不允许影响缓冲区列表(请参见:help :bufdo),因此我们需要使用一个更繁琐但相当简单的Vim脚本。

下面的函数枚举所有现有的缓冲区编号并删除那些没有名称(在界面上显示为[No Name])也没有任何未保存的更改。通过调用不带尾随!符号的:bdelete命令来保证后一种情况,此时修改的缓冲区将被跳过。

function! DeleteEmptyBuffers()
    let [i, n; empty] = [1, bufnr('$')]
    while i <= n
        if bufexists(i) && bufname(i) == ''
            call add(empty, i)
        endif
        let i += 1
    endwhile
    if len(empty) > 0
        exe 'bdelete' join(empty)
    endif
endfunction

如果您想要彻底删除空缓冲区,包括未加载的缓冲区,请考虑(慎重!)将 exe 'bdelete' 替换为 exe 'bwipeout'(请参阅 :help :bd:help :bw)。

要测试缓冲区的内容,请使用 getbufline() 函数。例如,要确保缓冲区中不包含任何文本,请按照以下方式修改 while 循环内的 if 声明:

        if bufloaded(i) && bufname(i) == '' && getbufline(i, 1, 2) == ['']

注意这里将bufexists()更改为bufloaded()。这是必要的,因为只有已经加载的缓冲区中的内容才能被获取;对于未加载的缓冲区,getbufline()无论其内容如何都返回一个空列表。


13

我一直在使用以下函数来完成这项工作:

function! s:CleanEmptyBuffers()
    let buffers = filter(range(1, bufnr('$')), 'buflisted(v:val) && empty(bufname(v:val)) && bufwinnr(v:val)<0 && !getbufvar(v:val, "&mod")')
    if !empty(buffers)
        exe 'bw ' . join(buffers, ' ')
    endif
endfunction

这个版本与ib的版本非常相似,不同之处在于它不会操作quickfix缓冲区(只要有任何其他空缓冲区显示在窗口中)。


7
我能想到的唯一解决方法是创建一个函数来报告缓冲区是否为空。类似这样的代码:
function! BufferIsEmpty()
    return line('$') == 1 && getline(1) == '' 
endfunction

3
类似条件:line2byte(line("$")+1)<=2。(注:该条件用于Vim文本编辑器中,表示判断当前光标所在行的下一行是否与当前行相差不超过两个字节的距离,如果是,则满足条件。) - ZyX
@ZyX:为什么不用line2byte(line('$')) < 2 - ib.
@ib vim -u NONE -N -c 'call setline(".", "abc") | echo line2byte(line("$"))' - ZyX

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接