Перейти к определению функции в vim

241

Как перейти к определению функции с помощью vim? Например, с помощью Visual Assist я могу ввести Alt+ gпод функцией, и она открывает контекстное меню, в котором перечислены файлы с определениями.

Как я могу сделать что-то подобное в VIM?

Джон Клегг
источник
2
GNU Global лучше, чем ctags.
Джичао
6
@Jichao, не могли бы вы рассказать нам немного больше о своем опыте? С какими языками GNU Global работал лучше для вас? Есть ли что-то еще в контексте, который вы предпочли, чтобы я был важным? Или, может быть, вы использовали его во многих различных сценариях, и вы, кажется, в основном / всегда предпочитаете это? Что тебе больше нравится в этом? Спасибо.
still_dreaming_1
@Jichao Я превратил ваш комментарий в ответ сообщества вики. Я бы приветствовал ваши изменения и вклад в этот ответ.
still_dreaming_1

Ответы:

213

Используйте ctags. Создайте файл тегов и сообщите vim, где он используется, с помощью команды: tags. Тогда вы можете просто перейти к определению функции, используя Ctrl-]

В этом вопросе есть больше трюков и советов .

Пол Томблин
источник
2
php достаточно C-подобен, чтобы с ним работали «Exuberant ctags». Не знаю, есть ли у него режим Python.
Пол Томблин
5
Нет опыта работы с Cscope. Что есть?
Пол Томблин
10
Сходство с C не имеет ничего общего с поддержкой CTags PHP. Он поддерживает как PHP, так и Python. Взгляните на ctags.sourceforge.net/languages.html, чтобы увидеть полную поддержку.
данные
2
как я могу генерировать ctags?
dwaynemac
4
было бы здорово получить ссылку на то, где лучше всего научиться работать с этими ctags.
Fzs2
138

Если все содержится в одном файле, есть команда gd(как в «определении goto»), которая приведет вас к первому вхождению в файл слова под курсором, который часто является определением.

Скотти Т
источник
1
Что делать, если у меня нет слова под курсором (я бы лучше набрал его)?
Фуад Сауд
@FuadSaud просто найдите его с помощью/
LucasB
6
/почти всегда не точен, так как он будет соответствовать всем вхождениям. Я обнаружил, что вы можете :tag <function_name>перейти к определению через ctags.
Фуад Сауд
Функция перехода к определению @Faud основана на указании идентификатора курсором (в каждой IDE). Печатание / поиск - еще одна особенность, вы их путаете.
кровавый
101

g* делает достойную работу без установки ctags.

То есть, типа g, *(или просто *- смотрите ниже) , чтобы найти слово под курсором (в данном случае, имя функции). Затем нажмите, nчтобы перейти к следующему (или Shift- nдля предыдущего) вхождению.

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

- Редактировать-- Хотя я уже давно использую g *, я недавно обнаружил два ярлыка для этих ярлыков!

(а) *перейдет к следующему вхождению слова под курсором. (Нет необходимости вводить команду g'goto' в vi).

(б) #переходит к предыдущему вхождению, аналогичным образом.

N и n по-прежнему работают, но «#» часто очень полезно для начала поиска в обратном направлении, например, при поиске объявления переменной под курсором.

Брент Фауст
источник
10
Разница между *и g*есть границы слов при поиске. *выполняет \<keyword\>поиск (так же, как \bkeyword\bв обычном регулярном выражении), в то время как g*ищет keywordбез слов.
Николай S
если у вас есть сотня вхождений функции в файле, *вам понадобится в среднем 50 обращений, прежде чем вы найдете определение.
naught101
49

Используйте gdили gDпри наведении курсора на любую переменную в вашей программе.

  1. gd приведет вас к местной декларации.
  2. gD приведет вас к глобальной декларации.

больше вариантов навигации можно найти здесь .

Используйте cscope для перекрестных ссылок на большой проект, такой как ядро ​​Linux.

0x90
источник
14

Как сказал Пол Томблин, вы должны использовать ctags . Вы также можете рассмотреть возможность использования плагинов для выбора подходящего или предварительного просмотра определения функции под курсором. Без плагинов у вас будет головная боль при попытке выбрать один из сотен перегруженных методов 'doAction', поскольку встроенная поддержка ctags не учитывает контекст - только имя.

Также вы можете использовать cscope и функцию «найти глобальный символ». Но ваш vim должен быть скомпилирован с поддержкой + cscope, которая по умолчанию не является одним из вариантов сборки.

Если вы знаете, что функция определена в текущем файле, вы можете использовать клавиши «gD» в обычном режиме, чтобы перейти к определению символа под курсором.

Вот самый загружаемый плагин для навигации
http://www.vim.org/scripts/script.php?script_id=273

Вот один, который я написал для выбора контекста при переходе к тегу
http://www.vim.org/scripts/script.php?script_id=2507

Николай Голубев
источник
Привет @ mykola-golubyev, ссылка, указанная в Detailed descriptionразделе #2507скрипта, не работает. Можете ли вы предоставить еще один, пожалуйста?
FelikZ
12

Другой распространенный метод - поместить имя функции в первый столбец. Это позволяет найти определение с помощью простого поиска.

int
main(int argc, char *argv[])
{
    ...
}

Вышеупомянутая функция может быть найдена /^mainвнутри файла или с помощью:grep -r '^main' *.c в каталоге. Пока код имеет правильный отступ, единственный раз, когда идентификатор будет появляться в начале строки, находится в определении функции.

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

Судья майгарден
источник
13
Я всегда удивлялся, почему некоторые программисты так пишут свои подписи!
Тарраш
Кроме того, когда вы пишете свои сигнатуры функций, включая «{» в первом столбце, вы можете быстро перейти к каждой функции, нажав]], чтобы перейти вперед в файле и [[вернуться назад.
BentChainRing
12

TL; DR:

Современный способ заключается в использовании COC для завершения, подобного intellisense, и одного или нескольких языковых серверов (LS) для перехода к определению (и еще более значительных способов). Для еще большей функциональности (но не необходимой для перехода к определению) вы можете установить один или несколько отладчиков и получить полноценную среду IDE. Быстрый старт:

  1. установите vim-plug для управления вашими плагинами VIM
  2. добавить COC и (опционально) Vimspector вверху ~/.vimrc:
    call plug#begin()
    Plug 'neoclide/coc.nvim', {'branch': 'release'}
    Plug 'puremourning/vimspector'
    call plug#end()
    
  3. позвоните, :source $MYVIMRC | PlugInstallчтобы загрузить плагины VIM
  4. перезапустите vimи позвоните, :CocInstall coc-marketplaceчтобы получить легкий доступ к расширениям COC
  5. звоните :CocList marketplaceи ищите языковые серверы, например:
    • типа, pythonчтобы найти coc-jedi,
    • типа phpнайти coc-phplsи т.д.
  6. (опционально) см. install_gadget.py --helpдоступные отладчики, например:
    • ./install_gadget.py --enable-python,
    • ./install_gadget.py --force-enable-php, и т.д.

Полный ответ:

Языковой сервер (LS) - это отдельное отдельное приложение (по одному для каждого языка программирования), которое работает в фоновом режиме и анализирует весь ваш проект в режиме реального времени, предоставляя дополнительные возможности вашему редактору (любому редактору, не только vim). Вы получаете такие вещи, как:

  • завершение тега в пространстве имен
  • перейти к определению
  • перейти к следующей / предыдущей ошибке
  • найти все ссылки на объект
  • найти все реализации интерфейса
  • переименовать через весь проект
  • документация по зависанию
  • фрагменты кода, действия кода, форматирование, linting и многое другое ...

Связь с языковыми серверами осуществляется через Language Server Protocol (LSP). Оба nvimи vim8(или выше) поддерживают LSP через плагины, наиболее популярным из которых является Conquer of Completion (COC).

Список активно разрабатываемых языковых серверов и их возможностей доступен на веб-сайте Lang Server . Не все из них предоставляются расширениями COC. Если вы хотите использовать один из них, вы можете либо написать расширение COC самостоятельно, либо установить LS вручную и использовать комбинацию следующих плагинов VIM в качестве альтернативы COC:

Связь с отладчиками осуществляется по протоколу отладочного адаптера (DAP). Самый популярный плагин DAP для VIM - это Vimspector .

Протокол Language Server Protocol (LSP) был создан Microsoft для кода Visual Studio и выпущен как проект с открытым исходным кодом с разрешающей лицензией MIT (стандартизированной в сотрудничестве с Red Hat и Codenvy). Позже Microsoft выпустила Debug Adapter Protocol (DAP). Любой язык, поддерживаемый VSCode, поддерживается в VIM.

Я лично рекомендую использовать языковые серверы COC +, предоставляемые расширениями COC + ALE для дополнительной привязки (но с отключенной поддержкой LSP, чтобы избежать конфликтов с COC) + Vimspector + отладчики, предоставляемые Vimspector (называемые «гаджетами»), + следующие подключаемые модули VIM:

call plug#begin()
Plug 'neoclide/coc.nvim'
Plug 'dense-analysis/ale'
Plug 'puremourning/vimspector'
Plug 'scrooloose/nerdtree'
Plug 'scrooloose/nerdcommenter'
Plug 'sheerun/vim-polyglot'
Plug 'yggdroot/indentline'
Plug 'tpope/vim-surround'
Plug 'kana/vim-textobj-user'
  \| Plug 'glts/vim-textobj-comment'
Plug 'janko/vim-test'
Plug 'vim-scripts/vcscommand.vim'
Plug 'mhinz/vim-signify'
call plug#end()

Вы можете гуглить каждого, чтобы увидеть, что они делают.

CpRn
источник
11

1 - установить обильные ctags. Если вы используете osx, эта статья демонстрирует небольшую хитрость: http://www.runtime-era.com/2012/05/exuberant-ctags-in-osx-107.html

2- Если вы хотите включить ctags только для файлов в вашем каталоге, выполните эту команду в вашем каталоге:

ctags -R

Это создаст для вас файл тегов.

3. Если вы используете Ruby и хотите включить ctags для ваших драгоценных камней (это было очень полезно для меня с RubyMotion и разработанными мной локальными драгоценными камнями), сделайте следующее:

ctags --exclude=.git --exclude='*.log' -R * `bundle show --paths`

кредит: https://coderwall.com/p/lv1qww (обратите внимание, что я опустил опцию -e, которая генерирует теги для emacs вместо vim)

4- Добавьте следующую строку в ваш ~ / .vimrc

set autochdir 
set tags+=./tags;

(Почему точка с запятой: http://vim.wikia.com/wiki/Single_tags_file_for_a_source_tree )

5- Перейдите к слову, которому вы хотите следовать, и нажмите ctrl + ]; если вы хотите вернуться, используйте ctrl+o(источник: https://stackoverflow.com/a/53929/226255 )

Абдо
источник
Ссылка на упомянутую статью Mac не работает. Вот обновленная ссылка: runtime-era.blogspot.com/2012/05/… Лучше всего устанавливать ctags с помощью такого инструмента, как Homebrew
ZaydH
6

На второй ответ Павла: да, ctags (особенно exuberant-ctags ( http://ctags.sourceforge.net/ )) великолепен. Я также добавил это в свой vimrc, чтобы я мог использовать один файл тегов для всего проекта:

set tags=tags;/
Дэвид Волевер
источник
2

Установить cscope. Это работает очень похоже, ctagsно более мощный. Чтобы перейти к определению, вместо Ctrl+ ], сделайте Ctrl+ \+ g. Конечно, вы можете использовать оба одновременно. Но с большим проектом (скажем, ядром Linux), cscope на много миль впереди.

Диптенду Рой Чоудхури
источник
1

После генерации ctags вы также можете использовать следующее в vim:

:tag <f_name>

Выше приведут вас к определению функции.

Карун
источник