如何在Vim中删除多个缓冲区?


120

假设我有多个文件在Vim中作为缓冲区打开。这些文件有*.cpp*.h有些是*.xml。我想使用关闭所有XML文件:bd *.xml。但是,Vim不允许这样做(E93:多个匹配...)。

有什么办法吗?

附言:我知道:bd file1 file2 file3行得通。所以,我可以采用某种评估*.xmlfile1.xml file2.xml file3.xml

Answers:


194

您可以<C-a>用来完成所有比赛。因此,如果您键入:bd *.xml然后单击<C-a>,vim将完成命令:bd file1.xml file2.xml file3.xml


8
@Florian <tab>仅允许您循环显示匹配项,在命令行上输入一个条目<C-a>,一次添加所有匹配项。
比约恩Steinbrink

天哪,你是对的!抱歉。标签只有在只有一种可能的结果时才起作用。
弗洛里安·克莱因

如何在tmux上的Vim中使用<Ca>?
2015年

4
tmux默认情况下不绑定<Ca>,但是如果将其配置为例如使用<Ca>而不是<Cb>来模拟屏幕,则还应该将其配置为映射,例如<Ca> a以传递< Ca>到tmux内部运行的程序。tmux随附的screen-keys.conf可以做到这一点。
比昂·斯坦布林克(BjörnSteinbrink)2015年

7
如果您已经vim-rsi安装了JFTR (我想这是* nix上每个人都必须安装的),则要在<C-a>命令行中以原始方式进行工作,应该使用<C-x> <C-a>JFTR。
kostix

43
:3,5bd[elete]   

将删除缓冲区范围从3到5。


19

您也可以替代使用:

    :.,$-bd[elete]    " to delete buffers from the current one to last but one
    :%bd[elete]       " to delete all buffers

1
这很好用。我做了:LS看到缓冲号码,并将其一个,BBD:从号码删除缓存到B
Neaţu奥维迪乌·加布里埃尔

5

您可以使用它。

:exe 'bd '. join(filter(map(copy(range(1, bufnr('$'))), 'bufname(v:val)'), 'v:val =~ "\.xml$"'), ' ')

将其添加到命令中应该很容易。

function! s:BDExt(ext)
  let buffers = filter(range(1, bufnr('$')), 'buflisted(v:val) && bufname(v:val) =~ "\.'.a:ext.'$"')
  if empty(buffers) |throw "no *.".a:ext." buffer" | endif
  exe 'bd '.join(buffers, ' ')
endfunction

command! -nargs=1 BDExt :call s:BDExt(<f-args>)

我几乎对Vimscript一无所知,但是glob()函数呢?
Thanh DK

1
glob()只会为您提供现有文件(在硬盘驱动器上),而不会打开缓冲区。
Luc Hermitte

您忘记了fnameescape()缓冲名称。
ZyX 2012年

我刚刚检查了c:/Program files/foo.bar,甚至foo.bar.foo效果很好。fnameescape()如果我使用了缓冲区名称,则可能需要。但是我只检查缓冲区名称是否与给定表达式匹配:\.{ext}$-我将缓冲区编号提供给:bd`。我没有任何理由逃避正则表达式匹配。
Luc Hermitte'3

5

试试下面的脚本。该示例用于“ txt”,根据需要将其更改,例如更改为“ xml”。修改后的缓冲区不会被删除。按\ bd删除缓冲区。

map <Leader>bd :bufdo call <SID>DeleteBufferByExtension("txt")

function!  <SID>DeleteBufferByExtension(strExt)
   if (matchstr(bufname("%"), ".".a:strExt."$") == ".".a:strExt )
      if (! &modified)
         bd
      endif
   endif
endfunction

[编辑] 不带:bufdo相同(按Luc Hermitte的要求,请参见下面的评论)

map <Leader>bd :call <SID>DeleteBufferByExtension("txt")

function!  <SID>DeleteBufferByExtension(strExt)
   let s:bufNr = bufnr("$")
   while s:bufNr > 0
       if buflisted(s:bufNr)
           if (matchstr(bufname(s:bufNr), ".".a:strExt."$") == ".".a:strExt )
              if getbufvar(s:bufNr, '&modified') == 0
                 execute "bd ".s:bufNr
              endif
           endif
       endif
       let s:bufNr = s:bufNr-1
   endwhile
endfunction

1
我不喜欢,:bufdo因为它使当前窗口混乱。
Luc Hermitte'7

3

我也一直都需要此功能。这是我在vimrc中拥有的解决方案。

function! GetBufferList()
    return filter(range(1,bufnr('$')), 'buflisted(v:val)')
endfunction

function! GetMatchingBuffers(pattern)
    return filter(GetBufferList(), 'bufname(v:val) =~ a:pattern')
endfunction

function! WipeMatchingBuffers(pattern)
    let l:matchList = GetMatchingBuffers(a:pattern)

    let l:count = len(l:matchList)
    if l:count < 1
        echo 'No buffers found matching pattern ' . a:pattern
        return
    endif

    if l:count == 1
        let l:suffix = ''
    else
        let l:suffix = 's'
    endif

    exec 'bw ' . join(l:matchList, ' ')

    echo 'Wiped ' . l:count . ' buffer' . l:suffix . '.'
endfunction

command! -nargs=1 BW call WipeMatchingBuffers('<args>')

现在,我可以做:BW regex(例如:BW \.cpp$,擦除路径名称中与该模式匹配的所有匹配缓冲区。

如果要删除而不是擦除,当然可以替换exec 'bw ' . join(l:matchList, ' ')exec 'bd ' . join(l:matchList, ' ')


我有时在想,为什么Vim不支持正则表达式随处可见(:badd:bdelete:bufdo:bn...)
PUK

1

很简单:使用:bd[elete]命令。例如,:bd[elete] buf#1 buf#5 buf#3将删除缓冲区1、3和5。


1

TAB只会自动完成一个文件,你只要Vim 7.4.282的
使用<c-a>自动完成所有文件。

您可以使用:

bd filetype

然后仅用于<c-a>促进完成指定文件类型的所有打开文件。

例如,您有1.xml,2.xml,3.xml和4.xml,则可以执行以下操作:

bd xml

然后按 <c-a>

vim将自动为您完成以下操作:

bd 1.xml 2.xml 3.xml 4.xml

您只需按Enter键即可完成命令。

如果您对上述文件之一进行了更改,请记住要执行以下操作:

bd! xml
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.