Jak usunąć wiele buforów w Vimie?

120

Zakładając, że mam wiele plików otwartych jako bufory w Vimie. Pliki mają *.cpp, *.ha niektóre są*.xml . Chcę zamknąć wszystkie pliki XML z :bd *.xml. Jednak Vim nie pozwala na to (E93: Więcej niż jedno dopasowanie ...).

Czy jest na to sposób?

PS Wiem, że to :bd file1 file2 file3działa. Więc mogę jakoś ocenić *.xmldo file1.xml file2.xml file3.xml?

Thanh DK
źródło

Odpowiedzi:

194

Możesz użyć, <C-a>aby ukończyć wszystkie mecze. Więc jeśli wpiszesz, :bd *.xmla następnie naciśniesz <C-a>, vim wykona polecenie do :bd file1.xml file2.xml file3.xml.

Björn Steinbrink
źródło
8
@Florian <tab>pozwala tylko na przechodzenie między dopasowaniami, umieszczanie pojedynczego wpisu w wierszu poleceń, <C-a>dodaje wszystkie dopasowania jednocześnie.
Björn Steinbrink
mój Boże, masz rację! Przepraszam. tab działa tylko wtedy, gdy jest tylko jeden możliwy wynik.
Florian Klein,
Jak używasz <Ca> z vimem na tmux?
nabycie
4
tmux domyślnie nie wiąże <Ca>, ale jeśli skonfigurowałeś go tak, aby np. używał <Ca> zamiast <Cb> do emulacji ekranu, powinieneś również skonfigurować go do mapowania, na przykład <Ca> a, aby przekazać a < Ca> do programu działającego wewnątrz tmux. Robi to screen-keys.conf dostarczany z tmux.
Björn Steinbrink
7
JFTR, jeśli vim-rsizainstalowałeś (myślę, że to musi być dla wszystkich na * nix), aby uzyskać <C-a>pracę w oryginalny sposób w linii poleceń, powinieneś użyć <C-x> <C-a>zamiast tego.
kostix
43
:3,5bd[elete]   

Usunie zakres bufora od 3 do 5.

Rybak
źródło
19

Możesz również użyć alternatywnie:

    :.,$-bd[elete]    " to delete buffers from the current one to last but one
    :%bd[elete]       " to delete all buffers
Cylian
źródło
1
To działa nieźle. Robię a : ls, aby zobaczyć numery buforów i je : a, bbd, aby usunąć bufory od numeru a do b
Neaţu Ovidiu Gabriel
5

Możesz tego użyć.

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

Dodanie go do polecenia powinno być dość łatwe.

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
źródło
Prawie nic nie wiem o Vimscript, ale co z funkcją glob ()?
Thanh DK
1
glob()da ci tylko istniejące pliki (na twoim twardym dysku), a nie otwarte bufory.
Luc Hermitte
Zapomniałeś fnameescape()buforować nazwy.
ZyX
Właśnie sprawdziłem c:/Program files/foo.bari nawet foo.bar.foodziałało idealnie. fnameescape()mogło być wymagane, jeśli użyłem nazw buforów. Ale sprawdzam tylko, czy nazwy buforów pasują do danego wyrażenia: \.{ext}$- Numery buforów podaję: bd`. Nie mam powodu, aby uciec przed dopasowaniem wyrażeń regularnych.
Luc Hermitte
5

Wypróbuj poniższy skrypt. Przykład dotyczy „txt”, zmień go w razie potrzeby, np. Na „xml”. Zmodyfikowane bufory nie są usuwane. Naciśnij \ bd, aby usunąć bufory.

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

[Edytuj] To samo bez: bufdo (zgodnie z prośbą Luc Hermitte, patrz komentarz poniżej)

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
źródło
1
Nie podoba mi się, :bufdoponieważ psuje bieżące okno.
Luc Hermitte
3

Ja też potrzebowałem tej funkcjonalności przez cały czas. To jest rozwiązanie, które mam w moim 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>')

Teraz mogę po prostu to zrobić :BW regex(np. :BW \.cpp$Wyczyścić wszystkie pasujące bufory, które mają pasujący wzorzec w nazwie ścieżki.

Jeśli chcesz usunąć zamiast wycierać, można oczywiście zastąpić exec 'bw ' . join(l:matchList, ' ')zexec 'bd ' . join(l:matchList, ' ')

Kent
źródło
Czasami zastanawiam się, dlaczego vim nie obsługuje wyrażeń regularnych wszędzie ( :badd, :bdelete, :bufdo, :bn...)
puk
1

Bardzo prosto: użyj :bd[elete]polecenia. Na przykład :bd[elete] buf#1 buf#5 buf#3usunie bufory 1, 3 i 5.

Złupić
źródło
1

TABuzupełni tylko jeden plik dla ciebie jak z Vim 7.4.282
zastosowania <c-a>do autouzupełniania wszystkie pliki.

Możesz po prostu użyć:

bd filetype

następnie użyj, <c-a>aby ułatwić uzupełnianie wszystkich otwartych plików o określonym typie.

na przykład masz 1.xml, 2.xml, 3.xml i 4.xml, możesz wykonać:

bd xml

następnie wciśnij <c-a>

vim automatycznie uzupełni się za Ciebie w następujący sposób:

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

możesz po prostu nacisnąć klawisz Enter, aby zakończyć polecenie.

jeśli dokonałeś zmian w jednym z plików wymienionych powyżej, pamiętaj, aby:

bd! xml
stucash
źródło