Làm thế nào để xóa nhiều bộ đệm trong Vim?


120

Giả sử tôi có nhiều tệp được mở dưới dạng bộ đệm trong Vim. Các tập tin có *.cpp, *.hvà một số *.xml. Tôi muốn đóng tất cả các tệp XML bằng :bd *.xml. Tuy nhiên, Vim không cho phép điều này (E93: Nhiều hơn một trận đấu ...).

Có cách nào để làm điều này?

Tái bút tôi biết điều đó :bd file1 file2 file3hoạt động. Vì vậy, bằng cách nào đó tôi có thể đánh giá *.xmlđể file1.xml file2.xml file3.xml?

Câu trả lời:


194

Bạn có thể sử dụng <C-a>để hoàn thành tất cả các trận đấu. Vì vậy, nếu bạn gõ :bd *.xmlvà sau đó nhấn <C-a>, vim sẽ hoàn thành lệnh :bd file1.xml file2.xml file3.xml.


8
@Florian <tab>chỉ cho phép bạn duyệt qua các trận đấu, đặt một mục nhập duy nhất trên dòng lệnh, <C-a>thêm tất cả các trận đấu cùng một lúc.
Björn Steinbrink

Chúa ơi, bạn nói đúng! lấy làm tiếc. tab chỉ hoạt động khi chỉ có một kết quả khả thi.
Florian Klein,

Làm thế nào để bạn sử dụng <C>> với vim trên tmux?
nabn

4
tmux không ràng buộc <C >>> theo mặc định, nhưng nếu bạn định cấu hình nó để ví dụ: sử dụng <C> thay vì <Cb> để mô phỏng màn hình, bạn cũng nên định cấu hình nó để ánh xạ, ví dụ: <C> a để chuyển < Ca> đến chương trình chạy bên trong tmux. Screen-key.conf đi kèm với tmux thực hiện điều đó.
Björn Steinbrink

7
JFTR, trong trường hợp bạn đã vim-rsicài đặt (tôi nghĩ, nó phải có cho tất cả mọi người trên * nix), để <C-a>làm việc theo cách ban đầu trong dòng lệnh, bạn nên sử dụng <C-x> <C-a>thay thế.
kostix


19

Bạn cũng có thể sử dụng cách sử dụng khác:

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

1
Điều này hoạt động tốt. Tôi làm một : ls để xem đệm số và chúng : a, BBD để đệm xóa từ số a đến b
Neaţu Ovidiu Gabriel

5

Bạn có thể sử dụng cái này.

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

Sẽ khá dễ dàng để thêm nó vào một lệnh.

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

Tôi không biết gì về Vimscript, nhưng làm thế nào về chức năng global?
Thanh DK

1
glob()sẽ chỉ cung cấp cho bạn các tệp hiện có (trên ổ cứng của bạn) chứ không phải bộ đệm đã mở.
Luc Hermitte

Bạn quên fnameescape()đệm tên.
ZyX

Tôi vừa kiểm tra với c:/Program files/foo.bar, và thậm chí foo.bar.foovà nó hoạt động hoàn hảo. fnameescape()có thể đã được yêu cầu nếu tôi sử dụng các tên đệm. Nhưng tôi chỉ kiểm tra xem tên bộ đệm có khớp với một biểu thức nhất định hay không: \.{ext}$- Tôi cung cấp số bộ đệm cho: bd`. Tôi không có bất kỳ lý do gì để trốn tránh bất cứ điều gì để đối sánh regex.
Luc Hermitte

5

Hãy thử tập lệnh bên dưới. Ví dụ là cho "txt", hãy thay đổi nó khi cần thiết, ví dụ: thành "xml". Bộ đệm đã sửa đổi không bị xóa. Nhấn \ bd để xóa bộ đệm.

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

[Chỉnh sửa] Tương tự mà không có: bufdo (theo yêu cầu của Luc Hermitte, xem bình luận bên dưới)

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
Tôi không thích :bufdovì nó làm rối tung cửa sổ hiện tại.
Luc Hermitte

3

Tôi cũng đã từng có nhu cầu về chức năng này. Đây là giải pháp tôi có trong vimrc của mình.

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

Bây giờ, tôi chỉ có thể làm :BW regex(ví dụ: :BW \.cpp$và xóa tất cả các bộ đệm phù hợp khớp với mẫu đó trong tên đường dẫn của chúng.

Nếu bạn muốn xóa thay vì xóa, tất nhiên bạn có thể thay thế exec 'bw ' . join(l:matchList, ' ')bằngexec 'bd ' . join(l:matchList, ' ')


Đôi khi tôi tự hỏi tại sao vim không hỗ trợ biểu thức thông thường ở khắp mọi nơi ( :badd, :bdelete, :bufdo, :bn...)
PUK

1

Rất đơn giản: sử dụng :bd[elete]lệnh. Ví dụ: :bd[elete] buf#1 buf#5 buf#3sẽ xóa các bộ đệm 1, 3 và 5.


1

TABsẽ chỉ tự động hoàn thành một tệp cho bạn kể từ Vim 7.4.282
sử dụng <c-a>để tự động hoàn tất tất cả các tệp.

Bạn chỉ có thể sử dụng:

bd filetype

thì chỉ cần sử dụng <c-a>để tạo điều kiện hoàn thành tất cả các tệp đang mở của loại tệp được chỉ định.

ví dụ: bạn có 1.xml, 2.xml, 3.xml và 4.xml, bạn có thể làm:

bd xml

sau đó nhấn <c-a>

vim sẽ tự động hoàn thành cho bạn như sau:

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

bạn chỉ cần nhấn enter để hoàn tất lệnh.

nếu bạn đã thực hiện các thay đổi đối với một trong các tệp được đề cập ở trên, hãy nhớ thực hiện:

bd! xml
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.