Использование буферов — довольно фундаментальная часть правильного использования Vim, и, честно говоря, я какое-то время избегал их использования, когда начинал. Это странная концепция, если вы привыкли использовать любую программу с графическим интерфейсом, где чаще всего думают в терминах файлов и вкладок.
Но главной проблемой, которую мне пришлось решить, была команда :ls
, которую я до сих пор нахожу громоздкой и неинтуитивной. Я использовал fzf, чтобы загрузить свой список буферов в конце, который имеет предварительный просмотр и намного проще в использовании, но я все еще немного злился на себя за то, что не смог преодолеть эту фундаментальную часть функциональности Vim без плагина.
Также есть несколько вещей, которые мне не нравятся в команде буфера fzf. Загрузка занимает слишком много времени, вы не можете удалить буферы с его помощью или открыть более одного, и мне все еще приходится обращаться к нему слишком часто.
Я начал решать эту проблему, пытаясь сделать свою собственную функцию отображения буфера, которая открывалась бы быстрее, чем fzf, а также позволяла бы мне удалять буферы. Это включало создание нового скрытого буфера, вставку содержимого списка буферов (благодаря команде :redir
) и ограничение движения курсора вверх и вниз.
кстати: профессиональный совет, вы можете сохранить вывод любой команды, используя либо :redir
…
:redir => o | execute 'ls' | redir END | let buffers = o
…или функция execute()
…
:let buffers = execute('ls')
Иногда лучше использовать redir
, хотя execute
выглядит чище.
Для тех, кто интересуется скриптами vim, вот функция, которую я написал…
" The function's designed to take any command you want and turn it " into a menu list... function! AnyList(cmd, ftype, cursorposition) " If we're already in the buffer menu ignore... if bufname("%") == "menu-list" | return | endif " Save the buffer list into a variable called l:list... silent! redir => o | execute 'silent ' . a:cmd | redir END | let l:list = o " Set up the buffer-list buffer (this makes it hidden)... let g:anylistbuff = bufnr('menu-list', 1) call setbufvar(g:anylistbuff, "&buftype", "nofile") call bufload('menu-list') " Loop over each line in the buffer list and add " it to our empty buffer... let lnum = 0 for line in split(l:list, '\n') let lnum += 1 call setbufline(g:anylistbuff, lnum, line) endfor " If the user leaves the list, delete it... au! BufLeave menu-list execute g:anylistbuff . "bwipeout" " Make a new split and add the new buffer... execute "sbuffer" . g:anylistbuff " Set a cursorline for the menu look and feel... silent! set cursorline " Give the buffer a filetype for color syntax exe "silent! set filetype=" . a:ftype " Depending on the list type you'll want the cursor to " start in a specific position... exe "norm " . a:cursorposition " On "enter" open a buffer for the number " under the cursor... exe "map <silent> <buffer> <cr> :b " . expand("<cword>") . "<cr>" " On "dd" delete the buffer number under the cursor... exe "map <silent> <buffer> dd :bd " . expand("<cword>") . "<cr>V:g/./d\<cr>" . a:cursorposition " Limit movement, you can still do "w" etc, this is just to make " it a bit more like a menu... map <buffer> h <NOP> map <buffer> l <NOP> map <buffer> <esc> <c-w>c endfunction
Теоретически это работает довольно хорошо, но требует дополнительной работы, я обнаружил, что иногда это заставляет буферы вести себя довольно странно среди других проблем, которые я сейчас не могу вспомнить, короче говоря, мне стало скучно, и я пошел дальше, потому что я нашел лучший и более простой способ сделать то, что я хотел.
Вместо этого я просто использую строку состояния.
Я не использую Lightline или какой-либо причудливый плагин для строки состояния, как многие люди. Я никогда не находил их такими полезными. Вместо этого я установил свою собственную строку состояния с несколькими простыми вещами, такими как текущий буфер и текущий файл, а также процент файла.
Если вы запустите эту команду…
:set statusline=%p\ %b\ %f
Ваша строка состояния изменится, чтобы показать, насколько далеко вы прокрутили текущий файл в процентах — это %p
— текущий номер буфера — это %b
— и имя файла — %f
. \
должны избегать пробелов между каждым значением.
Чтобы добавить результат функции в строку состояния, заключите его в фигурные скобки…
:set statusline=%{FugitiveHead()}
Для тех, кто использует плагин Fugitive, это напечатает вашу текущую ветку git.
Вы можете добавить что угодно в строку состояния в виде обычного текста, :set statusline=boom
будет работать, пробелы должны быть экранированы, а все, что следует за %
, будет рассматриваться как специальное значение (см. :h statusline
, чтобы просмотреть полный список специальных значений, а также узнать текущее значение ваша строка состояния в любое время просто запустите :set statusline
).
Я просто добавил свой список буферов с помощью функции и объединил это с несколькими ярлыками для переключения буферов, и теперь я почти никогда не использую fzf для работы с буферами.
function ListBuffers() return join( \map( \getbufinfo({'buflisted':1}), \{ \key, val -> \val.bufnr == buffer_number() ? \(len(val.name) > 0 ? \fnamemodify(val.name, ":t") : '[No Name]') . '*' \: (len(val.name) > 0 ? fnamemodify(val.name, ":t") \: '[No Name]') \} \), ' • ' \) endfunction set statusline=%{ListBuffers()}
Это сопоставляет результат функции getbufinfo
(которая перечисляет текущие буферы) и для каждого элемента проверяет, является ли это текущим буфером, и добавляет *
, если да, и у буфера есть имя, если нет, он показывает [No Name]
. Затем он объединяет результат в строку с красивым символом •
между ними.
Затем я сопоставляю :bnext
с <leader>bn
, :bprevious
с <leader>bp
и :bdelete
с <leader>bd
.
Теперь я могу видеть, сколько у меня буферов, в каком порядке они расположены и в каком я нахожусь. Мне не нужно запускать какую-либо команду, чтобы увидеть их, и мне не нужно думать о том, какое число соответствует какому буферу. .
Таким образом, я никогда не использую fzf для буферов и почти никогда не использую :ls
. На самом деле, теперь, когда я использую :ls
, я нахожу его очень полезным.