Навигация в крупных проектах для Vim и Emacs +23


Из публикаций о Vim и Emacs складывается впечатление, что мало кто использует в них человеческую навигацию по коду. Или же используют вместо нее инструменты вроде ack и ag. А между тем для навигации в этих редакторах есть эффективные инструменты, которые существуют уже не одно десятилетие. Эти инструменты Ctags и Gnu global — они представлены во всех основных серверных Linux-дистрибутивах, так что навигация будет работать даже если разработка ведется на удаленном сервере.

Я буду писать большей частью про Emacs, потому что пользуюсь им, но буду давать ссылки на соответствующие плагины для Vim. Главное донести принцип работы и основные возможности инструментов и отговорить вас от неумеренного использования ack, ag и grep.


Ctags и Gnu global работают примерно одинаково — вы скармливаете им папку с исходниками проекта, и в ней появляются файлы индексов под названием tags, TAGS, GTAGS. В этих файлах хранятся все найденные в проекте символы: классы, методы, функции, переменные и т.п. и их позиции в файле исходного кода. Т.е. компактная информация достаточная для того, чтобы ввести в редакторе имя класса и перескочить в место его объявления. Или получить список файлов, где объявлен класс с таким именем.

Ctags


Ctags — это утилита, которая каждый раз сканирует все файлы проекты, не разбирая менялись они или нет. Для проектов в несколько тысяч файлов работает довольно шустро — до 10 секунд. Можно создавать отдельные файлы индексов для библиотек и для проекта, или для библиотек, бэкенда и фронтенда, и обновлять только тот индекс, который нужно.

Emacs использует файлы индексов Ctags одного формата, а вот Vim и Sublime Text Editor — другой. Поэтому если вы будете генерировать индексы для последующего использования в Emacs, то не забудьте добавить опцию -e.

Эта утилита довольно старая, и бывает двух… нет даже трех видов. Они мало различаются по сути, но сильно различаются по качеству вычленения символов. Самый примитивный из них — ctags идущий в комплекте с Emacs, так называемый etags. Его стоит использовать если больше ничего нет — поддерживает много языков, но мне понравилась только поддержка perl, C, Java. Команда называется etags или ctags.

Второй вариант — это exuberrant ctags. Та версия, которая поддерживается вашим дистрибутивом, и будет поддерживать еще пару лет, устаревшая. Но она гораздо лучше поддерживает парсинг PHP и JS. Команда называется ctags-exuberant.

Самый совершенный вариант — universal ctags. Данная версия поддерживает внешние парсеры типа coffeetags и вообще имеет самые лучшие парсеры для других языков. Желательно использовать именно эту утилиту, пусть и собирать ее придется вручную.

Итак вы определились какую версию будете использовать, а значит можете перейти в папку с проектом и запустить в терминале: ctags -e — если вы используете Emacs, или же просто ctags, если речь идет о другом редакторе.

Использование в Emacs

M-x visit-tags-table и выбираете файл TAGS. Дальше наводите курсор на имя метода и нажимаете M-., затем Enter. Если понимаете, что вы перескочили не на тот символ, то нажимаете C-u M-. — таким образом вы перейдете к следующему определению этого символа, но уже в другом файле. Советую установить helm для удобного выбора из списка тэгов, правда удобным он станет только после того как вы привыкнете к helm во всех остальных местах Emacs...

Если вы пользуетесь Emacs и пишите на PHP, то загляните сюда.

Использование в Vim



Gnu Global


Gnu Global был создан для работы с кодовыми базами проектов размером в несколько гигабайт в то время, когда IDE требующих нескольких гигабайт для работы еще не изобрели. Он работает примерно как и ctags, более того, он даже может использовать ctags в качестве бэкенда для парсинга — это очень удобно, потому что нативным образом Gnu Global поддерживает не так много языков. Однако есть одно важное отличие — Gnu Global не предполагает, что ваш редактор будет загружать файл индексов, а использует для поиска символов специальную утилиту global, которую редактор вызывает при поиске символа.

Также файл индексов оптимизирован таким образом, чтобы его можно было дополнять не переписывая с нуля. Благодаря этому если в проекте поменялся один файл, то парсингу будет подвергнут только он, а не весь проект, что драматически сказывается на скорости обновления. Это удобно, если у вас кода на сотни мегабайт, вы постоянно переключаете ветки или тянете последние изменения.

Для создания файла индексов перейдите в папку проекта и вызовите gtags. Ждите… Но вообще скорость хорошая — исходники JIdea Community Edition, а это порядка 150 мб чистого Java-кода, индексируются меньше чем за минуту. Последующие индексирования следует запускать при помощи gtags -i, чтобы индексировались только изменившиеся файлы.

Использование в Emacs

Лучше всего установить плагин ggtags, взять его можно здесь или в elpa, melpa или marmalade. Потом откройте один из файлов проекта и нажмите M-x ggtags-mode, затем M-x ggtags-visit-project-root и выберите папку где тэги лежат. Все, дальше в рамках файлов проекта если вы нажмете M-., то сработает переход к определению символа, который в данный момент под курсором. Хотите ввести имя символа вручную — C-u M-.. Если у символа больше одного определения, то нажимайте M-n и M-p для переключения между определениями. Чтобы обновить файл тэгов нажмите M-x ggtags-update-tags находясь на одном из файлов проекта.

Несмотря на то что ggtags и progectile оба покушаются на работу с проектами и индексацию оных, они не конфликтуют.

Использование в Vim



Приятного скакания по файлам.
Что вы используете чаще всего для навигации по символам?

Проголосовало 166 человек. Воздержалось 99 человек.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.




К сожалению, не доступен сервер mySQL