Vim имеет множество команд для закрытия чего угодно и в каких угодно сочетаниях, но чего он не умеет так это закрывать все одной командой. Человеку который начал использовать Vim недавно, это может показаться довольно странным. Попробуем разобраться, как исправить эту ситуацию.Когда я впервые познакомился с 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. Вкладками(табами) я не пользуюсь, мне вполне хватает сплитов в пределах одного экрана,
а проблем при работе с буферами они не решают, только добавляют.
