Просмотр исходного кода

Add MRU garbage collection.

This cleans up excess accumulation of deleted tabs and buffers in the
MRU data structures.  Tab deletions are expensive to track via
`TabClosed` events because those events fire after the tab has already
been deleted, so cleanup of dead tabs is handled via garbage collection.

Buffer deletions are tracked via `BufDelete` events, so garbage won't
build up in typical operation; but autocommands may be suppressed (e.g.,
via `:noautocmd bdelete`), necessitating garbage collection for buffers
as well.

To prevent excess garbage build-up caused by many tab deletions between
invocations of BufExplorer, tab garbage collection is invoked on
`TabClosed` events, for Vim versions where that event is supported.
Michael Henry 10 месяцев назад
Родитель
Сommit
78ce3c6a0d
1 измененных файлов с 38 добавлено и 0 удалено
  1. 38 0
      plugin/bufexplorer.vim

+ 38 - 0
plugin/bufexplorer.vim

@@ -141,6 +141,9 @@ augroup BufExplorer
     autocmd WinEnter        * call s:DoWinEnter()
     autocmd BufEnter        * call s:DoBufEnter()
     autocmd BufDelete       * call s:DoBufDelete()
+    if exists('##TabClosed')
+        autocmd TabClosed      * call s:DoTabClosed()
+    endif
     autocmd BufWinEnter \[BufExplorer\] call s:Initialize()
     autocmd BufWinLeave \[BufExplorer\] call s:Cleanup()
 augroup END
@@ -424,6 +427,33 @@ function! s:MRUEnsureTabId(tabNbr)
     return tabId
 endfunction
 
+" MRUGarbageCollectBufs {{{2
+"   Requires `s:raw_buffer_listing`.
+function! s:MRUGarbageCollectBufs()
+    for bufNbr in values(s:bufMru.next)
+        if bufNbr != 0 && !has_key(s:raw_buffer_listing, bufNbr)
+            call s:MRURemoveBuf(bufNbr)
+        endif
+    endfor
+endfunction
+
+" MRUGarbageCollectTabs {{{2
+function! s:MRUGarbageCollectTabs()
+    let numTabs = tabpagenr('$')
+    let liveTabIds = {}
+    for tabNbr in range(1, numTabs)
+        let tabId = s:GetTabId(tabNbr)
+        if tabId != ''
+            let liveTabIds[tabId] = 1
+        endif
+    endfor
+    for tabId in keys(s:bufMruByTab)
+        if tabId != s:tabIdHead && !has_key(liveTabIds, tabId)
+            call s:MRURemoveTab(tabId)
+        endif
+    endfor
+endfunction
+
 " DoWinEnter {{{2
 function! s:DoWinEnter()
     let bufNbr = str2nr(expand("<abuf>"))
@@ -452,6 +482,11 @@ function! s:DoBufDelete()
     call s:MRURemoveBuf(bufNbr)
 endfunction
 
+" DoTabClosed {{{2
+function! s:DoTabClosed()
+    call s:MRUGarbageCollectTabs()
+endfunction
+
 " ShouldIgnore {{{2
 function! s:ShouldIgnore(buf)
     " Ignore temporary buffers with buftype set.
@@ -583,6 +618,9 @@ function! BufExplorer()
 
     silent let s:raw_buffer_listing = s:GetBufferInfo(0)
 
+    call s:MRUGarbageCollectBufs()
+    call s:MRUGarbageCollectTabs()
+
     " We may have to split the current window.
     if s:splitMode != ""
         " Save off the original settings.