На днях я искал решение этой проблемы и наткнулся на отличный пост Рэя Грассо от апреля 2015 года. Я рекомендую прочитать пост, чтобы узнать о его решении; Я просто немного его изменил. Он также ссылается на свои точечные файлы, которые включают обновления с момента публикации сообщения.
О ctags
Много лет назад я познакомился с базовыми ctags
функциями в vim
. Но ctags
сам по себе гораздо более гибкий и может использоваться большинством редакторов. Я настоятельно рекомендую вам посетить веб-сайт ctags
, а также плагины для популярных редакторов, таких как vscode, atom и sublime text.
По сути, ctags
будет сканировать все файлы, которые вы его запрашиваете, и искать то, что он понимает как определения символов. Это классы, функции, имена переменных и так далее. ctags
имеет большой список известных языков, но поддержка JavaScript пока не самая лучшая.
Для начала убедитесь, что у вас установлено exuberant-ctags
, а не обычные теги ctags. Например, вы можете brew install ctags
на компьютере с macOS, на котором будет установлена последняя версия exuberant-ctags
.
Внутри vim
Создание ctags
Я использую ctags
, чтобы перейти к определению символа в данном проекте. Обычно это достигается двумя способами: с помощью курсора над символом и использования команд нормального режима для поиска в списке определенных тегов.
Переход к определению под курсором
Во время чтения кода, когда курсор находится над известным символом, нажатие Ctrl+]
приведет к переходу к этому определению.
Поиск доступных тегов
Если вы знаете, какой тег вам нужен, но не знаете его, вы можете :tag <tagname>
перейти к его определению. Команда :tag
поддерживает завершение табуляции; Я часто использую :tag
поиск, чтобы перейти к определениям классов или констант.
Навигация по нескольким совпадениям
Любой из этих способов перехода к определению может привести к совпадению нескольких тегов. Вы можете перемещаться по стеку тегов с помощью :tnext
(кратко, :tn
) или :tprevious
(:tp
). Если вы хотите увидеть список определений, найденных для любого данного тега, вы можете :tselect
(:tsel
).
Включение других пакетов в созданный файл тегов
Хотя это может занять слишком много времени в зависимости от размера вашего графа зависимостей, я счел полезным в некоторых случаях включить мой каталог node_modules
в мой файл tags
. В то время как я обычно включаю только базовые каталоги, такие как app
, config
и lib
, бывают случаи, когда мне нужно проверить источник модуля в том же сеансе, что и код моего приложения. Одним из примеров может быть случай, когда я впервые использую библиотечный модуль, и я не уверен, как все работает под прикрытием, или почему то, что я ожидаю, просто не так.
Ваш новый файл .ctags
После небольшой обрезки и изучения эта часть моего ~/.ctags
файла, относящаяся к JavaScript, выглядит так:
--exclude=node_modules --exclude=gulp --languages=-javascript --langdef=js --langmap=js:.js --langmap=js:+.jsx --regex-js=/[ \t.]([A-Z][A-Z0-9._$]+)[ \t]*[=:][ \t]*([0-9"'\[\{]|null)/\1/n,constant/ --regex-js=/\.([A-Za-z0-9._$]+)[ \t]*=[ \t]*\{/\1/o,object/ --regex-js=/['"]*([A-Za-z0-9_$]+)['"]*[ \t]*:[ \t]*\{/\1/o,object/ --regex-js=/([A-Za-z0-9._$]+)\[["']([A-Za-z0-9_$]+)["']\][ \t]*=[ \t]*\{/\1\.\2/o,object/ --regex-js=/([A-Za-z0-9._$]+)[ \t]*=[ \t]*\(function\(\)/\1/c,class/ --regex-js=/['"]*([A-Za-z0-9_$]+)['"]*:[ \t]*\(function\(\)/\1/c,class/ --regex-js=/class[ \t]+([A-Za-z0-9._$]+)[ \t]*/\1/c,class/ --regex-js=/([A-Za-z$][A-Za-z0-9_$()]+)[ \t]*=[ \t]*[Rr]eact.createClass[ \t]*\(/\1/c,class/ --regex-js=/([A-Z][A-Za-z0-9_$]+)[ \t]*=[ \t]*[A-Za-z0-9_$]*[ \t]*[{(]/\1/c,class/ --regex-js=/([A-Z][A-Za-z0-9_$]+)[ \t]*:[ \t]*[A-Za-z0-9_$]*[ \t]*[{(]/\1/c,class/ --regex-js=/([A-Za-z$][A-Za-z0-9_$]+)[ \t]*=[ \t]*function[ \t]*\(/\1/f,function/ --regex-js=/(function)*[ \t]*([A-Za-z$_][A-Za-z0-9_$]+)[ \t]*\([^)]*\)[ \t]*\{/\2/f,function/ --regex-js=/['"]*([A-Za-z$][A-Za-z0-9_$]+)['"]*:[ \t]*function[ \t]*\(/\1/m,method/ --regex-js=/([A-Za-z0-9_$]+)\[["']([A-Za-z0-9_$]+)["']\][ \t]*=[ \t]*function[ \t]*\(/\2/m,method/ --langdef=typescript --langmap=typescript:.ts --regex-typescript=/^[ \t]*(export)?[ \t]*class[ \t]+([a-zA-Z0-9_]+)/\2/c,classes/ --regex-typescript=/^[ \t]*(export)?[ \t]*module[ \t]+([a-zA-Z0-9_]+)/\2/n,modules/ --regex-typescript=/^[ \t]*(export)?[ \t]*function[ \t]+([a-zA-Z0-9_]+)/\2/f,functions/ --regex-typescript=/^[ \t]*export[ \t]+var[ \t]+([a-zA-Z0-9_]+)/\1/v,variables/ --regex-typescript=/^[ \t]*var[ \t]+([a-zA-Z0-9_]+)[ \t]*=[ \t]*function[ \t]*\(\)/\1/v,varlambdas/ --regex-typescript=/^[ \t]*(export)?[ \t]*(public|private)[ \t]+(static)?[ \t]*([a-zA-Z0-9_]+)/\4/m,members/ --regex-typescript=/^[ \t]*(export)?[ \t]*interface[ \t]+([a-zA-Z0-9_]+)/\2/i,interfaces/ --regex-typescript=/^[ \t]*(export)?[ \t]*enum[ \t]+([a-zA-Z0-9_]+)/\2/e,enums/ --regex-typescript=/^[ \t]*import[ \t]+([a-zA-Z0-9_]+)/\1/I,imports/
Обертывание в псевдоним
Наконец, следуя примеру г-на Грассо, давайте избавимся от чрезмерно жадного сопоставления и превратим его в красивый псевдоним:
alias jtags=”ctags -R app config lib && sed -i ‘’ -E ‘/^(if|switch|function|module\.exports|it|describe).+language:js$/d’ tags”
Удачного вимминга!