Автоматично закривати найстаріші буфери?


9

Нещодавно мені потрібно було відредагувати багато файлів, щоб змінити кожен файл. Щоб дістатися до кожного файлу, я переглянув NERDtree і відкрив один файл за іншим. Коли я відкривав все більше і більше файлів, я помітив, що моє використання пам’яті зростало багато. Закриваючий vim повернув мені багато пам’яті.

У мене встановлено досить багато плагінів, але я думаю, що причина моєї пам’яті настільки різко зросла через кількість буферів, які я відкрив після кількох редагувань.

Чи є спосіб обмежити кількість буферів, які vim дозволяє відкрити за один раз, автоматично закриваючи старі буфери відносно часу редагування?

Відповіді:


5

Давайте вирішимо проблему, а не лікуємо симптоми. Vim зазвичай не повинен використовувати велику кількість пам'яті. Найкраще було б ізолювати це питання. Деякі поради, які допоможуть знайти винуватця:

  • Вимкнути плагіни (використовуйте двійковий пошук, щоб зробити його швидшим)
  • Зменшіть своє ~/.vimrcопускання, щоб побачити, чи є в чому проблема
  • Вимкніть ~/.vimrcповністю черезvim -u NONE

Також див. Як я налагоджую файл vimrc?

Якщо ви знайшли помилку пам’яті з плагіном, зверніться до розробника плагіна. Якщо ви знайшли помилку пам’яті з Vim, тоді подайте звіт про помилку з кроками, щоб відтворити помилку. Подивитися:h bugs


+1; повинно бути можливо відкрити газильйонний буфер у Vim одночасно, і все ще добре. Поки ви не переглядаєте буфер (у вікні чи "вкладці"), він не завантажується в пам'ять.
Мартін Турноїй

@Carpetsmoker, змінні та настройки буфера не зникають, коли буфер не відображається у вікні. Якщо плагін зберігає багато інформації для кожного буфера, як запропонував Пітер, то пам'ять може бути витрачена на максимум (враховуючи, що кінцевий користувач більше нічого не зробить з буфером). BTW: Плагін може не зберігати дані, пов’язані з буферами, b:variablesале в, s:plugin[bufid]якщо підтримувач плагінів вважає за краще не забруднювати загальнодоступний b: "простір імен" . У цьому випадку видалення буфера не обов'язково збирає всі пов'язані змінні / пам'ять.
Люк Ермітт

5

Наступне має відповісти на ваше запитання.

function! s:SortTimeStamps(lhs, rhs)
  return a:lhs[1] > a:rhs[1] ? 1 
     \   a:lhs[1] < a:rhs[1] ? -1
     \                       : 0
endfunction

function! s:Close(nb_to_keep)
  let saved_buffers = filter(range(0, bufnr('$')), 'buflisted(v:val) && ! getbufvar(v:val, "&modified")')
  let times = map(copy(saved_buffers), '[(v:val), getftime(bufname(v:val))]')
  call filter(times, 'v:val[1] > 0')
  call sort(times, function('s:SortTimeStamps'))
  let nb_to_keep = min([a:nb_to_keep, len(times)])
  let buffers_to_strip = map(copy(times[0:(nb_to_keep-1)]), 'v:val[0]')
  exe 'bw '.join(buffers_to_strip, ' ') 
endfunction

" Two ways to use it
" - manually
command! -nargs=1 CloseOldBuffers call s:Close(<args>)
" - or automatically
augroup CloseOldBuffers
  au!
  au BufNew * call s:Close(g:nb_buffers_to_keep)
augroup END
" and don't forget to set the option in your .vimrc
let g:nb_buffers_to_keep = 42

Це потрібно перенести у плагін. Тоді вам доведеться вибрати, як ним користуватися.


3

Я не впевнений, як отримати найстаріші буфери щодо часу редагування, але натомість можна спробувати закрити найстаріші нередаговані буфери. Щось на зразок:

function CloseLast ()
    python <<EOF
import vim
N = 10
listed_buffers = [b for b in vim.buffers if b.options['buflisted'] and not b.options['modified']]
for i in range (0, len (listed_buffers) - N):
    vim.command (':bd' + str (listed_buffers[i].number))
EOF
endfunction

autocmd BufNew * call CloseLast()

Примітки:

  • vim.buffers- це список кожного буфера, відкритого в поточному сеансі, тому він також включає буфери, які не є в списку. Це не те саме, що список, повернутий :ls.
  • Тому ми повинні відфільтрувати приховані або видалені буфери. Це можна перевірити за допомогою options['buflisted'].
  • Аналогічно options['modified']давайте перевірити, чи буфер модифікований.
  • N - кількість немодифікованих, перелічених буферів, які ви хочете відкрити.

Завдяки відповіді Люка Ермітта, з якої я дізнався, як отримати часові позначки, ви можете скористатися наступним, щоб першим вигнати найстаршого неактивного:

listed_buffers = (b for b in vim.buffers if b.options['buflisted'] and not b.options['modified'])
oldest_buffers = sorted (listed_buffers, key = lambda b: eval('getftime("' + b.name + '")'))
for i in range (0, len (oldest_buffers) - N):
    vim.command (':bd' + str (oldest_buffers[i].number))

1
Вам не потрібен пітон. Vim більш ніж достатньо: :let buffers = filter(range(0, bufnr('$')), 'buflisted(v:val) && ! getbufvar(v:val, "&modified")')+:exe 'bw '.join(buffers, ' ')
Люк Ермітт

@LucHermitte Щоправда, але це не питання потреби . Я просто недостатньо знайомий з Vimscript. Довідка IIRC bwговорить, що ви не повинні використовувати його, "якщо ви не знаєте, що робите". Я не. :)
muru

Старі звички. Я завжди користуюся :bw, і ніколи :bd. Я ніколи не бачив сенсу видаляти майже все з буфера, але насправді не все.
Люк Ермітт,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.