
Когда я впервые познакомился с Vim у меня глаза разбежались от обилия способов
закрытия фaйлов, окон и самого редактора. Вот перечень команд удаления(закрытия)
буферов и окон(в квадратных скобках указаны полные названия команд):
- :bd[elete] — удалить буфер. На самом деле просто делает буфер невидимым, но
оставляет его в памяти. - :bw[ipeout] — полностью стирает(wipeout) буфер из памяти
- :bun[load] — удаляет буфер из памяти, но оставляет его в списке буферов.
Бесполезная команда, кроме тех случаев когда у Вас либо
гигантских размеров файл либо чрезвычайно мало оперативной памяти. - :close — закрыть текущий сплит. Буфер не удаляется
- :q[uit] — чисто теоретически команда должна закрывать Vim, на практике все немного сложнее
Я настоятельно рекомендую установить в .vimrc опцию set confirm, это позволит
избежать надоедливых сообщений об ошибке при попытке закрыть(удалить) буфер с
не сохраненными изменениями. Вместо ошибки будет появляться подтверждение
закрытия не сохраненного файла.
Для закрытия файла в традиционном смысле(для любого другого редактора)
подходит команда :bw, но к сожалению все команды по работе с буферами
обладают отвратительным свойством закрывать то окно в котором, в данный момент
они отображаются(естественно, если это не единственное окно на экране).
Данная проблема проблема решается установкой плагина bufkill.vim и использованием команды
:BW(:BD, :BUN) вместо :bw(:bd, :bun).
Команда :q должна закрывать Vim, но ее поведение зависит от ситуации и далеко не
интуитивно. Для закрытия окна используется команда :close, но закрыть с её
помощью последнее окно Вы не сможете. Также нельзя закрыть Vim с помощью
команд удаления буфера(даже если буфер последний).
По итогу пустой буфер невозможно удалить, последнее окно
нельзя закрыть и работа с несколькими файлами превращается в игру «угадай какую
команду нужно использовать сейчас — :bw, :BW, :q или :close». После
прочесывания форумов, мне пришлось изобретать велосипед, потому
как нужный мне я так и не нашел. Что мне было нужно так это привычный(по другим
редакторам) и интуитивный способ быстро закрывать файлы, окна и сам Vim.
Первая проблема — определиться с алгоритмом «привычного» способа производить все
вышеописанное. Путем проб и ошибок алгоритм стал вот таким:

На первый взгляд немного сложно, но когда начинаешь использовать — все встает на
свои места. Конечно это не панацея — окна(не буферы) по прежнему необходимо закрывать
с помощью :close.
Вот так выглядит реализация:
function! CountListedBuffers()
let cnt = 0
for nr in range(1,bufnr("$"))
if buflisted(nr)
let cnt += 1
endif
endfor
return cnt
endfunction
function! SmartExit()
let s:BufferToKill = bufnr('%')
let s:EmptyBuffer = 0
if bufname('%') == '' && ! &modified && &modifiable
if &buftype == 'nofile' && &swapfile == 0
" Is scratch buffer, not empty
else
let s:EmptyBuffer = 1
endif
endif
" Get a list of all windows which have this buffer loaded
let s:WindowListWithBufferLoaded = []
let i = 1
let buf = winbufnr(i)
while buf != -1
if buf == s:BufferToKill
let s:WindowListWithBufferLoaded += [i]
endif
let i = i + 1
let buf = winbufnr(i)
endwhile
" Check that the buffer is last
if(CountListedBuffers() < 2)
let s:LastBuffer = 1
else
let s:LastBuffer = 0
endif
if s:LastBuffer
if len(s:WindowListWithBufferLoaded) > 1
execute "close"
else
if ! s:EmptyBuffer
execute "bw | bw"
else
execute "q"
endif
endif
else
let g:BufKillActionWhenBufferDisplayedInAnotherWindow="kill"
execute "BW"
let g:BufKillActionWhenBufferDisplayedInAnotherWindow="confirm"
endif
endfunction
Для работы необходим установленный bufkill.vim.
В итоге мой меппинг для «закрытия всего и вся» выглядит так:
" «Умное» закрытие
nmap qq :call SmartExit()" Закрыть окно, но не удалять буфер
nmap qw <C-W>c
qq используется мною гораздо чаще, она делает именно то, что в моём понимании
должна была бы делать :q, но почему то не делает.
Закрытие
Итог
Vim'ом я пользуюсь с недавних пор, но у меня сложилось впечатление
что писать подобные костыли и велосипеды мне придется еще не раз! Но что уж
греха таить — это чрезвычайно увлекательно. Надеюсь данный мини-плагин или
информация из этой статьи кому-то пригодится.
P.S. Не холивара ради, но как с этим обстоят дела у Emacs?
P.P.S. Вкладками(табами) я не пользуюсь, мне вполне хватает сплитов в пределах одного экрана,
а проблем при работе с буферами они не решают, только добавляют.