Автоматически закрывать старые буферы?

9

Мне нужно было отредактировать много файлов в последнее время для небольшого изменения в каждом файле. Чтобы добраться до каждого файла, я просматривал NERDtree и открывал один файл за другим. Открывая все больше и больше файлов, я заметила, что объем используемой памяти увеличился. Закрытие vim вернуло мне много памяти.

У меня установлено довольно много плагинов, но я думаю, что причина, по которой мое использование памяти так резко возросло, была связана с количеством буферов, которые я открыл после нескольких правок.

Есть ли способ ограничить количество буферов, которые vim позволяет открывать за один раз, автоматически закрывая старые буфера относительно времени редактирования?

TrueJournals
источник

Ответы:

5

Давайте решать проблему, а не лечить симптомы. Vim обычно не должен использовать большие объемы памяти. Было бы лучше изолировать проблему. Несколько советов, которые помогут найти виновника:

  • Отключить плагины (используйте бинарный поиск, чтобы сделать это быстрее)
  • Уменьшите свой ~/.vimrcпух, чтобы увидеть, есть ли проблема
  • ~/.vimrcПолностью отключитьvim -u NONE

Также смотрите Как отладить мой файл vimrc?

Если вы обнаружите ошибку памяти в плагине, обратитесь к разработчику плагина. Если вы обнаружите ошибку памяти в Vim, отправьте отчет об ошибке с инструкциями по ее воспроизведению. Видеть:h bugs

Питер Ринкер
источник
+1; должна быть возможность открывать буфера в Vim в то же время, и все равно быть хорошим. Пока вы не просматриваете буфер (в окне или на вкладке), он не загружается в память.
Мартин Турной
@Carpetsmoker, буферные переменные и настройки не исчезают, когда буфер не отображается в окне. Если плагин хранит много информации для каждого буфера, как предположил Питер, то память может быть потрачена впустую (учитывая, что конечный пользователь больше ничего не будет делать с буфером). Кстати: плагин не может хранить данные, относящиеся к буферам, 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. В bwсправке IIRC говорится, что вы не должны использовать ее «если вы не знаете, что делаете». Я не. :)
Muru
Старые привычки. Я всегда использую :bw, и никогда :bd. Я никогда не видел смысла удалять почти все из буфера, но не все.
Люк Эрмит