¿Cómo eliminar múltiples búferes en Vim?

120

Suponiendo que tengo varios archivos abiertos como búfer en Vim. Los archivos tienen *.cpp, *.hy algunos lo son *.xml. Quiero cerrar todos los archivos XML con :bd *.xml. Sin embargo, Vim no lo permite (E93: Más de una coincidencia ...).

¿Hay alguna forma de hacer esto?

PD: Sé que :bd file1 file2 file3funciona. Así que ¿hay algún modo de evaluar *.xmla file1.xml file2.xml file3.xml?

Gracias DK
fuente

Respuestas:

194

Puede utilizar <C-a>para completar todos los partidos. Entonces, si escribe :bd *.xmly luego presiona <C-a>, vim completará el comando para :bd file1.xml file2.xml file3.xml.

Björn Steinbrink
fuente
8
@Florian <tab>solo le permite recorrer las coincidencias, poniendo una sola entrada en la línea de comando, <C-a>agrega todas las coincidencias a la vez.
Björn Steinbrink
dios mio tienes razon! lo siento. La pestaña solo funciona cuando solo hay un resultado posible.
Florian Klein
¿Cómo se usa <Ca> con vim en tmux?
nabn
4
tmux no vincula <Ca> por defecto, pero si lo configuró para, por ejemplo, usar <Ca> en lugar de <Cb> para emular la pantalla, también debe configurarlo para mapear, por ejemplo, <Ca> a para pasar un < Ca> hasta el programa que se ejecuta dentro de tmux. El screen-keys.conf que viene con tmux hace eso.
Björn Steinbrink
7
JFTR, en caso de que lo haya vim-rsiinstalado (creo que es imprescindible para todos en * nix), para obtener el <C-a>trabajo de la forma original en la línea de comandos, debe usar <C-x> <C-a>en su lugar.
kostix
43
:3,5bd[elete]   

Eliminará el rango de búfer de 3 a 5.

Pescador
fuente
19

También puede utilizar alternativamente:

    :.,$-bd[elete]    " to delete buffers from the current one to last but one
    :%bd[elete]       " to delete all buffers
Cylian
fuente
1
Esto funciona bien. Hago un : ls para ver los números de búfer y ellos : a, bbd para eliminar los búferes del número a al b
Neaţu Ovidiu Gabriel
5

Puedes usar esto.

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

Debería ser bastante fácil agregarlo a un 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
fuente
No sé casi nada sobre Vimscript, pero ¿qué hay de la función glob ()?
Thanh DK
1
glob()solo le dará los archivos existentes (en su disco duro) y no los búferes abiertos.
Luc Hermitte
Olvidó fnameescape()almacenar los nombres en búfer.
ZyX
Acabo de comprobarlo c:/Program files/foo.bar, e incluso foo.bar.fooy funcionó perfectamente. fnameescape()puede haber sido necesario si utilicé los nombres de búfer. Pero solo estoy verificando si los nombres de búfer coinciden con una expresión dada: \.{ext}$- Le doy números de búfer a: bd`. No tengo ninguna razón para escapar de nada para la coincidencia de expresiones regulares.
Luc Hermitte
5

Pruebe el siguiente guión. El ejemplo es para "txt", cámbielo según sea necesario, por ejemplo, a "xml". Los búferes modificados no se eliminan. Presione \ bd para eliminar los búferes.

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] Lo mismo sin: bufdo (según lo solicitado por Luc Hermitte, vea el comentario a continuación)

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
fuente
1
No me gusta :bufdoporque ensucia la ventana actual.
Luc Hermitte
3

Yo también necesitaba esta funcionalidad todo el tiempo. Esta es la solución que tengo en mi 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>')

Ahora, puedo hacer :BW regex(por ejemplo, :BW \.cpp$y borrar todos los búferes coincidentes que coinciden con ese patrón en su nombre de ruta.

Si desea eliminar en lugar de limpiar, por supuesto, puede reemplazar exec 'bw ' . join(l:matchList, ' ')conexec 'bd ' . join(l:matchList, ' ')

Kent
fuente
A veces me pregunto por qué vim no admite expresiones regulares en todas partes ( :badd, :bdelete, :bufdo, :bn...)
PUK
1

Muy simple: usa el :bd[elete]comando. Por ejemplo, :bd[elete] buf#1 buf#5 buf#3eliminará los búferes 1, 3 y 5.

Harry
fuente
1

TABsolo autocompletará un archivo para usted a partir de Vim 7.4.282
use <c-a>para autocompletar todos los archivos.

Puedes usar:

bd filetype

luego, utilice <c-a>para facilitar la finalización de todos los archivos abiertos del tipo de archivo especificado.

por ejemplo, tiene 1.xml, 2.xml, 3.xml y 4.xml, puede hacer:

bd xml

entonces presione <c-a>

vim se autocompletará de la siguiente manera:

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

puede simplemente presionar enter para completar el comando.

Si ha realizado cambios en uno de los archivos mencionados anteriormente, recuerde hacer:

bd! xml
stucash
fuente