Utiliser les replis (folding) de Vim

La rédaction de documents sur ordinateur fait gagner beaucoup de temps, mais parfois, rien ne remplace la bonne vieille feuille de papier. Il est en effet plus facile de comparer des portions de texte lorsqu’il est présent sur papier plutôt que sur un écran. Sitôt qu’un document devient plus grand que l’écran, il est difficile de comparer et travailler sur des endroits différents du fichier. Les fonctions de partage d’écran (:split) vertical ou horizontal peuvent pallier à ce problème mais nous allons nous intéresser ici aux replis (folding) de Vim. Un repli permet de cacher une portion du fichier en cours d’édition.

Toutes les commandes de repliage commencent par z. D’après la documentation, ce z fait penser à une feuille de papier repliée si on la regarde de profil. Oui, bon…

Création des replis

Commençons d’abord avec certaines actions simples de pliage. Ouvrez un fichier, assez long de préférence. Placez le curseur où bon vous semble. En mode normal, tapez zf10j, Vim crée alors un repli de 11 lignes : la ligne où se trouvait le curseur et les 10 lignes relatives au mouvement 10j. Il est possible d’utiliser toute sorte de mouvement en combinaison avec zf.

Les replis fonctionnent également en mode visuel. Tapez la touche V, sélectionnez quelques lignes via le mouvement 5k par exemple puis zf, Vim crée alors un repli contenant les lignes sélectionnées.

Il est également possible de créer un repli en indiquant un intervalle de lignes. Si vous souhaitez créer un repli occupant les lignes 50 à 70, tapez :50,70 fold et appuyez sur entrée. Notez que l’espace entre 70 et fold est facultatif et que vous pouvez ne saisir que fo au lieu de fold, fo est la forme courte de fold. Il est aussi possible d’utiliser le . pour désigner la ligne courante. Ainsi, si le curseur se trouve à la ligne 150 et que l’on désire créer un repli démarrant du curseur à la ligne 180, il suffit de saisir la commande :.,180 fo. Si vous inversez l’intervalle, Vim vous demandera si vous souhaitez intervertir les valeurs.

Enfin, vous pouvez créer un repli à partir de la position du curseur jusqu’à un résultat de recherche. Si vous exécutez zf/ma chaine ,Vim créera un repli allant de la ligne courante à la première occurrence de la chaine ma chaine.

Vim sait sélectionner le texte intelligemment. Vous êtes en train d’éditer un programme et vous avez un bloc de texte entre accolades { et }. Positionnez le curseur entre ces accolades, et tapez zfa}. Vim crée alors un repli allant de l’accolade située juste avant le curseur jusqu’à l’accolade située juste après le curseur. Ceci fonctionne aussi avec les autres délimiteurs de bloc : les parenthèses zfa), les crochets zfa], et les crochets angulaires zfa>. Vim sait reconnaître aussi les blocs imbriqués. Par exemple, en tapant zf2a}, Vim créera un repli sur le bloc englobant le bloc courant, autrement dit, le bloc de niveau supérieur.

Vous l’avez sans doute deviné avec la phrase précédente, les replis peuvent être imbriqués : un repli peut contenir d’autres replis, et ainsi de suite.

Une fois le repli créé, apparaît en surbrillance le nombre de lignes pliées ainsi qu’un petit échantillon du texte contenu. Les tirets indiquent le niveau hiérarchique du repli. Pour un repli principal (du plus haut niveau), il y a deux tirets. Les replis imbriqués sont représentés par plus de tirets : le niveau 2 est représenté par 3 tirets, le niveau 3 par 4 tirets, etc.

Représentation d’un repli fermé.

Représentation d’un repli fermé.

Utiliser les replis

Créer des replis, c’est bien, mais que peut-on en faire ? Il peut être intéressant de pouvoir ouvrir un repli pour voir ou modifier son contenu, non ? Pour ce faire, placez le curseur sur le repli concerné et tapez zo. Pour refermer le repli, tapez zc. Note : o pour open et c pour close.

Pour se déplacer rapidement entre les replis, utilisez les commandes zj et zk pour aller respectivement aux replis suivant et précédent, peu importe qu’ils soient ouverts ou fermés. Ces commandes devraient être faciles à retenir, puisqu’elles combinent la commande de repli z avec les commandes de déplacement j (une ligne vers le bas) et k (une ligne vers le haut). Si vous voulez vous déplacer au début ou à la fin d’un repli, utilisez respectivement [z et ]z. Il est bien sûr possible de répéter ces commandes en les préfixant d’un compteur.

Si le repli que vous venez d’ouvrir avec zo contient d’autres replis, ces derniers resteront fermés. Pour les ouvrir tous (le repli sous le curseur et ses sous-replis), tapez zO. Exécuter zc permet de fermer le repli qui est sous le curseur. zC permet de fermer tous les replis qui sont sous le curseur, faites quelques essais avec cette dernière pour bien comprendre son fonctionnement car dans certains cas, un seul repli est fermé.

La commande zr permet d’ouvrir un niveau de repli à la fois, tapez deux fois zr et deux niveaux de replis seront ouverts. Pour ouvrir récursivement tous les replis, tapez zR. La commande zm permet de fermer un niveau de repli à la fois, tapez deux fois zm et deux niveaux de replis seront fermés. Pour fermer récursivement tous les replis, tapez zM.

Pour supprimer un repli, placez le curseur sur le repli concerné puis tapez zd, pour supprimer un repli et tous ses sous-replis, tapez zD. Pour supprimer tous les replis du fichier, tapez zE. Ceci fonctionne que le repli soit ouvert ou non, cependant, supprimez les replis avec précaution car il n’est pas possible d’annuler la suppression d’un repli.

Vous vous demandez peut-être comment Vim traite le texte entre les replis quand vous effectuez une recherche ? Normalement. Si vous recherchez une chaine qui est dans un repli, Vim l’ouvrira et positionnera le curseur sur l’occurrence trouvée. Malheureusement, les replis ouverts lors d’une recherche ne sont pas refermés automatiquement. Cependant, un zM suffira à refermer tous les replis.

Vim traite aussi les replis fermés comme de simples lignes. Ainsi, si vous placez le curseur sur le repli fermé et que vous faites un dd, cela supprimera le repli ainsi que son contenu, pas simplement la première ligne. Vous pourrez aussi copier un repli fermé et tout son contenu via la commande yy, de la même manière qu’avec dd. Ce texte peut ensuite être collé via p.

L’option foldmethod

L’option foldmethod est très intéressante pour les programmeurs. Par défaut, la méthode de repliage est manuelle. Cependant, Vim peut aussi créer les replis automatiquement en fonction de l’indentation du fichier, de sa syntaxe, ou de marqueurs présents dans le texte.

Pour utiliser la méthode de repliage basée sur l’indentation du fichier (pratique en python), il suffit de taper la commande :set foldmethod=indent. Cela va automatiquement créer les replis à chaque niveau d’indentation, en supposant que le fichier est correctement indenté. J’ai une petite préférence pour :set foldmethod=syntax car les replis sont créés à partir de la syntaxe du fichier (un if, un while, un commentaire…), donc même si votre fichier est mal indenté, les replis seront quand même créés correctement. Vraiment très pratique !

Un petit exemple pour bien voir à quoi ça ressemble :

Exemple avec du code C.

Exemple avec du code C.

Une fois que l’on a tapé la commande :set foldmethod=syntax, les replis sont créés automatiquement :

Replis automatiques basés sur la syntaxe.

Replis automatiques basés sur la syntaxe.

Ouverture d’un niveau avec zr :

Ouverture d'un niveau avec zr.

Ouverture d’un niveau avec zr.

Ouverture du niveau suivant avec zr encore :

Ouverture du niveau suivant avec zr.

Ouverture du niveau suivant avec zr.

Vim permet aussi de créer les replis via des marqueurs présents dans le texte. Pour passer en mode marker, tapez :set foldmethod=marker. Lorsque vous créerez un repli, vous verrez alors une marque avec trois accolades au début et à la fin du repli, une fois ouvert avec zr, comme ceci :

Repli de type marker ouvert.

Repli de type marker ouvert.

Ces marqueurs sont mis en commentaire pour ne pas générer d’erreur dans votre code, ceci dépend donc du type de fichier ouvert. Donc, si vous travaillez avec un fichier HTML, vous verrez des <!–{{{–>, et si vous éditez une feuille de styles CSS, vous verrez des /*{{{*/. Vous pouvez aussi insérer des marqueurs de repli manuellement si vous le voulez, Vim les reconnaitra tout aussi bien et il saura également les supprimer avec zd.

Les replis créés via la méthode marker peuvent être annulés grâce à la commande u car ils agissent sur le contenu du fichier, contrairement aux autres méthodes.

Il est possible d’utiliser des marqueurs autres que {{{ et }}} pour créer les replis. Il suffit de faire un :set foldmarker=begin,endbegin représente la chaine marquant le début du repli, et end celui de fin du repli.

Si vous utilisez souvent les marqueurs, vous pouvez indiquer dans votre fichier .vimrc la méthode de repli que vous préférez :

set foldmethod=marker " par exemple.

J’aime bien utiliser les modelines avec les replis, c’est vraiment pratique. Elles permettent d’indiquer des options particulières à un fichier. Ces options sont écrites dans le fichier lui-même, tout au début. Par exemple, pour une page HTML, on pourra ajouter un commentaire contenant une modeline, comme dans l’exemple suivant.

<!-- vim: set foldmethod=marker: -->
<html>
<!--{{{-->
...
<!--}}}-->
</html>

Lorsque Vim ouvrira ce fichier, il se mettra en mode marker et repliera donc les portions de texte contenues entre {{{ et }}}.

Sauver les replis

Vous avez passé beaucoup de temps à créer des replis, ce serait vraiment dommage de les perdre en fermant le fichier. Pour les sauvegarder, faites un :mkview puis fermez le fichier. Ouvrez de nouveau le fichier en question, puis faites un :loadview pour restaurer l’état des replis. Pour plus d’informations sur cette commande, :help :mkview.

Personnellement, je n’utilise pas la technique suivante, mais il est possible d’automatiser la sauvegarde et le chargement des vues en ajoutant les lignes suivantes au .vimrc.

au BufWinLeave * mkview
au BufWinEnter * silent loadview

Maintenant, chaque fois que vous fermerez un fichier, l’état des replis sera sauvé. Cet état sera rechargé quand vous ouvrirez de nouveau le fichier dans Vim.

Résumé des commandes les plus utiles

  • zf crée le repli en mode visuel ou avec un mouvement ;
  • zo ouvre le repli sous le curseur ;
  • zc ferme le repli sous le curseur ;
  • zd supprime le repli sous le curseur ;
  • zj déplace le curseur au prochain repli ;
  • zk déplace le curseur au précédent repli ;
  • zR ouvre tous les replis ;
  • zM ferme tous les replis ;
  • zm augmente le niveau de repli de un ;
  • zr diminue le niveau de repli de un ;
  • zE supprime tous les replis du fichier ;
  • [z déplace le curseur au début du repli ;
  • ]z déplace le curseur à la fin du repli ;
  • zO ouvre tous les replis sous le curseur.

Conclusion

En général, vous n’utiliserez que les six premières commandes de la liste. N’oubliez simplement pas qu’elles commencent toutes par z. Vous pouvez consulter l’aide en faisant un :help folding.

Vous pourrez approfondir le sujet avec le livre suivant : Learning the vi and
Vim Editors
.