Quel que soit le système d'exploitation, un type d'application s'avère invariablement indispensable. Il s'agit, bien sûr, de l'éditeur de texte. Avec un système de type Unix, comme GNU/Linux, les deux éditeurs les plus connus et les plus utilisés sont GNU Emacs et Vi. Le choix de l'un ou de l'autre de ces éditeurs est affaire de préférence et d'habitude.

Bien sûr, il existe bien d'autres éditeurs. Citons par exemple, Nedit, gEdit, Cooledit ou encore l'horrible ed ;) Le choix d'un éditeur de texte est souvent définitif, en particulier dans le cas de logiciels puissants, nécessitant un minimum d'apprentissage. En effet, très peu nombreux sont les utilisateurs qui utilisent aussi fréquemment les deux éditeurs les plus populaires. L'un comme l'autre ont leurs avantages et leurs inconvénients. Nous ne nous lancerons pas ici dans une guerre de religions, cet article porte simplement sur l'utilisation de Vi.

Vi (prononcer vi-aïe) existe en plusieurs versions. Sous GNU/Linux, le Vi le plus courant est Vim (Vi IMproved) de Bram Moolenaar. Il y a également nvi (New Vi) de Sven Verdoolaege et Keith Bostic, Elvis de Steve Kirkendall et aussi vile de Thomas E. Dickey, Kevin Buettner et Paul Fox. Les exemples fournis dans ces pages sont basés sur Vim. Mais les indications données sont génériques et s'appliquent à toutes les versions de Vi. Notez que l'apprentissage de Vi ne se limite pas à GNU/Linux, presque toutes les versions de Vi citées ci-dessus existent pour d'autres systèmes (Windows, MacOS, Dos ou encore BeOS et Amiga).

La plupart des débutants n'aiment pas Vi (ni Emacs d'ailleurs) car il semble, de prime abord, peu intuitif et complexe. En effet, si vous avez l'habitude d'utiliser des choses comme EDIT sous Dos, le Notepad de Windows ou encore le SimpleText de MacOS, vous risquez d'être un peu dérouté.

Petite précision sur les éditeurs de texte : une telle application est destinée, comme son nom l'indique, à éditer du texte et non à le mettre en forme. Un éditeur de texte permet de modifier le contenu des fichiers texte ASCII. Dans un certain sens, ce que vous voyez est exactement ce que vous obtenez :) Il n'est donc pas question de mise en forme, de gras, d'italique, de souligné, etc.

Les modes Vi

Quel que soit le Vi que vous utilisez, une chose est absolument invariable : les deux modes d'utilisation. Pour résumer, Vi peut se trouver dans deux "états". Le premier est le mode commande, il sert à donner des ordres à l'éditeur (ouverture de fichier, sauvegarde, recherche, etc.). Mais lorsque vous désirez modifier le texte, vous devez passer dans un autre mode : le mode insertion. Il est important de bien comprendre ce principe de base. Car, en fonction du mode dans lequel vous vous trouvez, l'éditeur réagira de manière différente aux touches et aux séquences de touches composées au clavier.

En mode commande, les ordres donnés prennent la forme d'un ou deux caractères. Tantôt, ces ordres (ou commandes) sont accompagnés d'arguments comme un nom de fichier ou une valeur spécifique à utiliser. Notez que le mode commande est sensible à la casse des caractères. Ainsi, la commande x (effacer le caractère sous le curseur) est différente de X (effacer le caractère AVANT le curseur). En mode commande, ce que vous tapez au clavier n'apparaît pas à l'écran. Il n'est pas nécessaire de valider les commandes avec la touche Entrée. Dernier point important concernant ce mode, il est possible de lancer des ordres spécifiques destinés à l'éditeur sous-jacent à Vi (qui n'est que la partie visible du logiciel). Ces commandes sont appelées commandes ex. Toutes les commandes ex commencent par un caractère double point (:). Dans ce cas précis, les commandes apparaissent à l'écran et il est utile de les valider.

Par défaut, après son lancement, Vi est en mode commande. Pour passer en mode insertion, vous utiliserez la commande "i". Selon la configuration de votre Vi, vous verrez ou non apparaître le mode "INSERT" au bas de l'écran. Dès lors, les caractères que vous taperez seront insérés dans le texte édité. Pour sortir du mode d'édition (et donc retourner en mode commande), appuyez simplement sur la touche Echap du clavier.

Un peu de pratique

Si les explications qui viennent d'être données vous paraissent obscures, nous allons éclaircir tout cela avec quelques manipulations. Vi se lance avec la commande... vi. Vous pouvez passer en paramètre le nom d'un fichier. Si celui-ci existe, il sera ouvert, dans le cas contraire, un nouveau fichier sera créé. Lorsqu'on ouvre un fichier, Vi le charge dans un tampon (buffer) et l'affiche à l'écran pour vous permettre d'y faire des modifications. Lorsque vous sauvegardez le fichier, Vi enregistre le tampon sur le disque et écrase l'ancien fichier. Commençons donc par éditer un nouveau fichier :

$ vi premier

Nous voici dans Vi et en mode commande. Vous devez voir apparaître en bas de l'écran un message "premier" [New File], vous indiquant qu'il s'agit d'un nouveau fichier. A présent, passez en mode insertion avec la commande "i" puis tapez un texte quelconque. Enfin, repassez en mode commande avec la touche Echap. Vous pouvez, à présent, enregistrer les changements que vous venez d'apporter au tampon dans le fichier "premier" et quitter avec la commande ZZ. Notez qu'il s'agit de majuscules et que les caractères n'apparaissent effectivement pas. Vous voici revenu à l'invite du shell. La commande ZZ n'est pas la seule manière de procéder, voici quelques synonymes :

:x  sauvegarde et quitte
:wq sauvegarde et quitte
:w  sauvegarde sans quitter

Cette dernière commande peut prendre en argument le chemin et le nom d'un éventuel fichier dans lequel enregistrer le tampon en cours. Exemple :

:w /chemin/nouveau_fichier

Notre fichier contient maintenant du texte, nous pouvons donc le rééditer pour y apporter quelques modifications. Une fois dans Vi, passer en mode insertion, mais cette fois, avec la commande "R". Ce que vous taperez maintenant à l'endroit où se trouve le curseur écrasera le texte, vous remplacez les caractères. Vous pouvez repasser en insertion en faisant Echap puis "i". Certains Vi, dont Vim, selon sa configuration, permettent de basculer de l'insertion à l'écrasement avec la touche "Inser". Reportez-vous à la documentation de votre Vi ou, s'il s'agit de Vim, attendez le prochain article ;)

Vous venez de modifier le tampon mais, comme ces modifications ne sont pas enregistrées, plusieurs solutions s'offrent à vous. Vous pouvez, bien sûr, les enregistrer avec ZZ. Mais, dans le cas où ces changements s'avèrent inopportuns, vous pouvez utiliser la commande :e! qui vous permettra d'annuler tout changement et de revenir à la dernière version enregistrée. Si vous désirez annuler ces changements et, par la même occasion, quitter Vi, vous utiliserez alors :q!

Autre caractéristique importante concernant l'ouverture ou l'enregistement des fichiers, le caractère % possède une signification particulière. En effet, % représente le nom courant du tampon, c'est-à-dire le nom du fichier que vous avez originellement ouvert. Ainsi, en utilisant la commande :

:w %2

vous enregistrez vos modifications sous le nom premier2 dans le répertoire courant.

Utilisation plus poussée

Commençons nos manipulations plus élaborées avec quelque chose de simple : les déplacements du curseur. Déplacer le curseur dans le texte est quelque chose de relativement facile avec Vi à compter du moment où l'on a assimilé certaines règles.

De base, h, j, k et l permettent respectivement un déplacement du curseur de un caractère à gauche, en bas, en haut et à droite. Notez la position de ces touches sur le clavier... elles se suivent. Bien sûr, vous pouvez également utiliser les habituelles touches de direction.

Peu importe le mode dans lequel vous vous trouvez, un déplacement vertical dans le texte se fera ligne par ligne. Une ligne dans Vi est tout le texte contenu entre le premier caractère et le retour chariot final. Ainsi, une phrase faisant visuellement 5 lignes de texte à l'écran n'en fera réellement qu'une seule. Un déplacement vertical d'une ligne (avec j ou k) déplacera donc visuellement le curseur de 5 lignes. Faites l'essai sur un gros fichiers, vous comprendrez rapidement. Ce fonctionnement est très peu courant avec les éditeurs de textes Dos/Windows que vous connaissez sans doute déjà. Mais il s'agit d'une simple habitude à prendre.

En dehors des déplacements simples "au caractère", il existe tout un jeu de touches permettant un déplacement bien plus efficace. En voici quelques-unes :

w déplace le curseur au début du mot suivant
b déplace le curseur au début du mot courant ou précédent
e déplace le curseur à la fin du mot courant

Plus intéressant, les touches ) et ( vous permettent respectivement de déplacer le curseur au début de la phrase courante/précédente ou de la phrase suivante. Une phrase est une suite de caractères se terminant par un point suivi d'un espace.

Quel que soient les touches de déplacement que vous utilisez, vous pouvez les faire précéder d'une valeur numérique. Celle-ci indiquera alors le nombre d'occurences de la commande. De ce fait, dans le mode commande, si vous tapez 12l, vous déplacerez 12 fois le curseur d'un caractère vers la droite.

Modification du texte

Qu'il s'agisse d'un fichier de configuration, de sources ou encore, plus simplement, d'un texte quelconque, il existe un grand nombre de modifications différentes que l'on peut apporter à un fichier :

- Suppression
En dehors des habituelles touches "Effacement arrière" (backspace) et "Suppr" (delete) qui s'utilisent en mode insertion, Vi dispose d'un large panel de commandes d'effacement bien plus efficaces. Toutes les commandes de suppression débutent par la lettre "d" comme delete. Le second caractère de la commande renseigne Vi sur l'objet auquel s'applique la suppression :

dw : efface les caractères d'un mot se trouvant après le curseur (notez que l'espace immédiatement après ce mot est également supprimé). Si votre curseur est positionné en début de mot, celui-ci sera supprimé dans son intégralité. En revanche, si le curseur se trouve à un endroit précis du mot, ce n'est que la fin du mot qui sera éliminée.

Dans le même esprit :

dE : supprime le reste du mot avec la ponctuation.
db : supprime le début du mot (les caractères placés avant le curseur dans le mot)
d0 : supprime tous les caractères de la ligne placés avant le curseur.
d$ : supprime tous les caractères de la ligne placés après le curseur. La commande D est un raccourci pour d$.
dd : supprime la ligne complète (attention, il s'agit d'une ligne au sens Vi du terme).

Comme toutes les commandes, celles-ci peuvent être précédées d'une valeur numérique indiquant le nombre d'occurences.

- Déplacement
Un déplacement de texte est une suppression suivie d'un ajout. Toutes les commandes de suppression précédemment citées permettent des déplacements de texte. Ainsi, une ligne supprimée avec dd pourra être placée après le curseur, n'importe où dans le texte avec la commande p. Si vous préférez placer ce texte avant le curseur, utilisez P. Attention : seul le dernier texte supprimé pourra être placé avec p ou P. Si vous utilisez plusieurs fois une commande de suppression, ce n'est que le dernier objet "texte" qui sera placé. Les précédentes suppressions seront perdues. Nous verrons dans un prochain article comment conserver les textes supprimés dans un tampon spécifique. Une fois encore, vous pouvez préciser le nombre d'occurences de votre placement de texte. 3p placera trois fois de suite le texte précédemment supprimé.

- Copie
Rien de spécial ici, la copie de texte (yanking) se fait par les commmandes y, de la même manière que la suppression. Notez cependant que Y n'est pas un raccourci pour y$ mais pour yy (copie de la ligne complète). Le texte copié peut ensuite être placé avec les commandes p/P.

- Annulation et répétition
Les erreurs de saisie sont fréquentes chez les humains. Il est donc normal que l'éditeur de texte permette l'annulation de la dernière modification. Dans ce cas, la commande u vous permettra d'annuler votre dernier changement. Avec le Vi "classique", seule la dernière modification peut être annulée. Une seconde utilisation d'u annulera l'annulation :) Les différents Vi modernes comme Vim ou nvi permettent de choisir un fonctionnement différent et de conserver un grand nombre de niveaux d'annulation.

Dans certains cas, il est également pratique de pouvoir répéter la dernière manipulation. Ce sera donc la commande . qui sera utilisée.

- Répétition avec argument numérique
Nous en avons déjà parlé, les commandes peuvent être précédées d'une valeur de répétition. Bien que cela soit fort pratique pour une suppression ou un placement de texte, il est un domaine où cette fonctionnalité est encore plus utile. Imaginez-vous en train d'éditer un fichier de configuration. Lorsqu'il s'agit d'un gros fichier, il est courant de placer judicieusement des commentaires afin de conserver une trace des modifications. Parfois, il est également utile de bien séparer chaque partie du fichier par une ligne composée, par exemple, de #. Quoi de plus lassant que de rester appuyé sur la touche en attendant d'obtenir le résultat escompté ? Avec Vi, rien de plus facile : si vous désirez placer 25 occurences d'un ou de plusieurs caractères, il vous suffit d'utiliser :

25i#<ECHAP>

Et vous obtiendrez automatiquement vos 25 dièses (#) à la position courante du curseur.

Recherches simples

Fonctionnalité indispensable de tout éditeur de texte qui se respecte, la recherche est indispensable dans bien des cas. Imaginez-vous en train de parcourir les quelques 400 ou 500 lignes d'un fichier de configuration à la main pour y trouver l'option que vous désirez changer... Impensable !

La recherche simple de motifs avec Vi se fait en utilisant la commande / pour une recherche vers le bas ou avec ? pour une recherche vers le haut. Ainsi, en tapant /coup<ENTREE>, vous recherchez le groupe de caractères "coup". Faites bien attention aux espaces. Avec une telle recherche, vous trouverez aussi bien le mot "coup", que "couper", "coupant", etc.

Vous pouvez répéter la recherche précédente vers le bas avec /<ENTREE> ou vers le haut avec ?<ENTREE>. Sachez également que la commande N vous permet de répéter la recherche dans le sens opposé. Vous pouvez également combiner les opérations de recherche et de suppression avec, par exemple, une commande de suppression. Attention, aucune confirmation n'est demandée par défaut ! Ainsi, la commande :

d/coup

supprime la prochaine occurence du groupe de caractères "coup" dans la recherche vers le bas. N'oubliez pas que u vous permet d'annuler une éventuelle erreur de manipulation.

Il existe également une version minimaliste de la recherche. Celle-ci correspond à la commande f et permet de rechercher un caractère dans la ligne courante. placera le curseur sur la prochaine occurence du caractère è. Inversement, placera le curseur sur la précédente occurence du caractère è.

Recherches et remplacements avancés

Nous venons de voir quelques fonctionnalités courantes de recherche avec un éditeur de texte. N'importe quel éditeur "bas de gamme" en fait de même, mais ce qui fait la puissance de logiciels comme Vi ou encore Emacs dans ce domaine est la capacité d'utiliser beaucoup plus de critères dans la recherche. Prenons un exemple simple...

Supposons qu'après être arrivé au terme de la rédaction d'un texte, vous vous rendiez compte d'une regrettable erreur : vous avez utilisé le terme "boîte" en lieu et place de "récipient" dans tout le texte. Pire encore, vous avez tantôt écrit ce mot "boîte" et tantôt "boite". Comment donc rechercher ce terme dans ces différentes versions et ce, au singulier comme au pluriel ? Pas d'inquiétude, c'est un jeu d'enfant avec Vi :

/bo.te*

Qu'avons-nous fait ? Nous venons de rechercher vers le bas un groupe de caractères dont les deux premières lettres sont bo, suivis en troisième de n'importe quel caractère, suivi de te puis de n'importe quelque nombre de caractères. bo.te* est un motif de recherche ou pattern, en anglais. Clarifions un peu tout cela. Le . représente n'importe quel caractère unique n'étant pas une nouelle ligne. Les espaces sont considérés comme des caractères. Le * représente n'importe quel nombre de caractères.

Mais cela ne convient pas vraiment. En effet, vous pouvez parfaitement avoir des mots dans votre texte répondant exactement aux mêmes critères de recherche ("booter" ou "bonté") par exemple. Dans le cas d'une recherche, ce n'est pas vraiment grave, mais avec un remplacement, le résultat peut être catastrophique. Il nous faut donc être plus précis dans notre recherche en spécifiant des différentes "alternatives" pour ce mot. Réfléchissons, nous pouvons avoir un "i" ou un "î", nous pouvons donc spécifier cela dans notre recherche. Celle-ci sera alors :

/bo[iî]te*

Les crochets permettent de définir plusieurs alternatives pour un caractère. Ici [iî] signifie "i" ou "î". Le résultat est bien meilleur cette fois. Passons donc à l'étape suivante en procédant à nos remplacements :

:%s/bo[iî]te*/récipient/gc

Cette fois-ci, nous utilisons le mode ex pour remplacer toutes les occurences du mot. Voyons cela dans le détail :

% est un caractère très utile pour ce genre de manipulation. Il s'agit en fait d'un raccourci pour 1,$ qui signifie "depuis la ligne 1 jusqu'à la fin du fichier". Plutôt que de spécifier le nombre d'occurences de la commande, nous précisons sa portée. L'unité de mesure est la ligne. Ainsi, si nous avions voulu que notre commande de remplacement ne porte que sur les 10 premières lignes, nous aurions pu faire : 1,10. De la même manière, il est possible de n'apporter des changements qu'à une ligne précise comme, par exemple, :2, qui ne concerne que la seconde ligne.

s est la commande de substitution/remplacement. Sa syntaxe est relativement simple : s/ancien/nouveau

Enfin, g et c sont optionnels. g permet d'appliquer le remplacement à toutes les occurences dans une ligne. En omettant cette option, seule la première occurence de bo[iî]te* serait remplacée. c permet de confirmer manuellement les remplacements.

Une autre manière de procéder est d'utiliser la commande g du mode ex. Attention, ne confondez pas la commande g et l'option g citée plus haut. La ligne complète utilisant la commande g serait alors :

:g/bo[iî]te*/s//récipient/gc

Le résultat est le même, mais le sens de la commande est différent. Ici, la commande g nous permet de sélectionner les lignes contenant bo[iî]te*. C'est alors sur ces lignes que nous utilisons la commande de remplacement s en substituant le motif recherché par récipient. g et c ont, bien sûr, la même utilité. Notez que vous n'avez pas besoin de répéter le motif de recherche pour la commande s si celui-ci est le même que pour g.

Pourquoi donc existe-t-il deux manières de procéder ? Nous arrivons au même résultat avec les deux méthodes car notre remplacement est simpliste. Imaginez le cas où vous posséderiez une liste très longue de produits alimentaires. Dans cette liste figureraient des tomates vertes et rouges et des haricots rouges. Malheureusement pour vous, les haricots rouges ne sont plus disponibles et remplacés par des haricots verts (je sais, c'est léger comme exemple). Vous ne pouvez donc pas rempkacer toutes les occurences de rouge en vert. Vous ne pouvez pas non plus rechercher "Haricots verts" car ces deux mots ne sont pas toujours côte à côte ("Haricots secs verts" par exemple). Dans ce cas, vous ne pouvez pas utiliser la commande s. En revanche, g vous sortira une belle épine du pied :

:g/haricot*/s/rouge/vert/g

Et voilà ! Nous venons de rechercher les lignes où l'on fait mention de haricots et ce n'est que dans ces lignes que nous remplaçons rouge par vert.

Dernier exemple

Essayons de faire utile cette fois :)
Il est courant d'utiliser certains acronymes comme s'il s'agissait de mots courants. Mais en bon français, les acronymes s'écrivent en majuscule. Ainsi, parler de "chaîne scsi" n'est pas tout à fait français. Il convient d'écrire "chaîne SCSI". Encore une fois, Vi possède une solution. Commençons par la commande adéquate :

:%s/\([sS][cC][sS][iI]\)/\U\1/g

Impressionnant, n'est-ce pas ? En réalité, ceci est beaucoup plus simple qu'il n'y paraît :

%s que vous connaissez déjà est la commande de remplacement appliquée jusqu'à la fin du fichier.
La partie entre crochets est également acquise, nous cherchons "s" ou "S" suivi de "c" ou "C", etc.
Autour de ce motif, nous avons placé des parenthèses car nous comptons nous servir du résultat de la recherche dans la suite de la commande. Comme il ne s'agit pas de caractères faisant partie du motif à rechercher, nous avons dû les faire précéder d'un \. C'est ce qu'on appelle couramment "échapper" un caractère. Vous pouvez utiliser jusqu'à 9 motifs entre parenthèses.
Nous remplaçons ensuite le résultat de la recherche par \U\1. Il s'agit ici de passer en majuscules (\U comme uppercase) et de reprendre le résultat \1.
Nous appliquons cela à toutes les occurences d'une ligne, /g

Nous nous arrêterons ici pour cette fois. Partant des explications données dans cet article, amusez-vous avec Vi. Apprenez à naviguer dans le texte, à maîtriser les changements de mode, à remplacer et rechercher du texte ... Nous continuerons le mois prochain avec des fonctionnalités bien plus amusantes :)

Liens

Vim
http://www.vim.org

Elvis
ftp://ftp.cs.pdx.edu/pub/elvis/

Vile
http://dickey.his.com/vile/

Nvi
http://www.bostic.com/vi/

Linux Magazine France n°25 - Février 2001