Перевод с английского © Гиви Хакеридзе.
Слайды VIM for (PHP) Programmers
на zmievski.org.
См. также
Vim-galore — по-русски,
Ваша проблема с Vim заключается в том, что вы не въехали в vi.
Open Source Fellow, Digg
Twitter: @a
http://gravitonic.com/
PHP Québec Conf ~ March 5, 2009
Научитесь эффективно использовать справку, :help
— ваш друг.
Используйте CTRL-V
перед командами с CTRL
.
Используйте префиксы i_
и v_
для получения справки по последовательностям
с CTRL
в режиме вставки и визуальном режиме.
В окне справки используйте CTRL-]
(прыжок к тегу) и CTRL-T
(перейти обратно).
Насколько хорошо вы знаете язык Vim-а? Какой у него алфавит? Посмотрите на вашу клавиатуру. Вы можете сказать, что делает каждая клавиша? Что такое режимы? Сколько вы их знаете? А сколько используете?
Если язык вам не нравится, измените его.
Пример: Что вы делаете, чтобы быстро выйти из Vim-а?
ZZ
(выход с сохранением)ZQ
(выход без сохранения)или
:nmap ,w :x<CR>
:nmap ,q :q!<CR>
Совет: set showcmd
позволяет видеть частично введённые команды.
Как узнать, где вы находитесь?
CTRL-G
gCTRL-G
Побалуйте себя и выполните set ruler
, которая покажет в строке статуса номер
строки, колонки и проценты. Или сконфигурируйте её так, как вам будет угодно,
при помощи 'rulerformat'
.
Вы используете для перемещения h
/j
/k
/l
?
Или застряли в стрелках мира GUI?
Если так, переучивайтесь.
Спасите себя от бессчётных миль перемещений между домашним рядом клавиш и стрелками.
Как переместиться к:
gg
и G
G
или Ngg
%
^
<CR>
-
Мы можем запоминать положение в буфере:
m<буква>
устанавливает метку с названием <буква>
в текущей позиции `<буква>
переносит к этой метке точно'<буква>
переносит на строку с этой меткой:marks
показывает все установленные меткиМетки очень полезны в изменении текста.
Установите метку (допустим ma
).
Теперь можно:
c`a
— изменить текст от курсора до метки a
d`a
— удалить текст от курсора до метки a
='a
— переформатировать строки, начиная с текущей до строки с меткой a
Допустим, что вы куда-то перепрыгнули.
Как вернуться обратно?
` `
переносит между двумя последними позициями.
Можно явно установить `
(метку контекста):
m`
, перепрыгнуть куда-нибудь, а затем вернуться назад при помощи ` `
.
Совет: CTRL-O
и CTRL-I
переносят между позициями во всей истории прыжков,
но не могут быть использованы в качестве перемещений (как напр., w
или G
— пер.).
'.
и `.
— перепрыгнуть к строке или точному положению последнего изменения.
gi
— невероятно удобная комбинация.
Переводит в режим вставки в том месте, где она производилась в последний раз.
Сценарий: измените что-нибудь, выйдите из режима вставки, посмотрите что-то
в другом месте, а затем при помощи gi
вернитесь назад и возобновите редактирование.
Еще немного вкусностей:
CTRL-Y
и CTRL-E
(если можно, избегайте лишней работы) —
вставляют символы над и под курсоромCTRL-A
(эй, я хочу это повторить) — вставляет ранее вставленный текстCTRL-R=<выражение>
(встроенный калькулятор) — вставляет всё, что Vim может вычислитьCTRL-T
и CTRL-D
(табуляция и де-табуляция) — добавляет или удаляет
отступ размером в ширину сдвига (shiftwidth) в начало строкиОсвободите ваш <Backspace>
:
:set backspace=start,indent,eol
позволяет удалять до начала вставки, автоотступы и даже символы новой строки.
Поиск очень важен.
Перемещение и информация.
Как вы ищите?
Чем-то вроде f
/F
/t
/T
?
Что насчёт *
и #
?
Поиск в строке:
f
/F
<символ>
перемещает к первому <символу>
справа/слева и устанавливает курсор на нёмt
/T
<символ>
делает почти то же, но устанавливает курсор перед символомdf;
— удалить текст от курсора до первого ;
справаcT$
— изменить текст от курсора до первого $
слеваЧасто бывает нужно посмотреть другие употребления слова под курсором:
*
/#
— поиск следующего/предыдущего вхождения целого словаg*
/g#
— найти следующее/предыдущее вхождение части словаИли найти строки с некоторым словом: [I
и ]I
покажут их список.
Для перехода к строке удобно использовать мапинг с включенными файлами:
:map ,f [I:let nr = input("Which one: ")<Bar>exe "normal " . nr ."[\t"<CR>
И, конечно, есть поиск с использованием регулярных выражений:
/<шаблон>
— поиск <шаблона>
вперёд?<шаблон>
— поиск <шаблона>
назадn
повторяет поискN
повторяет поиск в противоположном направленииЯзык регулярных выражений Vim-а слишком сложен для изложения здесь.
Управляйте вашими настройками поиска:
:set wrapscan
— для продолжения поиска с другого конца файла:set incsearch
— поиск по мере набора, <Enter>
— принять,
<Esc>
— отменить:set ignorecase
— поиск без учёта регистра, или используйте внутри
шаблона:
\c
— для поиска без учёта регистра\C
— для поиска с учётом регистраНе забывайте, что любой поиск/прыжок можно использовать в качестве аргумента перемещения:
d/^#
— удалить всё до строки, начинающейся с символа комментарияy/^class/;?function
— скопировать всё, начиная с текущей позиции,
до первой function
перед первым class
:[диапазон]s/<шаблон>/<замена>/{флаги}
— команда замены, используется
обычно с диапазоном адресов, очень мощной вещью (читайте справку).
Но кто захочет считать строки и делать что-то подобное :-23,’ts/foo/bar/
?
На самом деле вы будете использовать пару сокращений или просто визуальный режим.
Часто используемые диапазоны:
%
эквивалентно 1,$
(весь файл).
— текущая строка/<шаблон>/
или ?<шаблон>?
— строка, совпадающая с <шаблон>
:%s/foo/bar/
— заменить первое foo
на bar
в каждой строке всего файла:.,/<\/body>/s,<br>,<br/>,gc
— исправить теги br
, начиная с текущей
строки, до строки с </body>
, с подтверждением (c
- «cautious»,
подтверждение)&
— повторить предыдущую замену в текущей строке&&
— повторить замену, с флагами, которые использовались ранееg&
— повторить замену глобально, используя флагиПознакомьтесь с ними поближе, потому что их фантастически удобно использовать после оператора или в визуальном режиме. Встречайте два типа — «inner» (внутри) и «ambient» (вокруг). «Внутри» всегда выбирает меньше текста, чем «вокруг».
aw
, aW
— вокруг слова или СЛОВА (см. документацию)iw
, iW
— внутри слова или СЛОВА (см. документацию)as
, is
— вокруг или внутри предложенияap
, ip
— вокруг или внутри абзацаa{
, i{
— весь блок {..}
или текст внутри негоa(
, i(
— весь блок (..)
или только текст внутриa<
, i<
— весь блок <..>
или только текст внутриЕсть ещё более крутые:
a'
, i'
— строка в одинарных кавычках или текст внутриa"
, i"
— строка в двойных кавычках или текст внутриЗаметьте, что эти объекты знают об экранированных кавычках внутри строки.
at
, it
— весь блок тега или только текст внутри него
(теги HTML и XML)Примеры:
das
— удалить предложение и пробелы после негоci(
— изменить текст внутри блока (..)
yat
— скопировать весь окружающий ближайший тег, где находится курсорgUi'
— перевести в верхний регистр текст внутри одинарных кавычекvip
— визуально выделить абзац без последующих пробеловЭто вы уже должны знать:
y
— yank (копировать), d
— delete (удалить),
p
paste (вставить) после, P
— вставить перед]p
, ]P
— вставить после/до с расстановкой отступовПолезные мапинги для вставки и последующего переформатирования/расстановки отступов:
:nnoremap <Esc>P P'[v']=
:nnoremap <Esc>p p'[v']=
Регистры — ваш многоцелевой буфер обмена.
Вы используете их, даже не зная о них.
Каждая команда y
или d
копирует в регистр, не именованный или именованный.
"<буква>
перед командой копирования/удаления/вставки указывает регистр
с именем <буква>
.
Копирование в регистр с буквой в верхнем регистре дополняет его содержимое, это полезно для сбора текста из нескольких буферов и последующей вставки как одного целого.
"wyy
— скопировать текущую строку в регистр w
"WD
— удалить до конца строки и добавить удалённое в регистр w
"wp
— вставить содержимое регистра w
CTRL-Rw
— вставить содержимое регистра w
(в режиме вставки)В регистры можно записывать макрокоманды:
q<буква>
— начать запись набранного текста в регистр <буква>
q
останавливает запись@<буква>
проигрывает макро <буква>
@@
повторяет выполнение последнего выполненного макроДля просмотра содержимого регистров используйте :reg
.
У оригинального vi был только один уровень отмены.
Ха!
А Vim имеет бесконечное количество (ограниченное только памятью).
Установите 'undolevels'
таким, какое вам нужно (по умолчанию — 1000).
Простой пример: u
— отмена, CTRL-R
— повторение.
В Vim 7-й версии добавлена отмена с ветвлениями.
Если отменить что-то, а затем сделать изменения, то создаётся новая ветка.
g-
, g+
— переход к более старому/новому состоянию текста (по всем веткам).
Можно путешествовать во времени:
:earlier Ns,m,h
— вернуться к состоянию текста каким он был N
секунд, минут, часов назад:later Ns,m,h
— перейти к состоянию текста позднее похожим образом:earlier 10m
— вернуться на 10 минут назад до того, как я выпил
банку Red Bull и сделал эти дурацкие изменения.
Уфф.
Используйте его, потому что это проще, чем запоминать непонятные диапазоны или команды перемещения.
Начните выделение с:
v
— посимвольноV
— построчноCTRL-V
— блокомИспользуйте любую команду перемещения для изменения выделения.
К выделению можно применить любую команду нормального режима или команду ex :
.
Блочный визуальный режим это — вообще что-то. Особенно для текста в виде таблиц.
Совет: o
переносит курсор на другой конец выделения, где можно продолжить
выделение.
Как только вы оказались в блочном режиме:
I<текст><Esc>
— вставить <текст>
перед блоком в каждой строкеA<текст><Esc>
— добавить <текст>
после блока на каждой строкеc<текст><Esc>
— заменить каждую строку в блоке на <текст>
r<символ><Esc>
— заменить все символы на <символ>
Замена строк в реальном времени. Подстановка выполняется, когда набран символ не ключевого слова:
:ab tempalte template
— исправление опечатки
Расширение посложнее:
:iab techo <?php echo ?><Left><Left><Left>
Научитесь работать с окнами.
Как перемещаться между ними.
:new
, :sp
должны быть на кончиках ваших пальцев.
Очень важно изучить команды с CTRL-W
для изменения размеров окон и перемещения
между ними.
Начиная с 7-й версии, Vim поддерживает вкладки.
:tabe <файл>
— редактировать файл в новой вкладке:tabn
, :tabp
(или gt
, gT
— для переключения)Возможно, вы захотите замапить это для более удобной навигации,
(если gt
, gT
для вас слишком сложно).
Vim очень дружественен в дополнении. В командной строке просто используйте <Tab>
:
'wildmenu'
и 'wildmode'
(мне нравится "list:longest,full"
):new ~/dev/fo<Tab>
— дополнить имя файла:help ‘comp<Tab>
— дополнить имя опции:re<Tab>
— дополнить командуНажимайте <Tab>
повторно для прохода в цикле, CTRL-N
для следующего совпадения,
CTRL-P
— для предыдущего.
CTRL-X
, за которым следуют комбинации с CTRL-
, включает режим дополнения
в режиме вставки. Я в основном использую дополнение имён файлов, идентификаторов
и омни-дополнение. Когда имеется несколько совпадений, появляется окошечко
с вариантами.
CTRL-X CTRL-F
— дополнить имя файлаCTRL-X CTRL-N
— дополнить идентификаторУ меня есть отличный ремапинг для <Tab>
:
“ Вставить <Tab> или дополнить идентификатор,
“ если курсор находится после символа ключевого слова
function MyTabOrComplete()
let col = col('.') - 1
if !col || getline('.')[col-1] !~ '\k'
return "\<tab>"
else
return "\<C-N>"
endif
endfunction
inoremap <Tab> <C-R>=MyTabOrComplete()<CR>
Омни-дополнение основано на эвристике, которая угадывает, как вы хотите дополнить в соответствии с типом файла, который вы редактируете. Чуть поболее — позднее.
Сделали мапинги для каждого режима режимов и утомились менять текст в кавычках?
:nmap X ci"
Сделать Vim похожим на браузер?
:nmap <Space> <PageDown>
Быстро вставить ваш e-mail?
:imap ;EM me@mydomain.com
Пусть <Backspase>
в визуальном режиме работает как <Delete>
?
:vmap <BS> x
У Vim-а — сотни опций. Изучите их, чтобы управлять ими так, как вам нужно.
:options
позволяет изменять опции интерактивно:options | resize
— лучше (опций очень много)В сессии хранятся все виды окон и глобальные настройки. Можно сохранить сессию, а позднее восстановить её. Расположение окон будет прежним.
:mksession <файл>
— сохранение сессии в <файле>
:source <файл>
— загрузить сессию из <файла>
vim -S <файл>
— возобновить редактирование сессииgf
— перейти к файлу под курсором (CTRL-W
CTRL-F
— то же,
в новом окне):read
— прочитать содержимое файла или вывод процесса
:read foo.txt
— прочитать содержимое файла foo.txt:read !wc %:h
— выполнить wc с текущим файлом и вставить
результат в текст (IMHO :h
здесь лишнее — пер.):%!sort
, :%!grep
или используйте :!
в визуальном
режимеvip:!sort
:
и /
перемещают по истории:
и /
с префиксом ограничивают перемещение этим
префиксомq:
и q/
открывают окно редактирования истории (<Enter>
выполняет команду,
CTRL-C
копирует в командную строку)CTRL-A
и CTRL-X
увеличивают/уменьшают число под курсором (шестнадцатеричные
и восьмеричные — тоже)ga
— какой символ у меня под курсором?:set number
для включения нумерации строк:nmap <silent> <F6> set number!<CR>
:set autowrite
— убрать запросы Vim-а хотите ли вы сохранить файл,
когда покидаете буферCTRL-E
/CTRL-Y
— скроллировать окно вниз/вверх без перемещения курсора:set scroloff=N
— начинать скроллинг, когда курсор находится
на расстоянии N строк от верхнего/нижнего края:set updatecount=50
— сохранять своп-файл на диск каждые 50
нажатий на клавиши:set showmatch matchtime=3
— когда вставляется скобка, кратковременно
перепрыгнуть к парной. 3 — в десятых секундыfc
вызывает Vim с последней командой и запускает её после того,
как вы выйдите из Vim (или fc N
чтобы редактировать команду N в истории)vimdiff
в оболочке (:help vimdiff
)CTRL-L
для фрагментного копирования строки над текущей:
imap <C-L> @@@<ESC>hhkywjl?@@@<CR>P/@@@<CR>3s
Настройте Vim, разместив файлы в каталоге ~/.vim (в этом каталоге vimrc д.б. без точки — пер.)
filetype plugin on
, filetype indent on
.vimrc - глобальные настройки
.vim/
after/ - файлы, которые загружаются в последнюю очередь
ftplugin/
plugin/
syntax/
...
autoload/ - автоматически загружаемые скрипты
colors/ - пользовательские цветовые схемы
doc/ - документация к плагинам
ftdetect/ - скрипты для определения типа файла
ftplugin/ - плагины для типов файла
indent/ - скрипты для отступов
plugin/ - плагины
syntax/ - скрипты для подсветки синтаксиса
Vim поддерживает произвольные команды сборки/линтинга, если настроить
'makeprg'
и 'errorformat'
правильно:
:set makeprg=php\ -l\ %
:set errorformat=%m\ in\ %f\ on\ line\ %l
Теперь достаточно набрать :make
(и пару раз <Enter>
), и курсор будет
помещён на строку с синтаксической ошибкой.
Вы уже должны быть знакомы с командой %
(переместить курсор к паре),
которая используется для ()
, {}
, []
и т.д.
Но такое можно использовать и для прыжков между тегами PHP и HTML.
Используйте плагин matchit.vim.
Но syntax/php.vim содержит ошибки и опечатки в правиле поиска соответствия.
Я предлагаю своё.
Схожие с Vim-овскими встроенными объектами:
aP
— PHP-блок, включая тегиiP
— текст внутри PHP-блокаПримеры:
vaP
— выделить текущий PHP-блок (с тегами)caP
— изменить текст внутри текущего PHP-блокаyaP
— скопировать весь PHP-блок (с тегами)Всё это — в моём файле .vim/ftplugin/php.vim.
У Vim-а есть очень полезные плагины для синтаксиса PHP, которые имеют несколько опций:
let php_sql_query=1
для подсветки синтаксиса в строках SQLlet php_htmlInStrings=1
для подсветки в строках HTMLlet php_noShortTags=1
для запрета коротких теговlet php_folding=1
для разрешения свёрток для классов и функцийНаучитесь управлять свёртками:
zo
— раскрыть свёртку (если курсор на строке со свёрткой)zc
— свернуть ближайшую свёрткуzR
— открыть все свёрткиzM
— закрыть все свёрткиzj
— перейти в начало следующей свёрткиzk
— перейти к концу предыдущей свёрткиДля Vim теги это — идентификаторы PHP (классы, функции, константы). Если у вас файл с тегами, то можно быстро переходить к определению любого тега. Установите
. Он умеет сканировать ваши скрипты и выводить файл с тегами, содержащий информацию об идентификаторах. В данный момент он не поддерживает информацию о членах класса (выводит методы как функции). Для исправления этого приходится применять сторонний патч.Для пересборки файла с тегами после редактирования используйте мапинг:
nmap <silent> <F4>
\ :!ctags -f ./tags
\ --langmap="php:+.inc"
\ -h ".php.inc" -R --totals=yes
\ --tag-relative=yes --PHP-kinds=+cf-v .<CR>
set tags=./tags,tags
Будут рекурсивно просканированы все PHP-файлы в текущем каталоге и подкаталогах.
CTRL-]
— перейти к тегу под курсоромCTRL-W
CTRL-]
— перейти к тегу в новом окне:tag <идентификатор>
— перейти к произвольному тегу:tag /<regexp>
— перейти к или показать теги, совпадающие с <regexp>
,
при нескольких совпадениях — выбрать тег из списка:tselect <идентификатор>
или /<regexp>
— вместо перехода показать
списокCTRL-T
— вернуться туда, где были ранееСм. также плагин taglist.vim.
В Vim 7 появилось мощное омни-дополнение основанное на эвристике.
CTRL-X
CTRL-O
начинает дополнение (я замапил это на CTRL-F
).
На основании контекста умно дополняет классы, переменные, методы.
Встроенные функции дополняет тоже.
Дополнение функции показывает прототип.
array_<CTRL-X><CTRL-O>
покажет список функции для работы с массивами.
Выберите одну из списка, и в окне предварительного просмотра будет показан прототип.
CTRL-W
CTRL-Z
— чтобы закрыть окно предварительного просмотра.
Вне блоков PHP переключается на дополнение HTML/CSS/JavaScript.
Дополнительно см.:
:help ins-completion
:help popupmenu-completion
:help popupmenu-keys
:help ft-php-omni
Vim можно бесконечно настраивать и расширять при помощи плагинов. Их написано уже тысячи. Установка очень проста, просто бросьте их в каталог .vim/plugin. Однако сначала прочтите инструкции.
Позволяет читать, записывать и просматривать удалённые каталоги и файлы. Обычно я использую его по ssh-соединению при помощи протокола scp. Чтобы избежать постоянных запросов пароля, нужно запустить ssh-агента. Не используйте беспарольные ключи! Когда настроите, используйте:
vim scp://hostname/path/to/file
:new scp://hostname/path/to/dir/
Похож на браузер netrw, но больше похож на проводник по иерархии каталогов. Не поддерживает удалённые файловые операции.
:nmap <silent> <F7> :NERDTreeToggle<CR>
Обеспечивает обзор исходного кода. Предоставляет быстрый доступ к классам, функциям и константам. Автоматически обновляет окно при переключении буферов. Может показывать прототип и область видимости тега. Требует наличия Exuberant Ctags.
Сохраните это в ~/.vim/after/plugin/general.vim:
let Tlist_Ctags_Cmd = "/usr/local/bin/ctags-ex"
let Tlist_Inc_Winwidth = 1
let Tlist_Exit_OnlyWindow = 1
let Tlist_File_Fold_Auto_Close = 1
let Tlist_Process_File_Always = 1
let Tlist_Enable_Fold_Column = 0
let tlist_php_settings = 'php;c:class;d:constant;f:function'
if exists('loaded_taglist')
nmap <silent> <F8> :TlistToggle<CR>
endif
Реализует некоторую функциональность снипетов TextMate.
Поддерживает многие языки, включая PHP/HTML/CSS/JavaScript.
По умолчанию привязывается к <Tab>
, но это раздражает,
приходится переназначать клавишу после его загрузки.
Поместите это в ~/.vim/after/plugin/general.vim:
if exists('loaded_snippet')
imap <C-B> <Plug>Jumper
endif
inoremap <Tab> <C-R>=MyTabOrComplete()<CR>
Автоматически вставляет блоки PHP Documentor. Работает в одно- и много-строчном режиме. По умолчанию не предоставляет мапинги. Прочитайте документацию, чтобы настроить переменные по умолчанию для копирайта, пакета и т.д.
Добавьте это в ~/.vim/ftplugin/php.vim:
inoremap <buffer> <C-P> <Esc>:call PhpDocSingle()<CR>i
nnoremap <buffer> <C-P> :call PhpDocSingle()<CR>
vnoremap <buffer> <C-P> :call PhpDocRange()<CR>
let g:pdv_cfg_Uses = 1
Предоставляет управление файлами проекта как в IDE. Позволяет группировать файлы и быстрый доступ к ним. Может искать и выполнять произвольные команды.
Поиск различной информации, основанный на тегах. Быстрый доступ к:
Позволяет отладку при помощи xdebug по протоколу DBGp.
Достаточно прост, но работу делает.
Нужно, чтобы Vim был скомпилирован с опцией +python
.
См. раздел ресурсов для ссылок на документацию.
Предоставляет интерфейс с CVS/SVN/git.
Установите его, затем выполните :help vcscommand
.
Vim рулез! Это был лишь поверхностный взгляд с моей очень субъективной точки зрения. Не застревайте в колее, продолжайте читать и пробовать новые вещи.
404
): http://www.live-emotion.com/memo/index.php?plugin=attach&refer=%CA%AA%C3%D6&openfile=ctags-5.6j-php.zip404
): http://2bits.com/articles/using-vim-andxdebug-dbgp-for-debugging-drupal-or-any-php-application.htmlhttp://joind.in/121
http://digg.com/
http://gravitonic.com/talks/