Aller à la définition de fonction dans vim

241

Comment accéder à une définition de fonction à l'aide de vim? Par exemple avec Visual Assist, je peux taper Alt+ gsous une fonction et cela ouvre un menu contextuel listant les fichiers avec des définitions.

Comment puis-je faire quelque chose comme ça dans vim?

Jon Clegg
la source
2
gnu global est meilleur que ctags.
Jichao
6
@Jichao, pouvez-vous nous donner un peu plus d'informations sur votre expérience? Dans quelles langues gnu global a-t-il mieux fonctionné pour vous? Y a-t-il autre chose dans le contexte que vous préférez en ce que je sois important? Ou peut-être l'avez-vous utilisé dans de nombreux scénarios différents et vous semblez le préférer principalement / toujours? Qu'aimez-vous mieux à ce sujet? Merci.
still_dreaming_1
@Jichao J'ai transformé votre commentaire en une réponse wiki communautaire. Je serais heureux de recevoir vos modifications et votre contribution à cette réponse.
still_dreaming_1

Réponses:

213

Utilisez des ctags. Générez un fichier de balises et indiquez à vim où il se trouve à l'aide de la commande: tags. Ensuite, vous pouvez simplement passer à la définition de la fonction en utilisant Ctrl-]

Il y a plus de trucs et astuces sur les balises dans cette question .

Paul Tomblin
la source
2
php est assez semblable à C pour que "ctags exubérants" devrait fonctionner avec. Je ne sais pas s'il a un mode python.
Paul Tomblin
5
Aucune expérience avec Cscope. Qu'est-ce que c'est?
Paul Tomblin
10
La similitude avec C n'a rien à voir avec le support de CTags PHP. Il prend en charge PHP ainsi que Python. Jetez un œil à ctags.sourceforge.net/languages.html pour voir le support complet.
données du
2
comment générer des ctags?
dwaynemac
4
ce serait formidable d'obtenir une référence à l'endroit où il est préférable d'apprendre à utiliser ces ctags.
Fzs2
138

Si tout est contenu dans un seul fichier, il y a la commande gd(comme dans 'goto definition'), qui vous amènera à la première occurrence dans le fichier du mot sous le curseur, qui est souvent la définition.

Scottie T
la source
1
que faire si je n'ai pas le mot sous le curseur (je préfère le taper)?
Fuad Saud
@FuadSaud suffit de le rechercher en utilisant/
LucasB
6
/est presque toujours imprécis, car il va correspondre à toutes les occurrences. J'ai découvert que vous pouvez réellement passer :tag <function_name>à la définition via ctags.
Fuad Saud
La fonction @Faud Jump To Definition repose sur le pointage d'un identifiant avec un curseur (dans chaque IDE). Taper / rechercher est une autre fonctionnalité, vous les confondez.
sanglant
101

g* fait un travail décent sans ctags mis en place.

C'est-à-dire, tapez g, *(ou simplement *- voir ci-dessous) pour rechercher le mot sous le curseur (dans ce cas, le nom de la fonction). Appuyez ensuite sur npour passer à l' occurrence suivante (ou Shift- npour la précédente).

Il ne saute pas directement à la définition, étant donné que cette commande recherche simplement le mot sous le curseur, mais si vous ne voulez pas vous occuper de la configuration de ctags pour le moment, vous pouvez au moins vous éviter d'avoir à re -tapez le nom de la fonction pour rechercher sa définition.

--Modifier-- Bien que j'utilise g * depuis longtemps, j'ai récemment découvert deux raccourcis pour ces raccourcis!

(a) *passera à l'occurrence suivante du mot sous le curseur. (Pas besoin de taper la gcommande «goto» dans vi).

(b) #revient à l'événement précédent, de façon similaire.

N et n fonctionnent toujours, mais '#' est souvent très utile pour démarrer la recherche initialement dans le sens inverse, par exemple, lors de la recherche de la déclaration d'une variable sous le curseur.

Brent Faust
la source
10
La différence entre *et g*est les limites des mots dans la recherche. *effectue une \<keyword\>recherche (identique \bkeyword\bà l'expression régulière), tout en g*recherchant keywordsans limites de mots.
Nicolai S
si vous avez cent occurrences d'une fonction dans un fichier, cela *vous prendra en moyenne 50 hits avant de trouver la définition.
naught101
49

Utilisez gdougD tout en plaçant le curseur sur une variable de votre programme.

  1. gd vous amènera à la déclaration locale.
  2. gD vous amènera à la déclaration globale.

plus d'options de navigation peuvent être trouvées ici .

Utilisez cscope pour le référencement croisé de grands projets tels que le noyau Linux.

0x90
la source
14

Comme Paul Tomblin l'a mentionné, vous devez utiliser des ctags . Vous pouvez également envisager d'utiliser des plugins pour sélectionner celui qui convient ou pour prévisualiser la définition de la fonction sous le curseur. Sans plugins, vous aurez mal à la tête en essayant de sélectionner l'une des centaines de méthodes 'doAction' surchargées car la prise en charge ctags intégrée ne prend pas en compte le contexte - juste un nom.

Vous pouvez également utiliser cscope et sa fonction 'find global symbol'. Mais votre vim doit être compilé avec le support + cscope qui n'est pas une option de construction par défaut.

Si vous savez que la fonction est définie dans le fichier actuel, vous pouvez utiliser les touches 'gD' en mode normal pour passer à la définition du symbole sous le curseur.

Voici le plugin de navigation le plus téléchargé
http://www.vim.org/scripts/script.php?script_id=273

En voici un que j'ai écrit pour sélectionner le contexte tout en sautant sur le tag
http://www.vim.org/scripts/script.php?script_id=2507

Mykola Golubyev
la source
Salut @ mykola-golubyev, le lien que vous avez fourni dans la Detailed descriptionsection du #2507script est rompu. Pouvez-vous en fournir un autre s'il vous plaît?
FelikZ
12

Une autre technique courante consiste à placer le nom de la fonction dans la première colonne. Cela permet de trouver la définition avec une simple recherche.

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

La fonction ci-dessus pourrait alors être trouvée avec /^mainà l'intérieur du fichier ou avec :grep -r '^main' *.cdans un répertoire. Tant que le code est correctement mis en retrait, la seule fois où l'identificateur se produira au début d'une ligne est à la définition de la fonction.

Bien sûr, si vous n'utilisez pas de ctags à partir de ce moment, vous devriez avoir honte de vous-même! Cependant, je trouve que cette norme de codage est également un ajout utile.

Le juge Maygarden
la source
13
Je me suis toujours demandé pourquoi certains codeurs écrivent leurs signatures de cette façon!
Tarrasch
De plus, lorsque vous écrivez vos signatures de fonction, y compris «{» dans la première colonne, vous pouvez vous déplacer rapidement vers chaque fonction en appuyant sur]] pour avancer dans le fichier et [[pour revenir en arrière.
BentChainRing
12

TL; DR:

La manière moderne consiste à utiliser COC pour une complétion de type intellisense et un ou plusieurs serveurs de langues (LS) pour passer à la définition (et bien plus encore). Pour encore plus de fonctionnalités (mais ce n'est pas nécessaire pour passer à la définition), vous pouvez installer un ou plusieurs débogueurs et obtenir une expérience IDE complète. Démarrage rapide:

  1. installez vim-plug pour gérer vos plug-ins VIM
  2. ajoutez COC et (éventuellement) Vimspector en haut de ~/.vimrc:
    call plug#begin()
    Plug 'neoclide/coc.nvim', {'branch': 'release'}
    Plug 'puremourning/vimspector'
    call plug#end()
    
  3. appeler :source $MYVIMRC | PlugInstallpour télécharger les plug-ins VIM
  4. redémarrez vimet appelez :CocInstall coc-marketplacepour accéder facilement aux extensions COC
  5. appeler :CocList marketplaceet rechercher des serveurs linguistiques, par exemple:
    • tapez pythonpour trouver coc-jedi,
    • tapez phppour trouver coc-phpls, etc.
  6. (facultatif) voir install_gadget.py --helppour les débogueurs disponibles, par exemple:
    • ./install_gadget.py --enable-python,
    • ./install_gadget.py --force-enable-php, etc.

Réponse complète:

Le serveur de langues (LS) est une application autonome distincte (une pour chaque langage de programmation) qui s'exécute en arrière-plan et analyse l'ensemble de votre projet en temps réel, exposant des fonctionnalités supplémentaires à votre éditeur (n'importe quel éditeur, pas seulement vim). Vous obtenez des choses comme:

  • achèvement de la balise sensible à l'espace de noms
  • sauter à la définition
  • passer à l'erreur suivante / précédente
  • trouver toutes les références à un objet
  • trouver toutes les implémentations d'interface
  • renommer l'ensemble d'un projet
  • documentation sur le vol stationnaire
  • extraits, actions de code, mise en forme, peluches et plus encore ...

La communication avec les serveurs de langues s'effectue via le Language Server Protocol (LSP). Les deux nvimet vim8(ou plus) prennent en charge LSP via des plug-ins, le plus populaire étant Conquer of Completion (COC).

La liste des serveurs de langues développés activement et de leurs capacités est disponible sur le site Web de Lang Server . Tous ceux-ci ne sont pas fournis par les extensions COC. Si vous souhaitez utiliser l'un de ceux-ci, vous pouvez soit écrire une extension COC vous-même, soit installer LS manuellement et utiliser la combinaison des plug-ins VIM suivants comme alternative au COC:

La communication avec les débogueurs s'effectue via le protocole DAP ( Debug Adapter Protocol ). Le plug-in DAP le plus populaire pour VIM est Vimspector .

Le Language Server Protocol (LSP) a été créé par Microsoft pour Visual Studio Code et publié en tant que projet open source avec une licence MIT permissive (normalisée par la collaboration avec Red Hat et Codenvy). Plus tard, Microsoft a également publié le protocole DAP ( Debug Adapter Protocol ). Toute langue prise en charge par VSCode est prise en charge dans VIM.

Je recommande personnellement d'utiliser COC + les serveurs de langues fournis par les extensions COC + ALE pour les peluches supplémentaires (mais avec le support LSP désactivé pour éviter les conflits avec COC) + Vimspector + débogueurs fournis par Vimspector (appelés "gadgets") + les plug-ins VIM suivants:

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()

Vous pouvez google chacun pour voir ce qu'ils font.

cprn
la source
11

1- installez des ctags exubérants. Si vous utilisez osx, cet article montre une petite astuce: http://www.runtime-era.com/2012/05/exuberant-ctags-in-osx-107.html

2- Si vous souhaitez uniquement inclure les ctags des fichiers dans votre répertoire uniquement, exécutez cette commande dans votre répertoire:

ctags -R

Cela va créer un fichier "tags" pour vous.

3- Si vous utilisez Ruby et souhaitez inclure les ctags de vos gemmes (cela m'a été très utile avec RubyMotion et les gemmes locales que j'ai développées), procédez comme suit:

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

crédit: https://coderwall.com/p/lv1qww (Notez que j'ai omis l'option -e qui génère des balises pour emacs au lieu de vim)

4- Ajoutez la ligne suivante à votre ~ / .vimrc

set autochdir 
set tags+=./tags;

(Pourquoi le point-virgule: http://vim.wikia.com/wiki/Single_tags_file_for_a_source_tree )

5- Accédez au mot que vous souhaitez suivre et appuyez sur ctrl + ]; si vous souhaitez revenir en arrière, utilisez ctrl+o(source: https://stackoverflow.com/a/53929/226255 )

Abdo
la source
Le lien vers l'article Mac mentionné est rompu. Voici le lien mis à jour: runtime-era.blogspot.com/2012/05/… Le mieux est d'installer des ctags avec un outil comme Homebrew
ZaydH
6

Pour seconder la réponse de Paul: oui, ctags (en particulier exuberant-ctags ( http://ctags.sourceforge.net/ )) est génial. J'ai également ajouté ceci à mon vimrc, donc je peux utiliser un fichier de balises pour un projet entier:

set tags=tags;/
David Wolever
la source
2

Installez cscope. Cela fonctionne très bien ctagsmais plus puissant. Pour aller à la définition, au lieu de Ctrl+ ], faites Ctrl+ \+ g. Bien sûr, vous pouvez utiliser les deux simultanément. Mais avec un gros projet (disons noyau Linux), cscope a des kilomètres d'avance.

Diptendu Roy Chowdhury
la source
1

Après avoir généré des ctags, vous pouvez également utiliser les éléments suivants dans vim:

:tag <f_name>

Ci-dessus vous amènera à la définition de la fonction.

Karun
la source