*usr_29.txt* Pour Vim version 6.2c.
MANUEL UTILISATEUR DE VIM- de Bram Moolenaar
Se déplacer dans les programmes
Le créateur de Vim est un programmeur. Il n'y a rien de surprenant à ce que Vim
offre de nombreuses commodités pour faciliter l'écriture de programmes, comme :
Se déplacer pour trouver où les identificateurs sont définis et utilisés.
Visualiser les déclarations dans une fenêtre séparée.
On en dit plus dans le présent chapitre.
|29.1| Utiliser des marqueurs
|29.2| La fenêtre de prévisualisation.
|29.3| Se déplacer dans un programme
|29.4| Trouver les identifiants globaux
|29.5| Trouver les identifiants locaux
Chapitre suivant : |usr_30.txt| Edition de programmes
Chapitre précédent: |usr_28.txt| Pliage
Table des matières : |usr_toc.txt|
==============================================================================
*29.1* Utiliser des marqueurs (ou "tags")
Qu'est-ce qu'un marqueur? C'est un endroit où un identificateur est défini. Un
exemple en est la définition d'une fonction dans un programme C ou C++.
Une liste de marqueurs est maintenue dans un fichier de marqueurs. Ils peuvent
être utilisés par Vim pour sauter directement de n'importe où jusqu'au
marqueur, à savoir l'endroit où l'identificateur est défini.
Pour générer le fichier de marqueurs pour tous les fichiers de langage C,
utiliser la commande suivante :
ctags *.c
"ctags" est un programme séparé. Il est installé par défaut avec la plupart des
systèmes UNIX. Si vous ne l'avez pas déjà, vous pouvez trouver "Exuberant ctags",
qui est une version étendue à 33 langages de programmation du ctags traditionnel
ici:
http://ctags.sf.net
Maintenant, supposant que vous êtes dans Vim et vous que voulez aller à la
définition d'une certaine fonction "startlist", vous pouvez y sauter en utilisant
la commande suivante :
:tag startlist
Cette commande trouvra la fonction "startlist" même si elle est dans un autre
fichier. La commande CTRL-] saute au marqueur du mot sous lequel se trouve
votre curseur. Ceci rend très facile l'exploration d'un enchevêtrement de code
C. Supposons, par exemple, que vous êtes dans la fonction "write_block". Vous
pouvez voir qu'elle appelle "write_line".
Mais que fait "write_line" ?
En plaçant le curseur sous l'appel à "write_line", et en pressant sur CTRL-],
vous sautez à la définition de cette fonction. La fonction "write_line" fait
appel à la fonction "write_char". Vous devez vous figurer ce que fait cette
dernière. Alors, positionnez votre curseur sous l'appel à "write_char" et
pressez CTRL-]. Maintenant, vous êtes à la défintion la fonction "write_char".
+-------------------------------------+
|void write_block(char **s; int cnt) |
|{ |
| int i; |
| for (i = 0; i < cnt; ++i) |
| write_line(s[i); |
|} | |
+-----------|-------------------------+
|
CTRL-] |
| +----------------------------+
+--> |void write_line(char *s) |
|{ |
| while (*s != 0) |
| write_char(*s++); |
|} | |
+--------|-------------------+
|
CTRL-] |
| +------------------------------------+
+--> |void write_char(char c) |
|{ |
| putchar((int)(unsigned char)c); |
|} |
+------------------------------------+
La commande ":tags" montre la liste des marqueurs que vous avez parcourus:
:tags
# TO tag FROM line in file/text
1 1 write_line 8 write_block.c
2 1 write_char 7 write_line.c
>
Maintenant, pour revenir, la commande CTRL-T va au marqueur précédent. Dans
l'exemple ci-dessus, vous retournez dans la fonction "write_line" juste à
l'appel à "write_char".
Cette commande prend un argument de comptage qui indique de combien de marqueurs
vous voulez reculer. Vous avez avancé, et maintenant reculé. Avançons à nouveau.
La commande suivante saute au marqueur qui est au sommet de la liste :
:tag
Vous pouvez la préfixer d'un compteur et sauter en avant de ce nombre de marqueurs.
Par exemple :
:3tag
CTRL-T aussi peut être précédée d'un compteur.
Ces commandes vous permettent ainsi de descendre un arbre d'appels avec CTRL-]
et le remonter par CTRL-T. Utilisez ":tags" pour savoir où vous en êtes.
PARTAGE DE FENETRES
La commande ":tag" remplace le fichier dans la fenêtre courante par celui
contenant la fonction recherchée. Mais, supposons que vous vouliez voir non
seulement celle-ci mais aussi la précédente ?
Vous pouvez partager la fenêtre en utilisant la commande ":split" suivie de
la commande ":tag". Vim dispose d'une commande raccourcie qui enchaîne les deux:
Pour partager la fenêtre courante et sauter au marqueur sous le curseur,
utilisez cette commande:Si un compte est spécifié, la nouvelle fenêtre aura ce nombre de lignes.
PLUS SUR LES FICHIERS DE MARQUEURS
Quand vous avez des fichiers dans de nombreux répertoires, vous pouvez créer
un fichier de marqueurs dans chacun d'entre eux. Vim ne sera alors capable de
sauter à des marqueurs ailleurs que dans des fichiers du répertoire courant.
Pour trouver les marqueurs dans plus de fichiers, utiliser l'option 'tags'
pour inclure tous les fichiers souhaités.
Exemple:Ceci recherche un fichier de marqueurs dans le même répertoire que le fichier
courant, dans un niveau au-dessus de répertoire et dans tous les sous-répertoires.
Ceci peut conduire à un grand nombre de fichiers mais peut ne pas suffire.
Par exemple, en éditant un fichier dans "~/proj/src", on ne trouve pas le
fichier "~/proj/sub/tags". Pour faire face à une telle situation, Vim propose
la recherche à travers un arbre complet de sous-répertoires.
Exemple:UN FICHIER DE MARQUEURS
Quand Vim doit chercher des fichiers de marqueurs en de nombreux endroits,
vous pouvez entendre le disque s'agiter. Ce peut être un peu lent.
Dans ce cas, il peut être intéressant de consacrer un peu plus de temps à générer
un plus grand fichier de marqueurs. Vous pouvez faire cela de nuit.
Ceci requiert le programme "Exuberant ctags" mentionné ci-dessus. Il accepte
un paramètre lui demandant une scrutation récursive d'un arbre complet de
répertoires :Un autre aspect sympathique du ctags Exuberant est qu'il reconnaît un nombre
important de types de langages. Ainsi ne fonctionne-t-il pas seulement pour
des programmes écrits en C ou en C++, mais également pour Eiffel et même les
scripts Vim. Voir la documentation de ctags pour régler celà.
Maintenant, il ne vous reste plus qu'à indiquer à Vim où se trouve votre
gros fichier de marqueurs.
:set tags=~/proj/tags
CORRESPONDANCES MULTIPLES
Quand une fonction est définie de nombreuses fois (ou une même méthode dans
plusieurs classes), la commande ":tag" sautera à la première. Si la
correspondance a lieu dans le fichier courant, ce sera celle-ci.
Vous pouvez maintenant sauter aux autres occurences par:Vous pouvez répéter cette commande pour les occurences suivantes. S'il y en a
beaucoup, vous pouvez choisir vers laquelle sauter:Vim vous présentera alors une liste de choix:
# pri kind tag file
1 F f mch_init os_amiga.c
mch_init()
2 F f mch_init os_mac.c
mch_init()
3 F f mch_init os_msdos.c
mch_init(void)
4 F f mch_init os_riscos.c
mch_init()
Enter nr of choice (<CR> to abort):
Vous pouvez saisir le numéro (trouvé dans la première colonne) auquel vous
souhaitez sauter. Les informations des autres colonnes vous permettent de
vous faire une bonne idée d'où se passe la correspondance.
Pour vous déplacer parmi les marqueurs trouvés, les commandes suivantes
peuvent être utilisées:
:tfirst aller à la première correspondance
:[compte]tprevious aller à la [compte]-ième correspondance précédente
:[compte]tnext aller à la [compte]-ième correspondance suivante
:tlast aller à la dernière correspondance
Si [compte] est omis, il est remplacé par 1.
DEVINER LES NOMS DE MARQUEURS
La complémentation de ligne de commande est un bon moyen d'éviter de saisir
un nom de marqueur long. Tapez-en seulement un petit morceau et pressez <Tab>:Vous obtiendrez la première correspondance. Si ce n'est pas celle que vous
voulez, pressez <Tab> jusqu'à ce que vous trouviez la bonne.
Quelquefois vous connaissez seulement une partie du nom d'une fonction.
Ou vous avez de nombreux marqueurs qui commencent de la même façon, mais
finissent différemment. Vous pouvez demander à Vim d'utiliser un modèle pour
trouver le marqueur. Supposez que vous vouliez sauter à un marqueur qui
contient la chaîne "block". Tapez d'abord ceci :Maintenant, utilisez la complémentation de ligne de commande: pressez <Tab>.
Vim trouvera tous les marqueurs qui contiennent "block" et sautera au premier.
Le "/" avant un marqueur signale à Vim que ce qui suit n'est pas un
marqueur cherché littéralement mais un modèle. Vous pouvez utiliser ici toutes
les options de recherche de modèles. Par exemple, supposons que vous
vouliez trouver un marqueur qui commence par "write_":Le "^" spécifie que le marqueur commence par "write_". Autrement, le marqueur
"overwrite" aurait pu convenir. De façon similaire, "$" à la fin du modèle
assure une correspondance en fin de marqueur.
UN BUTINEUR DE MARQUEURS
Puisque CTRL-] vous envoie à la définition de l'identificateur trouvé sous le
curseur, vous pouvez utiliser une liste d'identificateurs comme une table des
matières.Voici un exemple
D'abord, créer un fichier de liste d'identificateurs (ceci requiert d'utiliser
Exuberant ctags):Maintenant, démarrez Vim sans nom de fichier et ouvrez le fichier de liste
dans une fenêtre de partage vertical de Vim:La fenêtre contient une liste de toutes les fonctions. Il y a aussi d'autres
informations que vous pouvez ignorer. Faites ":set ts=99" pour nettoyer un peu
l'écran. Dans cette fenêtre, créez une redéfinition:Déplacez le curseur à la ligne qui contient la fonction à laquelle vous voulez
vous déplacer. Pressez <Enter>. Vim sautera dans l'autre fenêtre à la
fonction souhaitée.
SUJETS CONNEXES
Vous pouvez positionner 'ignorecase' pour ignorer la casse dans les recherches.
L'option 'tagbsearch' indique si le fichier de marqueurs est trié ou non.
Par défaut, un fichier est supposéz trié , ce qui rend les recherches beaucoup
plus rapides, mais ne marche pas si le fichier n'est pas effectivement trié.
L'option 'taglength' peut être positionnée pour préciser le nomnbre de
caractères significatifs dans un marqueur.
Si vous utilisez le programme SNiFF+, vous pouvez utiliser l'interface Vim
|sniff|. SNiFF+ est un programme commercial.
Cscope est un programme libre. Il ne trouve pas seulement où un symbole est
défini, mais aussi où il est utilisé. Voir |cscope|.
==============================================================================
*29.2* La fenêtre de prévisualisation
Quand vous éditez du code qui contient un appel de fonction, vous avez besoin
d'utiliser les bons arguments. Pour connaître les valeurs à passer vous pouvez
regarder comment la fonction est définie. Le mécanisme des marqueurs marche
très bien pour ça. Il est préférable d'afficher le code de la fonction dans une
autre fenêtre. Pour celà, on peut utiliser la fenêtre de prévisualisation.
Pour ouvrir une fenêtre de prévisualisation, pour afficher la fonction
"write_char":Vim ouvrira une fenêtre et ira au marqueur "write_char". Puis il vous ramène à
la position originale. Ainsi, vous pourrez continuer de taper sans avoir
besoin de la commande CTRL-W.
Si le nom d'une fonction apparaît dans le texte, vous pouvez obtenir sa
définition dans la fenêtre de prévisualisation avec :Il existe un script qui affiche automatiquement le texte où le mot sous lequel
le curseur se trouve a été défini. Voir |CursorHold-example|
Pour fermer la fenêtre de prévisualisation utiliser cette commande :Pour éditer un fichier donné (par ex. defs.h) dans la fenêtre de prévisualisation,
utiliser :Finalement, ":psearch" peut être utilisé pour trouver un mot dans le fichier
courant et tout fichier inclus et afficher la correspondance dans la fenêtre de
prévisualisation. Ceci est particulièrement utile qaund on utilise des fonctions
de bibliothèque, pour lesquelles on n'a pas de fichier de marqueurs. Exemple:Ceci affichera le fichier 'stdio.h' dans dans la fenêtre de prévisualisation, avec
le prototype de fonction pour popen():Vous pouvez spécifier la hauteur en lignes de la fenêtre de prévisualisation
par l'option 'previewheight' .
==============================================================================
*29.3* Déplacements dans un programme
Puisqu'un programme est structuré, Vim peut y reconnaître des éléments. Des
commands adaptées peuvent être utilisées pour s'y déplacer. Les programmes
en langage C contiennent souvent des constructions comme celle-ci :
#ifdef USE_POPEN
fd = popen("ls", "r")
#else
fd = fopen("tmp", "w")
#endif
Mais souvent beaucoup plus longues et éventuellement imbriquées. Positionnez
le curseur sous "#ifdef" et pressez %. Vim sautera au "#else". Presser % à
nouveau vous envoie au "#endif". Un autre % vous renvoie au "#ifdef".
Quand la construction est imbriquée, Vim trouvera les éléments correspondants.
C'est une bon moyen de vérifier si vous n'avez pas oublié un "#endif".
Quand vous êtes quelque part à l'intérieur d'une paire "#if" - "#endif",
vous pouvez sauter à son début par un:Si vous n'êtes pas après un "#if" ou un "#ifdef", Vim émettra un bip.
Pour sauter en avant au prochain "#else" ou "#endif" utiliser:Ces deux commandes sautent tout bloc "#if" - "#endif" Qu'elles peuvent
rencontrer.
Exemple:
#if defined(HAS_INC_H)
a = a + inc();
# ifdef USE_THEME
a += 3;
# endif
set_width(a);
Avec le curseur à la dernière ligne, "[#" vous positionne à la première ligne.
Le bloc "#ifdef" - "#endif" du milieu est sautéC.D in the middle is skipped.
SE DEPLACER DANS LES BLOCS DE CODE
En langage C, les blocs de code sont entourés de paires d'accolades {}.
Ils peuvent être joliment longs. Pour se déplacer au début du bloc de code
le plus extérieur au niveau courant, utilisez la commande "[[". Utilisez "]]"
pour trouver le début du bloc le plus extérieur suivant.
Ceci suppose que les "{" et "}" sont en première colonne. La commande "[{"
vous déplace au début du bloc courant, elle saute les paires {} de même niveau.
La commande "]}" saute à la fin
En résumé:
function(int a)
+-> {
| if (a)
| +-> {
[[ | | for (;;) --+
| | +-> { |
| [{ | | foo(32); | --+
| | [{ | if (bar(a)) --+ | ]} |
+-- | +-- break; | ]} | |
| } <-+ | | ]]
+-- foobar(a) | |
} <-+ |
} |
|
function f2 (int a) |
{ <-+
Quand vous écrivez du C++ ou du java, le bloc {} externe est pour la classe.
Le niveau suivant est pour une méthode. Quand vous êtes quelquepart à
l'intérieur d'une classe utilisez "[m" pour trouver le prochain début d'une
méthode, et "]m" pour trouver la prochaine fin d'une méthode.
De plus, "[]" déplace en arrière à la fin d'une fonction et "][" déplace
en avant à la fin d'une fonction. La fin d'une fonction est définie par
une "}" en première colonne.
int func1(void)
{
return 1;
+----------> }
|
[] | int func2(void)
| +-> {
| [[ | if (flag)
start +-- +-- return flag;
| ][ | return 2;
| +-> }
]] |
| int func3(void)
+----------> {
return 3;
}
N'oubliez pas que vous pouvez aussi utiliser "%" pour vous déplacer
alternativement entre les caractères appairés (), {} and [].
Ceci marche aussi d'il y a de nombreuses lignes entre.
SE DEPLACER DANS LES PARENTHESES
Les commandes "[(" et "])" marchent de façon similaire à "[{" et "]}", sauf
qu'elles agissent sur des paires de parenthèses au lieu de paires d'accolades.
<--------------------------------
<-------
if (a == b && (c == d || (e > f)) && x > y)
-------------->
-------------------------------->SE DEPLACER DANS LES COMMENTAIRES
Pour retourner au début d'un commentaire utilisez "[/". Pour aller en avant
jusqu'à la fin d'un commentaire, utilisez "]/". Ceci ne fonctionne que pour
les commentaires délimités par /* .... */ .
+-> +-> /*
| [/ | * Un commentaire --+
[/ | +-- * sur la belle vie. | ]/
| */ <-+
|
+-- foo = bar * 3; --+
| ]/
/* un petit commentaire */ <-+
==============================================================================
*29.4* Recherche d'identificateurs globaux
Suppposons que vous êtes en train d'éditer un fichier C et vous demandez si
une variable est définie comme "int" ou comme "unsigned". Une façon rapide d'y
répondre est avec la commande "[I". Supposons que le curseur est sous le mot
"column". TapezVim listera toutes les lignes où il peut trouver ce mot. Pas seulement dans le
fichier courant, mais aussi dans tous les fichiers inclus (récursivement),
Le résultat ressemble à :
structs.h
1: 29 unsigned column; /* column number */
L'avantage sur l'utilisation de marqueurs ou la fenêtre de prévisualisation
est que la recherche s'étend aux fichiers inclus. Dans la plupart des cas, le
résultat est que l'on retrouve la bonne déclaration, même si le fichier de
marqueurs est dépassé ou que vous n'avez pas de marqueurs pour les fichiers
inclus.
Néanmoins, un certain nombre de prérequis doivent être satisfaits pour que
"[I" fonctionne : Tout d'abord, l'option 'include' doit spécifier comment un
fichier est inclus. La valeur par défaut marche bien pour C et C++. Pour
d'autres langages, vous devez la changer.
LOCALISATION DES FICHIERS INCLUS
Vim trouvera les fichiers inclus aux endroits spécifiés avec l'option
'path'. Si un répertoire manque, certains fichiers inclus ne seront pas
trouvés. Vous pouvez vous en rendre compte avec cette commande :Ceci listera les fichiers inclus qui n'ont pu être trouvés. Ainsi que les
fichiers inclus par les fichiers inclus.
Un exemple de sortie :
--- Included files not found in path ---
<io.h>
vim.h -->
<functions.h>
<clib/exec_protos.h>
Le fichier "io.h" est inclus par le fichier courant et n'a pu être trouvé.
"vim.h" a été trouvé, ainsi ":checkpath" ouvre ce fichier et cherche ce que
celui-ci doit inclure. Les fichiers "functions.h" et "clib/exec_protos.h",
demandés par "vim.h" ne sont pas trouvés.
Note:
Vim n'est pas un compilateur. Il ne reconnaît pas les instructions "#ifdef".
Ceci signifie que toute instruction "#include" sera essayée, même si elle
vient dans un bloc "#if JAMAIS".
Pour corriger les fichiers introuvables, ajoutez un répertoire à l'option
'path'. Un bon endroit pour s'occuper de ça serait le Makefile. Surveillez
les lignes contenant un article "-I", comme "-I/usr/local/X11". Pour ajouter
ce répertoire, utilisez :S'il y a un grand nombre de répertoires, vous pouvez utiliser un joker '*'.
Exemple:Ceci trouverait autant "/usr/local/include" que "/usr/X11/include".
Quand on travaille sur un projet avec toute une arborescence de fichiers
inclus, l'article '**' est utile. Il cherchera récursivement dans tous les
sous-répertoires.
Exemple:Ceci cherchera les fichiers dans :
/projects/invent/include
/projects/invent/main/include
/projects/invent/main/os/include
etc...
Il y a encore plus de possibilités. Consultez l'option 'path' pour info.
Si vous voulez voir quels sont les fichiers réellement trouvés, utilisez
cette command:
:checkpath!
Vous obtiendrez une (très longue) liste de fichiers inclus, les fichiers qu'ils
incluent, etc... Pour raccourcir un peu la liste, Vim affiche "(Already listed)"
pour les fichiers trouvés précédemment.
SAUTER A UNE CORRESPONDANCE
"[I" produit une liste avec une seule ligne de texte. Quand vous voulez avoir
une vue plus précise du premier article, vous pouvez y sauter avec la commande :Vous pouvez aussi utiliser"[ CTRL-I", puisque CTRL-I revient au même que de
presser <Tab>.
La liste que "[I" produit a un numéro au début de chaque ligne. Quand vous
voulez sauter à un autre article que le premier, tapez son numéro d'abord:sautera au troisième article de la liste. Rappelez-vous que vous pouvez
utiliser CTRL-O pour retourner d'où vous venez.
COMMANDES CONNEXES COMMANDS
[i ne liste que la première correspondance
]I ne liste que les articles sous le curseur
]i ne liste que le premier article sous le curseur
TROUVER DES IDENTIFICATEURS DONNES
La commande "[I" trouve n'importe quel identificateur. Pour ne trouver que
des macros, définies par "#define", utilisez:A nouveau, la recherche est conduite à travers les fichiers inclus.
L'option 'define' spécifie à quoi doit ressembler une ligne qui définit des
articles pour la recherche par "[D". Vous pourriez le changer pour travailler
avec d'autres langages que le C et le C++.
Les commandes reliées à "[D" sont:
[d ne liste que la première correspondance
]D ne liste que les articles sous le curseur
]d ne liste que le premier article sous le curseur
==============================================================================
*29.5* Trouver des identificateurs locaux
La command "[I" cherche dans les fichiers inclus. Pour chercher dans le seul
fichier courant, et sauter au premier emplacement où le mot sous le surseur
est utilisé :Mnémotechnique: "Goto Definition". Cette commande est très utile pour trouver
une variable ou une fonction déclarée localement ("static" en termes de langage
C) Exemple (curseur sous "counter"):
+-> static int counter = 0;
|
| int get_counter(void)
gD | {
| ++counter;
+-- return counter;
}
Pour restreindre encore davantage la recherche, et ne regarder que dans la
fonction courante, utilisez cette commande:Ceci reculera au début de la fonction courante et trouvera la première
occurence du mot sous lequel se trouve le curseur. En fait, Vim cherche en
arrière une ligne vide au-dessus d'une "{" en première colonne. A partir de
là, il cherche l'identificateur vers l'avant.
Exemple (curseur sous "idx"):
int find_entry(char *name)
{
+-> int idx;
|
gd | for (idx = 0; idx < table_len; ++idx)
| if (strcmp(table[idx].name, name) == 0)
+-- return idx;
}
==============================================================================
Chapitre suivant : |usr_30.txt| Editer des programmes
Copyright: voir |manual-copyright| vim:tw=78:ts=8:ft=help:norl: