18 нояб. 2010 г.

Shell в отдельном буфере vim'а

Лично мне, кажется весьма удобной возможность работать в консоли (например в том же bash'е) не отвлекаясь от любимого vim'а. Можно одновременно коммитить код или изменять структуру каталогов проекта или делать прочие подобные вещи не выходя из vim'а и не отвлекаясь на другие окна.
Раньше (пару лет назад), я искал плагин, который позволил бы открывать отдельный буфер с каким-нибудь shell'ом, но натыкался на предложения перекомпилировать vim, предварительно применив к его исходникам набор патчей. Естественно, меня не устраивало подобное положение вещей - мне хотелось простого плагина, а не плясок с бубном.
Оказывается, выход есть! Подобный плагин существует и называется Conque Shell.

Данный плагин позволяет открывать вертикальный или горизонтальный буфер или новую вкладку с практически любым командным интерпретатором. Также, можно открывать выбранный интерпретатор и в текущем буфере. Можно запускать почти все консольные программы - мне не удалось запустить лишь mc.
Как видно, цвета вполне хорошо отображаются даже в таком терминале...

Установка плагина проста и состоит из 4 шагов:
  • Нужно скачать последнюю версию conque.vba отсюда
  • Открыть скачанный файл в vim'е
  • Сказать в нормальном режиме :so %
  • Выйти из vim'а
В зависимостях у плагина лишь сам Vim и Python.

Существует всего 4 основных команды для работы с плагином:
  • :ConqueTerm bash - открывает терминал с bash'ем в текущем буфере
  • :ConqueTermSplit bash - открывает терминал с bash'ем в новом горизонтальном буфере
  • :ConqueTermVSplit bash - то же самое, что и в предыдущем пункте, но буфер теперь вертикальный
  • :ConqueTermTab bash - то же самое, но вместо нового буфера открывается новая вкладка
Команду  создания нового горизонтального буфера с запущенным bash'ем я повесил у себя на отдельный хоткей. Вначале создается соответствующий буфер, затем в нем отключается, включенная мной ранее для всего Vim'а, подсветка пробелов и табуляций (чтобы не мешала), затем осуществляется переход в режим вставки для начала работы с запущенным интерпретатором.

"Открываем Bash в горизонтальном окне/буфере
"после отключаем подсветку пробелов и табуляций 
"для открытого буфера
imap <C-c>b <Esc>:ConqueTermSplit bash<CR><Esc>:setlocal nolist<CR>a
nmap <C-c>b :ConqueTermSplit bash<CR><Esc>:setlocal nolist<CR>a

Настройки ConqueTerm просты и достаточно подробно описаны в :help ConqueTerm. Я опишу лишь те настройки, которые я был вынужден поменять для своего удобства.

"настройки для ConqueTerm
let g:ConqueTerm_InsertOnEnter = 0
let g:ConqueTerm_CWInsert = 1 "по прежнему переходим между окнами по <C-w>[whjkl]
let g:ConqueTerm_TERM = 'xterm'
let g:ConqueTerm_ReadUnfocused = 1
let g:ConqueTerm_CloseOnEnd = 1
let g:ConqueTerm_SendFunctionKeys = 1

InsertOnEnter = 0 означает, что при переходе в буфер с открытым интерпретатором vim не будет самостоятельно переходить в режим вставки. Так как-то привычнее... CWInsert  = 1 позволяет переходить между открытыми буферами по <C-w>w и прочим подобным сочетаниям клавиш. Чтобы послать <C-w> терминалу, надо просто нажать и отпустить эти клавиши и подождать.
ReadUnfocused = 1 указывает плагину на необходимость обновления содержимого терминального окна, даже если курсор находится в другом окне. Так можно получать, например, самые свежие показания от top'а. Автоскроллинг не поддерживается - автор пишет, что это связано с ограничениями вимовского скриптового языка.
SendFunctionKeys = 1 заставляет посылать функциональные клавиши F1-F12 напрямую терминалу, а не vim'у.
CloseOnEnd = 1 - буфер закрывается при завершении программы, запущенной в ней. В нашем случае этой программой является bash.
В случае, если терминал нещадно тормозит, имеет смысл отключить поддержку цвета:
let g:ConqueTerm_Color = 0 "disable colors
Конечно будет не так красиво и цветасто, как в обычном терминале, но работать будет довольно быстро.

Радует, что этот плагин поддерживает разнообразные извращения, например такие как это:
uname -a, запущенный в сесси bash'а, которая запущена внутри консольного вима, который запущен в сесии bash'а, которая запущена внутри gvim'а

В заключение, небольшой скринкаст, показывающий как все это работает "в движении":