Como excluir vários buffers no Vim?

120

Supondo que eu tenha vários arquivos abertos como buffers no Vim. Os arquivos têm *.cpp, *.he alguns são *.xml. Eu quero fechar todos os arquivos XML com :bd *.xml. No entanto, o Vim não permite isso (E93: Mais de uma correspondência ...).

Há alguma maneira de fazer isso?

PS Eu sei que :bd file1 file2 file3funciona. Para que eu possa de algum modo avaliar *.xmla file1.xml file2.xml file3.xml?

Thanh DK
fonte

Respostas:

194

Você pode usar <C-a>para concluir todas as correspondências. Portanto, se você digitar :bd *.xmle pressionar <C-a>, o vim concluirá o comando para :bd file1.xml file2.xml file3.xml.

Björn Steinbrink
fonte
8
O @Florian <tab>apenas permite percorrer as correspondências, colocando uma única entrada na linha de comando e <C-a>adicionando todas as correspondências de uma só vez.
Björn Steinbrink
meu deus você está certo! Desculpe. A guia funciona apenas quando há apenas um resultado possível.
Florian Klein
Como você usa <Ca> com vim no tmux?
Nabn 25/05
4
O tmux não liga <Ca> por padrão, mas se você o configurou para, por exemplo, usar <Ca> em vez de <Cb> para emular a tela, você também deve configurá-lo para mapear, por exemplo, <Ca> a para passar um < Vá até o programa em execução no tmux. O screen-keys.conf que acompanha o tmux faz isso.
Björn Steinbrink
7
JFTR, no caso de você ter vim-rsiinstalado (acho que é obrigatório para todos no * nix), para obter o <C-a>trabalho da maneira original na linha de comando, você deve usá-lo <C-x> <C-a>.
kostix
43
:3,5bd[elete]   

Exclui o intervalo do buffer de 3 a 5.

Pescador
fonte
19

Você também pode usar como alternativa:

    :.,$-bd[elete]    " to delete buffers from the current one to last but one
    :%bd[elete]       " to delete all buffers
Cylian
fonte
1
Isso funciona bem. Eu faço um : ls para ver tampão números e eles : um bbd para buffers Excluir do número um para b
Neaţu Ovidiu Gabriel
5

Você pode usar isso.

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

Deve ser bastante fácil adicioná-lo a um comando.

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>)
Luc Hermitte
fonte
Não sei quase nada sobre o Vimscript, mas e a função glob ()?
Thanh DK
1
glob()fornecerá apenas arquivos existentes (no disco rígido) e não buffers abertos.
Luc Hermitte 01/07
Você esqueceu de fnameescape()armazenar nomes em buffer.
ZyX
Acabei de verificar com c:/Program files/foo.bar, e mesmo foo.bar.fooe funcionou perfeitamente. fnameescape()pode ter sido necessário se eu usasse os nomes dos buffers. Mas só estou verificando se os nomes dos buffers correspondem a uma determinada expressão: \.{ext}$- Dou números de buffer para: bd`. Não tenho nenhuma razão para escapar de nada para a correspondência de expressões regulares.
Luc Hermitte
5

Experimente o script abaixo. O exemplo é para "txt", altere-o conforme necessário, por exemplo, para "xml". Buffers modificados não são excluídos. Pressione \ bd para excluir os buffers.

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

[Editar] Mesmo sem: bufdo (conforme solicitado por Luc Hermitte, veja o comentário abaixo)

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
Habi
fonte
1
Eu não gosto :bufdo, pois mexe com a janela atual.
Luc Hermitte 01/07
3

Eu também precisava dessa funcionalidade o tempo todo. Esta é a solução que tenho no meu 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>')

Agora, eu posso fazer :BW regex(por exemplo, :BW \.cpp$e limpar todos os buffers correspondentes que correspondam a esse padrão em seu nome de caminho.

Se você deseja excluir, em vez de limpar, é claro que pode substituir exec 'bw ' . join(l:matchList, ' ')porexec 'bd ' . join(l:matchList, ' ')

Kent
fonte
Às vezes me pergunto por que vim não suporta expressões regulares em todos os lugares ( :badd, :bdelete, :bufdo, :bn...)
puk
1

Muito simplesmente: use o :bd[elete]comando Por exemplo, :bd[elete] buf#1 buf#5 buf#3excluirá os buffers 1, 3 e 5.

atormentar
fonte
1

TABsó irá completar automaticamente um arquivo para você a partir de Vim 7.4.282
uso <c-a>de autocomplete todos os arquivos.

Você pode apenas usar:

bd filetype

use apenas <c-a>para facilitar a conclusão de todos os arquivos abertos do tipo de arquivo especificado.

por exemplo, você tem 1.xml, 2.xml, 3.xml e 4.xml, você pode:

bd xml

então aperte <c-a>

O vim será preenchido automaticamente para você da seguinte maneira:

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

você pode simplesmente pressionar enter para concluir o comando.

Se você fez alterações em um dos arquivos mencionados acima, lembre-se de fazer:

bd! xml
estuque
fonte