Как удалить несколько буферов в Vim?


120

Предполагая, что у меня есть несколько файлов, открытых как буферы в Vim. Файлы есть *.cpp, *.hа некоторые есть *.xml. Я хочу закрыть все файлы XML с помощью:bd *.xml . Однако Vim не позволяет этого (E93: более одного совпадения ...).

Есть какой-либо способ сделать это?

PS Я знаю, что это :bd file1 file2 file3работает. Так что я могу как - то оценивать *.xmlс file1.xml file2.xml file3.xml?

Ответы:


194

Вы можете использовать <C-a>для завершения всех матчей. Поэтому, если вы наберете, :bd *.xmlа затем нажмете <C-a>, vim завершит команду до :bd file1.xml file2.xml file3.xml.


8
@Florian <tab>позволяет вам только циклически перебирать совпадения, помещая одну запись в командную строку, <C-a>добавляя все совпадения сразу.
Björn Steinbrink

боже ты прав! Прости. вкладка просто работает, когда есть только один возможный результат.
Florian Klein

Как вы используете <Ca> с vim на tmux?
набн

4
tmux не связывает <Ca> по умолчанию, но если вы настроили его, например, на использование <Ca> вместо <Cb> для эмуляции экрана, вы также должны настроить его для сопоставления, например, <Ca> a для передачи < Ca> через программу, работающую внутри tmux. Это делает screen-keys.conf, который идет с tmux.
Björn Steinbrink

7
JFTR, если вы vim-rsiустановили (я думаю, он должен быть у всех на * nix), вместо этого <C-a>вы должны использовать , чтобы получить работу оригинальным способом в командной строке <C-x> <C-a>.
kostix


19

Вы также можете использовать альтернативно:

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

1
Это прекрасно работает. Я делаю : ls, чтобы увидеть номера буферов, и их : a, bbd, чтобы удалить буферы с номера a до b
Neaţu Ovidiu Gabriel

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()предоставит вам только существующие файлы (на вашем жестком диске), а не открытые буферы.
Люк Эрмитт 01

Вы забыли fnameescape()буферизовать имена.
ZyX

Я только что проверил c:/Program files/foo.bar, и даже foo.bar.fooон отлично работал. fnameescape()могло потребоваться, если бы я использовал имена буферов. Но я только проверяю, соответствуют ли имена буферов заданному выражению: \.{ext}$- Я даю номера буфера: bd`. У меня нет причин избегать чего-либо для сопоставления регулярных выражений.
Люк Эрмитт 02

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

[Edit] То же самое без: bufdo (по просьбе Люка Эрмитта, см. Комментарий ниже)

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как это портит текущее окно.
Люк Эрмитт 01

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, ' ')


Я иногда удивляюсь , почему ВИМ не поддерживает регулярные выражения всюду ( :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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.