Accueil

La réconciliation entre Vi et Emacs : le mode viper

Avertissement

Ceci est le texte écrit après coup, suite à la présentation que j'ai faite aux Journées Perl 2010 à Calais. Pour cette présentation, j'avais prévu de ne pas faire de transparents à montrer au fur et à mesure de l'exposé mais plutôt de faire une démo en direct. Je continue à penser que c'était un bon choix. J'ai donc réfléchi à ce que je devais présenter, mais je n'ai pas couché ces réflexions sur le papier et a fortiori, je n'ai pas fait de plan. Ça, en revanche, c'était une mauvaise idée. Même si j'ai l'impression que mon public a été intéressé par mon exposé, je me rends compte que j'ai allègrement pataugé dans la semoule en recherchant les différents points que je devais présenter. Et si j'ai retrouvé la plupart de ces points, je les ai exposés en désordre. Je me rattrape donc ici en exposant cette fois les différents points dans un ordre plus logique. Et comme je ne suis pas limité dans le temps, j'expose quelques points supplémentaires dont je n'avais pas intention de parler en 20 minutes.

Préliminaires

Tout d'abord, il est nécessaire que je présente mon parcours. J'ai réellement commencé à apprendre Vi lorsque j'ai participé à un projet sous Unix à partir de décembre 1992. Nous étions une trentaine de personnes dans l'équipe. À l'époque, il y avait un terminal de type VT220 par personne plus une demi-douzaine de PC Windows pour l'ensemble de l'équipe. L'essentiel du travail, aussi bien rédaction des spécifications et documents d'étude que programmation, avait donc lieu directement sous Unix. À cette occasion, j'ai imprimé man vi et man ex, soit deux fois 37 pages si je me souviens bien. Et j'ai découvert ainsi la puissance de Vi, alors que la plupart de mes collègues, qui n'avaient pas daigné lire les pages de manuel, ressentaient plutôt Vi comme une gêne ou comme un mal nécessaire.

C'est à partir de 1995 que j'ai été affecté à des projets dans lesquels nous travaillions en mode client-serveur, avec un PC pour chaque membre de l'équipe. Un collègue m'a installé Vi (ou vim ?) sous MS-DOS sur mon PC, ce qui a fait que j'ai pu continuer à pratiquer.

Ce même collègue m'a installé Linux en double boot en 1998. À peu près à la même époque, j'ai installé Linux également sur ma machine à la maison. Et, histoire de m'exercer les méninges, j'ai décidé de partir à la découverte d'Emacs (en parallèle de l'apprentissage d'un nouveau langage de programmation que vous connaissez peut-être : Perl). Depuis, je n'ai plus cessé d'utiliser Emacs. En revanche, mon utilisation de Vi a considérablement diminué, je ne l'utilisais plus que pour les messages de commit sur les dépôts CVS et SVN de l'association (je sais, j'aurais pu modifier mes variables d'environnement pour écrire mes messages de commit sous Emacs ; mais je ne l'ai pas fait et puis c'est tout).

Tout cela pour dire que j'ai plusieurs années d'expérience sur chacun des deux éditeurs de texte. Donc, je suis à même de savoir qu'il y a des actions plus faciles à faire sous Vi que sous Emacs et qu'il y en a d'autres qui sont plus faciles à faire sour Emacs que sous Vi. Simplement, j'avais fait le choix de profiter des fonctions avancées d'Emacs et de me résigner à être privé des fonctions avancées de Vi.

Puis il y a eu les Journées Perl 2009, avec ma présentation sur les nombres romains. Au cours de cette présentation, j'ai montré comment les Romains écrivaient 10 000 en « ((|)) » et 100 000 en « (((|))) ». À titre de plaisanterie, j'avais donné l'expression d'un googol en passant outre la réalité historique et en étendant ce principe aux puissances supérieures de 10. Ainsi, le googol était censé s'écrire avec 98 parenthèses ouvrantes, une barre verticale puis 98 parenthèses fermantes. Alors que j'utilisais Emacs pour taper le texte de la présentation, j'ai utilisé Vi pour taper le googol. En effet, il se tape très simplement avec la séquence suivante :

98i( [ESC] a| [ESC] 98a) [ESC]
Il aurait été possible de chercher dans les fonctions Emacs comment multiplier une chaîne de caractères par un facteur de répétition, mais j'ai préféré ouvrir une autre session dans un autre éditeur pour taper le googol, cela allait finalement plus vite. Néanmoins, cela m'a laissé un sentiment de frustration et je n'acceptais plus d'être privé des facilités d'édition de Vi.

C'est alors que je me suis intéressé à un module Emacs que j'avais jusqu'à lors négligé, le « mode viper ». Après une première lecture de la documentation, j'ai lancé ce mode et j'ai essayé de taper la séquence ci-dessus et cela m'a affiché un googol. Depuis, ma vie a basculé et je n'utilise plus que Emacs en mode viper (sauf encore une fois pour les messages de commit).

Description

Notation

Pour les commandes utilisables sous Vi et sous Emacs en mode Viper, j'ai utilisé un fond jaune. Cela permet de mieux mettre en relief certains caractères de petite taille, comme le point ou la virgule.

Les commandes Emacs apparaissent quant à elles sur un fond bleu. Pour ces commandes, j'ai utilisé la syntaxe habituelle, avec « C- » pour la touche contrôle et « M- » pour la touche méta. Une séquence de touches pour Emacs peut contenir des espaces, ces espaces ne servent qu'à améliorer la présentation, il ne font pas partie de la commande à taper.

Dans un cas comme dans l'autre, pour les touches qui n'ont pas de glyphe à l'écran, comme la barre d'espace et la touche échappement, ainsi que pour les touches modificatrices (à l'exception des « C- » et « M- » présentés ci-dessus), j'utilise une abréviation entre crochets et sur fond blanc.

Lancement

Pour lancer le mode viper, c'est très simple. Il suffit de taper M-x viper, « M » désignant la touche « méta ». Comme cette touche n'existe pas sur les claviers de PC, le mode viper se lance par l'une de ces séquences :

[ESC] x viper [RET]
[ALT] x viper [RET]
(en relâchant la touche [ESC] avant de taper « x » ou bien en relâchant la touche [ALT] après avoir tapé « x » et avant de taper le « v » de « viper ».)

Au lancement, viper affiche un écran d'accueil (que l'on peut inhiber lorsque l'on connaît par cœur son contenu) puis un écran pour indiquer son niveau. En effet, viper fonctionne un peu sur le même principe que les jeux de rôle. Vous commencez au niveau 1. Puis, au fur et à mesure de votre utilisation de viper, vous accumulez de l'expérience, ce qui vous permet de passer au niveau 2, où vous disposerez de nouvelles fonctions. Et en continuant à accumuler de l'expérience, vous passerez au niveau 3, puis 4 puis 5, avec à chaque fois de nouvelles fonctions. Mais à l'inverse des jeux de rôle, l'expérience n'est pas comptabilisée en points et c'est à votre guise que vous passez au niveau supérieur et non pas quand le maître du donjon vous le permet.

Les différents modes

Vi est connu pour être modal. Vous pouvez être en mode commande ou en mode saisie de texte. Cela apparaît si vous avez positionné le paramètre showmode (par défaut dès l'installation sous Vim, à faire soi-même dans les anciennes versions de Vi). En mode saisie de texte, la ligne d'état affiche la mention « INSERT » ou « REPLACE ». Le mode viper possède, lui, trois modes : le mode « commandes Vi », le mode « saisie de texte » et le mode « Emacs ». Ces modes sont explicités par une chaîne <V>, <I> ou <E> respectivement, sur la ligne d'état de la fenêtre. Également, le curseur change entre le mode commande et le mode saisie : rectangle de la taille d'un caractère en mode commande, ligne fine verticale en mode saisie. Voir ci-dessous les trois modes.

Viper en mode Vi Viper en mode saisie de texte Viper en mode Emacs

À noter une variante, lorsque l'on utilise R pour le mode remplacement ou les commandes du genre 3cw pour remplacer une portion de texte. Dans ce cas, la portion de texte remplacée apparaît sur un fond coloré et l'indicateur de la ligne de statut est <R>

Viper en mode remplacement de texte

En fait, pour des raisons qui apparaîtront plus tard, je n'utilise quasiment jamais le mode Emacs. Du coup, la forme du curseur et la couleur du fond me suffisent pour savoir si je suis en saisie de texte ou en commande et je ne prête plus attention à la marque « <I> » ou « <V> ».

Les différents modes (suite)

En fait, le terme « mode » possède plusieurs sens, lorsque l'on utilise Emacs et viper. Nous venons de voir les modes de fonctionnement de Vi, selon le sens que donnent les habitués de Vi à ce terme. Les habitués d'Emacs désignent par « mode » l'utilisation de certains packages (*) qui se divisent en deux sortes, major modes et minor modes.

(*) J'utilise le terme « module » également, mais c'est peut-être dû à l'influence du monde Perl. Quelqu'un qui assistait à mon exposé a évoqué les plug-ins, c'est encore un terme différent pour la même chose.

Les major modes sont associés à un langage de programmation : Perl, avec au choix le mode Perl ou le mode CPerl, ou bien awk, C, HTML et même makefile. Chacun de ces modes fournit un certain nombre de fonctions, notamment des raccourcis. Par exemple, en mode HTML, l'utilisation de la séquence C-c C-c h permet d'insérer <a href=""></a>. Également, un major mode fournit des règles pour le coloriage syntaxique.

Les minor modes, servent juste à influencer de façon plus ou moins importante le fonctionnement d'Emacs. Parmi ces minor modes on trouve par exemple :

On peut s'étonner que viper soit catalogué comme mineur, compte tenu du nombre de fonctionnalités qu'il apporte. La distinction entre majeur et mineur est en fait une différence qualitative et non pas quantitative. Pour un buffer donné, il ne peut y avoir qu'un seul mode majeur (tant pis si vous avez un here-document contenant une portion de HTML ou si vous utilisez Inline::Python), tandis que plusieurs modes mineurs peuvent être actifs simultanément. D'autre part, les modes majeurs colorient les caractères (ce que je n'aime pas et que je désactive systématiquement) tandis que les modes mineurs colorient le fond de la fenêtre derrière les caractères, ce que je trouve très pratique.

Pour passer d'un mode à l'autre

Pour passer du mode « commandes Vi » au mode « saisie de texte », c'est comme d'habitude les commandes i, a, o ou O. Ou bien, les différentes déclinaisons de la commande c de changement de texte (cw, c$, cf. et ainsi de suite). Ou enfin la commande R pour que le texte ne soit pas inséré, mais qu'il remplace le texte existant. Et pour passer du mode « saisie de texte » au mode « commandes Vi », il suffit de taper sur [ESC].

Pour accéder au mode « Emacs », il y a deux possibilités. Si vous avez besoin de soumettre une seule commande et si vous êtes en mode « commandes Vi », il suffit de taper une barre oblique inverse \ et la prochaine touche sera interprêtée avec les associations Emacs au lieu des associations utilisées par Vi. Si vous avez plusieurs commandes à lancer en mode Emacs, tapez C-z et vous verrez l'indicateur passer de <V> (ou <I>) à <E>. Le retour se fait de même avec C-z.

Touche [META] : [ESCAPE] ou [ALT] ?

Lorsque j'ai commencé à utiliser Emacs, j'ai décidé d'utiliser la touche [ESC] pour les commandes [META]. La raison est qu'il faut relâcher la touche [ESC] avant d'appuyer sur la suivante, alors que l'on doit maintenir la touche [ALT] pressée pour appuyer la touche suivante, donc la touche [ESC] est moins fatigante et moins propice à l'apparition du syndrome du canal carpien. Mais compte tenu du rôle spécifique de cette touche dans Vi et dans viper, j'ai changé mon fusil d'épaule et dorénavant, j'utilise la touche [ALT] pour les commandes [META].

Avec une exception : il existe une commande just-one-space sous Emacs pour remplacer une longue chaîne d'espaces par un seul espace. Cette fonction est associée à la séquence [META][ESPACE]. Si l'on tente d'utiliser la touche [ALT] pour ce faire, la combinaison [ALT][ESPACE] ouvre le menu de la fenêtre pour icônifier, déplacer ou redimensionner la fenêtre. C'est pourquoi je tape la séquence \ [ESC][ESPACE] pour passer en mode Emacs pour la commande suivante, laquelle commande commence par un [ESC] interprêté comme [META]. La documentation d'Emacs évoque des problèmes avec d'autres séquences comme [ALT][TAB], mais je ne sais pas à quoi cela correspond. Peut-être est-ce une super fonction de la mort dont on ne peut plus se passer une fois qu'on y a goûté...

Intégration des commandes Emacs

En fait, pour de très nombreuses commandes Emacs, il n'y a même pas besoin de changer de mode par C-z ou par \, si vous êtes au niveau 3. En effet, si le mode mineur viper n'a pas prévu d'associer une fonction à une combinaison de touches, on utilisera l'association standard Emacs et la fonction résultante. Et comme les concepteurs de viper ont pris soin de ne pas utiliser les combinaisons contenant C-x et C-c, toutes les fonctions appelées par une combinaison de touches commençant par C-x ou par C-c sont immédiatement disponibles en mode « commandes Vi » (au niveau 2 et plus) et même en mode « saisie de texte » (au niveau 3 et plus).

Il y a quelques phénomènes curieux, parfois. Par exemple, sous Emacs, pour coller une chaîne du presse-papier, on utilise C-y et pour aller en fin de ligne, on utilise C-e. Or ces deux combinaisons sont utilisées par Vi pour déplacer l'affichage (scroller) d'une ligne vers le haut ou vers le bas. Donc, dans viper en mode « commandes Vi », ces touches décalent l'affichage d'une ligne. En revanche, en mode « saisie de texte », ces commandes permettent de coller du texte et d'aller à la fin de la ligne courante. J'avoue que je me laisse encore avoir quand, pour aller à la fin de la ligne en mode « commandes Vi », je tape C-e au lieu de taper $ et que je vois l'affichage se déplacer d'une ligne.

Ce que je sais plus ou moins faire avec Emacs, mais où Vi en mode commande est meilleur

Les facteurs de répétition

C'est l'une des fonctionnalités les plus célèbres de Vi. Il suffit de taper un nombre avant de taper une commande et la commande est répétée autant de fois. Par exemple, si h vous permet de reculer d'un caractère, 8h vous permettra de reculer de huit caractères. De même, si dd supprime une ligne, 8dd en supprimera huit. Il existe également un mécanisme de répétition sous Emacs, mais cela nécessite un préfixe [META] ou C-u, c'est beaucoup moins pratique, surtout que le pavé numérique ne fonctionne pas. Les actions présentées ci-dessus se traduisent sous Emacs par C-u 8 C-b ou M-8 C-b et par C-u 8 C-k ou M-8 C-k.

Et là où Vi prend nettement le pas sur Emacs, c'est pour la répétition d'une chaîne de plusieurs caractères. Pour composer une chanson sous Vi, rien de plus simple. Tapez atra [ESP][ESC] 8ala [ESP][ESC] et vous obtenez :

tra la la la la la la la la 

Revenons à une action moins spectaculaire et comparons les différentes façons de déplacer le curseur de 5 mots vers la droite, sur une machine avec un clavier français et un pavé numérique (les conclusions seraient légèrement différentes pour un clavier américain sans pavé numérique). Sous Vi, la séquence est 5w, soit deux actions élémentaires. Sous Emacs, vous avez le choix entre M-5 M-f (deux actions élémentaires) ou C-u 5 M-f (trois actions élémentaires). La différence peut sembler minime, mais voici ce que cela donne lorsque l'on considère les actions des doigts sur le clavier. « Taper » signifie presser une touche et la relâcher immédiatement, ce qui est considéré comme une seule action, alors qu'un appui prolongé se compose de deux actions différentes pour « presser » et « relâcher ». Pour Vi :

  1. Taper le « 5 » du clavier numérique
  2. Taper le « w » du clavier principal
Pour Emacs, première variante :
  1. Presser la touche [ALT]
  2. Presser la touche [SHIFT]
  3. Taper la touche « ( » du clavier principal, pour avoir le « 5 »
  4. Relâcher la touche [SHIFT]
  5. Taper le « f » du clavier principal
  6. Relâcher la touche [ALT]
Pour Emacs, seconde variante :
  1. Presser la touche [CTRL]
  2. Taper le « u » du clavier principal
  3. Relâcher la touche [CTRL]
  4. Presser la touche [SHIFT]
  5. Taper la touche « ( » du clavier principal, pour avoir le « 5 »
  6. Relâcher la touche [SHIFT]
  7. Presser la touche [ALT]
  8. Taper le « f » du clavier principal
  9. Relâcher la touche [ALT]
Ainsi donc, un avantage important de Vi sur Emacs pour les facteurs de répétition est que l'on peut utiliser le pavé numérique pour les facteurs à un chiffre (ou pour le premier chiffre des facteurs de répétition 10 ou plus). Tandis qu'Emacs impose l'utilisation de la rangée supérieure du pavé principal, combiné avec l'appui de longue durée des touches de modification comme [SHIFT].

Les déplacements au sein d'une ligne

Si les deux éditeurs permettent le déplacement par caractère ou par mot, ou encore jusqu'à l'extrémité de la ligne, il y a un mode de déplacement qui n'a pas d'équivalent sous Emacs : la recherche rapide d'un caractère. J'en ai déjà parlé, dans un tutoriel en annexe du compte-rendu de la réunion de Paris.PM le 14 septembre 2005. Voici l'extrait correspondant.

Cela dit, en mode saisie de texte, j'utilise les commandes quasi-universelles comme [CTL][Flèche] ou les commandes Emacs, comme M-f et M-b.

Les marque-pages

Sous Emacs, on peut poser un marque-page (également appelé « marque ») par C-x r [ESP] x et, ultérieurement, faire revenir le curseur à cette marque par C-x r j x. Sous Vi et sous Viper, la pose du marque-page se fait pas m x et le retour à la marque par [BACKQUOTE] x pour revenir précisément au caractère marqué, ou bien [QUOTE] x pour revenir sur le premier caractère différent de blanc de la ligne où se trouve le marque-page. Vi est plus ergonomique et plus souple qu'Emacs. Et Emacs présente un problème exposé plus tard, problème inexistant sous Vi.

Une précaution, toutefois, pour le nom des marque-pages sous Vi et sous Viper : utilisez de préférence des consonnes. En effet, sur un clavier français, l'utilisation de [BACKQUOTE] suivi d'une voyelle peut faire que le pilote de périphérique du clavier convertira cette séquence en une voyelle accentuée « à » ou « è » et que l'éditeur de texte ne recevra pas la séquence attendue.

Le copier-coller multiple

Le copier-coller multiple et un certain nombre d'autres fonctions d'Emacs reposent sur les concepts de Région, de Point et de Marque (le « M » majuscule sert à différentier la Marque anonyme des marques nommées présentées au paragraphe ci-dessus et les majuscules de Point et de Région sont là pour ne pas faire de jaloux). Le Point est l'endroit pointé par le curseur, là où le caractère que vous tapez sera inséré. La Marque est un endroit du texte que vous avez désigné par la commande [CTL][ESP] et la Région est tout le texte entre la Marque et le Point. Donc, pour copier ou couper un bloc de texte dans un registre nommé sous Emacs, il faut que ce bloc de texte corresponde à la Région. Il faut donc aller à une extrémité de ce bloc, positionner la Marque par [CTL][ESP], déplacer le Point à l'autre extrémité du bloc sans déplacer la Marque par inadvertance et taper C-x r s x pour sauvegarder la Région dans le registre « x ». Vous pouvez remplacer x par une autre lettre de l'alphabet pour faire du copier-coller multiple, en collant les différents blocs sauvegardés par C-x r i a, C-x r i b et ainsi de suite. Vous pouvez également taper C-w pour couper ou M-w pour copier la Région dans le presse-papier, pour disposer de la chaîne dans les autres applications de votre machine.

Le problème est que la Marque est très volatile. Il est facile de la déplacer par inadvertance. Une recherche de chaîne de caractères, par exemple, positionne la Marque à l'endroit où la recherche a commencé, pour vous permettre d'y revenir éventuellement lorsque vous aurez trouvé ce que vous cherchez.

Sous Vi et sous Viper, c'est beaucoup plus facile. Vous tapez "a3dd pour couper 3 lignes que vous sauvegardez dans le registre « a », "b3yy pour copier (et non plus couper) trois lignes dans le registre « b », "c4yE pour copier 4 mots dans le registre « c », "dy} pour copier la fin du paragraphe courant dans le registre « d » et ainsi de suite. Et vous collez tout cela avec "ap, "bp, "cp et "dp,

Emacs présente un autre problème, l'espace de noms est commun pour les marque-pages et les registres de sauvegarde. Si vous avez posé une marque « a » avec C-x r [ESP] a, si ensuite vous sauvegardez une chaîne de caractères dans le registre « a » par C-x r s a, alors vous perdez votre marque-page. Et à l'inverse, si vous sauvegardez une chaîne de caractères par C-x r s a, puis que vous posez une marque « a » avec C-x r [ESP] a, alors vous perdez votre chaîne de caractères. De façon ironique, les utilisateurs de Vi ont tendance à se méfier de ce problème alors qu'il ne les concerne pas. En effet, l'utilisation de la double-quote pour les registres de sauvegarde et l'utilisation de la simple-quote et de la quote inversée pour les marque-pages provoquent une confusion sans fondement.

Les copies de bloc sans copier-coller

J'ai oublié de dire dans les préliminaires que j'ai connu l'éditeur ed, l'ancètre de Vi. Dans cet éditeur, la copie d'un bloc de lignes se fait par la commande début,fintdest et le déplacement par début,finmdest Avec Vi, c'est la même chose, avec un deux-points au début. Comme j'ai l'habitude de marquer le bloc à copier par les marques q et s, cela donne :

:'q,'st.
:'q,'sm.
On peut s'en passer, mais étant donné que je connais ces commandes, je les utilise parfois.

Également, pour supprimer toutes les lignes du début du fichier jusqu'à la ligne courante, j'utilise :1,.d. Pour supprimer toutes les lignes de la ligne courante à la fin du fichier, j'ai utilisé :.,$d jusqu'au moment où je me suis aperçu que dG était plus court.

L'indentation

Les différents modes majeurs associés à Perl, comme CPerl, ne m'apportent pas beaucoup de fonctionnalités que je trouve intéressantes et ils m'en apportent une que je considère comme une épine dans le pied : l'indentation automatique en fonction de règles qui ne me conviennent pas. Donc je préfère me mettre dans le fundamental-mode et indenter moi-même mon code. C'est fastidieux sous Emacs, mais avec Vi et Viper, c'est beaucoup plus simple. Pour une seule ligne, il suffit de taper 2i [ESP][ESC]. Pour plusieurs lignes consécutives, il convient plutôt d'utiliser les commandes << et >> avec le bon facteur de répétition et après avoir positionné la variable viper-shift-width. Notons que cela se fait par :

:set[RET]sw[RET]2[RET]y
sw est l'abréviation de shiftwidth et où le y final répond à la suggestion d'adopter cette valeur de façon permanente, en d'autres termes d'insérer
(setq viper-shift-width 2) ; don't touch or else...
dans le fichier .viper. Éh oui, le langage de script de viper est E-Lisp, comme Emacs.

L'interaction avec le shell

Comme de nombreux programmes Unix, Vi permet de lancer un shell sans quitter l'éditeur. Cela se fait avec :! commande. Par exemple, si vous voulez connaître la date et l'heure, tapez :!date.

Mieux, si vous voulez insérer la date et l'heure dans votre texte, tapez :r!date : :r pour « insère un fichier », ! pour « ce n'est pas un vrai fichier, c'est la sortie standard d'une commande » et date pour « laquelle commande est celle qui donne la date et l'heure ».

Encore mieux, vous pouvez passer une portion de votre texte en entrée standard à la commande Unix. Cela se fait avec la commande pleine page ! qui, comme d'habitude, se décline en n!! pour un nombre de lignes connu et !mvt pour désigner la portion à utiliser avec un mouvement de curseur. Par exemple, si vous voulez savoir combien de lignes, de mots et de caractères figurent dans les trois lignes qui suivent, tapez 3!!wc. Les trois lignes sont remplacées par le résultat de wc (vous pouvez récupérer l'ancien contenu avec u pour undo, bien entendu). Ou bien, pour reformatter le paragraphe suivant et harmoniser la longueur des lignes, tapez !}fmt, voire !}nroff pour avoir en plus une justification à droite.

Ce que je ne sais pas forcément faire avec Vi, mais où Emacs est nettement meilleur

J'ai lu la page web présentant le livre sur Vi chez O'Reilly. Cette page donnait en exemple le chapitre sur les clones de Vi : nvi, Vim et Elvis; Dans ce chapitre, il y a un gag récurrent. De temps en temps, le texte présente une fonctionnalité suivie d'une note de bas de page, laquelle rappelle que cela fait longtemps que les utilisateurs d'Emacs en disposent. Donc, si les utilisateurs d'Emacs en disposent, c'est que les utilisateurs de Viper en disposent aussi. J'ai installé Emacs 20.4 sur mon PC Windows au travail en novembre 1999. Depuis, j'ai changé trois fois de PC, mais à chaque fois, j'ai récupéré mes anciens fichiers, dont les fichiers d'installation d'Emacs et c'est encore Emacs 20.4 qui est installé sur mon PC professionnel à la mi-2010. Donc, sauf indication explicite du contraire, toutes les fonctionnalités présentées ci-dessous, étaient disponibles sous Viper en 1999.

Multi-buffers

En 1993, il m'arrivait d'éditer plusieurs fichiers à la fois sous Vi. Il y a essentiellement deux façons de le faire. La première consiste à énumérer les fichiers sur la ligne de commande :

vi fich1 fich2 fich3
puis à passer de l'un à l'autre avec :n. Une fois arrivé au dernier, ou même avant d'arriver au dernier, il était possible de revenir au premier avec :rew (rewind pour « rembobiner » la liste des arguments). L'autre façon de faire consiste à demander en cours d'édition un nouveau fichier avec :e [ESP] autre-fich. Puis le passage du second au premier et du premier au second se fait par :e#

Sous Emacs, c'est beaucoup plus simple. Si vous voulez éditer un nouveau fichier, existant ou à créer, il suffit de faire C-x C-f et le nom du fichier. Cela crée un buffer portant le même nom que le fichier et vous pouvez passer d'un buffer à l'autre avec C-x b suivi du nom du buffer. Ou bien, vous pouvez avoir la liste des buffers avec C-x C-b et choisir le buffer à éditer dans la liste. De plus, vous n'êtes pas obligé de sauvegarder le buffer que vous mettez de côté (quoique, cela ne fait pas de mal de le sauvegarder).

Cela ne m'empêche pas d'utiliser :q pour suppprimer le buffer courant, au lieu d'utiliser C-x k. Et il m'arrive même de créer un nouveau buffer en ouvrant un fichier existant par :e fichier.

Multi-fenêtre

Je sais que cela existe sous Vim, mais je n'ai jamais pris la peine de l'apprendre. J'ai préféré apprendre Emacs à la place. Sous Emacs, vous scindez la fenêtre courante en deux fenêtres superposées avec C-x 2 ou en deux fenêtres côte à côte avec C-x 3. Vous passez d'une fenêtre à l'autre en cliquant (ce que je fais très rarement) ou avec C-x o (o comme Oscar). Vous supprimez la fenêtre courante avec C-x 0 (zéro) ou vous supprimez toutes les fenêtres à l'exception de la fenêtre courante avec C-x 1 (le chiffre un). Il est possible de redimensionner les fenêtres, ce que je ne fais quasiment jamais. Et quand j'en ai vraiment besoin, j'utilise la souris au lieu de taper la séquence de touches que je n'ai pas pris la peine d'apprendre.

Mode Dired

« Dired » est l'abréviation de directory editor. Ce mode vous permet de lister les fichiers et sous-répertoires du répertoire courant ou du répertoire dont vous donnez le nom. Une fois ces fichiers affichés, vous pouvez effectuer quelques opérations courantes sur ces fichiers : suppression, changement de nom, copie, changement de propriétaire ou de groupe, modification des permissions d'accès rwx et, bien sûr, ouverture pour édition. Cela fait penser à Midnight Commander. J'ai essayé ce programme, mais je suis toujours revenu à Emacs et son mode Dired. Peut-être y a-t-il des fonctionnalités intéressantes dans Midnight Commander, seulement je préfère améliorer ma connaissance d'Emacs et de Viper plutôt que d'investir du temps d'apprentissage dans Midnight Commander. Ultérieurement, lors de la réunion technique du 16 mars 2011, à l'occasion de l'exposé de Franck, il me semble avoir vu quelque chose de similaire sous Vim.

Mode ediff

Les fonctionnalités offertes par ce mode existent dans de nombreux éditeurs, comme UltraEdit et PSPad, donc je suppose que cela existe également sous Vim. Mais bien sûr, cela existe sous Emacs depuis longtemps. Cette fonction permet de comparer ligne à ligne ou mot à mot deux buffers (ou deux parties de buffers, en utilisant la Région définie pour chacun) et de reporter sélectivement les modifications d'un buffer à l'autre. Si vous avez un fichier en UTF-8 et un autre en ISO-8859-1, ediff ne sera pas gêné (*) par le fait que l'on a des 0xC3A9 d'un côté et des 0xE9 de l'autre, dans les deux cas c'est le même caractère « é ». Le diff en ligne de commande n'est pas aussi futé.

(*) À condition que votre version d'Emacs soit suffisamment récente. Avec Emacs 20.4, le support d'UTF-8 est inexistant, donc a fortiori le mode Ediff détectera des différences entre 0xC3A9 et 0xE9.

Blocs rectangulaires

J'ai signalé plus haut que je préférais utiliser le copier-coller à la mode de Vi plutôt que celui à la mode d'Emacs, avec une exception. L'exception est lorsque j'ai besoin d'utiliser des blocs rectangulaires. Cela n'existe pas sous Vi, je ne sais pas si cela existe sous Vim, mais cela existe sous Emacs. Lorsque vous avez positionné la Marque et le Point, vous tapez C-x r r a et cela sauvegarde dans le registre a le rectangle dont la diagonale est délimitée par la Marque et le Point. Vous pouvez le coller à un autre endroit avec C-x r i a. Et il existe de nombreuses autres commandes pour traiter un rectangle de texte. Essayez apropos-command rectangle.

Recherche incrémentale

Si j'ai bien compris, cela existe sous Vim, donc pas besoin d'une longue explication. Juste une remarque. Sous Emacs, vous pouvez chercher soit une chaîne, soit une expression régulière. C'est C-s pour la recherche incrémentale d'une chaîne et M-C-s pour la recherche incrémentale d'une expression régulière. Pas besoin de modifier une variable de configuration. Et en plus, l'historique des expressions régulières est distinct de l'historique des chaînes.

Inversion de caractères, de mots ou de lignes

La documentation de Vim explique que cela peut se faire par xp. Mais du coup, cela écrase le contenu du presse-papier. Tandis qu'avec C-t sous Emacs, les deux caractères sont intervertis et en plus, votre presse-papier est inaltéré. Vous disposez également de M-t qui échange deux mots en laissant en place la ponctuation (un peu déroutant parfois) et C-x C-t qui échange deux lignes.

Conversion entre minuscules et majuscules

Avec Vi, la conversion entre minuscules et majuscules se fait simplement par ~, avec un facteur de répétition éventuel. Contrairement aux autres fonctions, il n'est pas possible de faire suivre la commande d'un déplacement pour déterminer son champ d'action. Prenons un exemple avec la ligne :

Que j'aime à faire apprendre un nombre utile aux sages !
sachant que le curseur (ou le Point) se trouve au début de « apprendre » et que je veux faire passer ce mot en majuscules. Il faut que j'estime la longueur de ce mot. Pour ceux qui connaissent par cœur le nombre pi, c'est facile, c'est 9 caractères, donc il faut taper 9~. Mais supposons que je me trompe dans mon estimation et que je tape 10~. Là, j'ai de la chance, le dixième caractère transformé en majuscule est le blanc qui suit « apprendre », donc il n'a pas été altéré par cette manip. Maintenant, si je tape 8~ ou 11~, dans un cas on a obtenu « APPRENDRe » et il faut faire un ~ complémentaire, dans l'autre cas le mot suivant est « Un » et je dois revenir en arrière pour changer le « U » en « u »

À l'inverse, avec Emacs, la conversion ne se fait pas caractère par caractère, mais mot par mot. Si le Point est au début d'un mot, ou sur du blanc ou de la ponctuation précédant le mot, M-u convertira ce mot en majuscules, M-l (« l » comme « Lima ») le convertira en minuscules et M-c convertira la première lettre en majuscule et les autres lettes en minuscules. Et si le Point se trouve en plein milieu du mot, c'est seulement la partie après le Point qui sera convertie. Ainsi, si le Point se trouve entre le « e » et le « n » de « apprendRe » (avec un « R » majuscule), alors on aura :

  M-u -> appreNDRE
  M-l -> apprendre
  M-c -> appreNdre
Notons qu'il existe également C-x C-u et C-x C-l qui opèrent sur la Région au lieu de s'appliquer simplement sur un mot.

Parenthèses équilibrées

Il est bien connu que les utilisateurs de Vi appuient comme des malades sur la touche % pour passer d'une parenthèse ouvrante à la parenthèse fermante correspondante, ou inversement. Je préfère la version Emacs, M-C-f pour avancer et M-C-b pour reculer, car cela fonctionne aussi en mode saisie de texte, et cela fonctionne avec les « < » et les « > » en mode HTML.

Tableaux

Un jour, en consultant le manuel d'Emacs, j'ai découvert par hasard qu'il contenait la solution à un problème que j'avais à ce moment-là : l'écriture de tableaux. Avec une commande du style table-insert, vous pouvez insérer quelque chose comme :

+-----+-----+-----+
|     |     |     |
+-----+-----+-----+
|     |     |     |
+-----+-----+-----+
|     |     |     |
+-----+-----+-----+

dans votre texte. La coloration n'est pas très heureuse, mais cela vaut le coup compte tenu des fonctions obtenues. Si ensuite vous insérez du texte dans une cellule, le texte s'insérera sans provoquer le déplacement de la barre verticale de droite. Si vous continuez à taper du texte alors que le texte déjà présent touche cette barre verticale, alors la cellule entière, ainsi que les cellules de la même colonne, sont étendues en fonction de la longueur du texte. Ainsi, si vous avez commencé à taper « azert »

+-----+-----+-----+
|azert|     |     |
+-----+-----+-----+
|     |     |     |
+-----+-----+-----+
|     |     |     |
+-----+-----+-----+

et que vous continuez avec « yuiop », vous obtenez

+----------+-----+-----+
|azertyuiop|     |     |
+----------+-----+-----+
|          |     |     |
+----------+-----+-----+
|          |     |     |
+----------+-----+-----+

Le seul inconvénient, c'est que l'insertion de texte n'est pas très compatible avec la frappe rapide. Si vous sauvegardez votre fichier puis que vous l'éditez le lendemain, vous pouvez réactiver ce mode table en tapant table-recognize. Vous pouvez changer les dimensions avec C-c C-c > pour étendre une cellule ainsi que toutes celles de la même colonne, ou bien C-c C-c < pour les contracter. Pour une extension ou une réduction verticale, c'est C-c C-c } et C-c C-c {. Pour une extension de plusieurs caractères en un seul coup, taper \ C-u 12 C-c C-c > (le backslash sert à quitter temporairement le mode Viper et passer en mode Emacs, quant au facteur 12, bien qu'il contienne plusieurs chiffres, il est possible de le taper avec le pavé numérique).

Il y a un certain nombre d'autres commandes sur les tableaux, dont une qui m'a bien plu : table-generate-source. Comme son nom l'indique, cette commande convertit le tableau dans un autre langage. Vous avez le choix entre HTML, LATEX et un langage que je ne connais pas, CALS, qui ressemble à du HTML ou du XML. Depuis, j'ai ouvert un compte sur Github et j'ai créé un dépôt montrant comment mettre à profit cette commande table-generate-source dans un makefile.

Autres modes majeurs

Lorsque j'ai raconté tout-à-l'heure qu'un mode majeur était associé à un langage de programmation, j'ai un peu simplifié la question. Il existe d'autres modes majeurs. Le mode Dired, déjà signalé, est un mode majeur qui n'est associé à aucun langage de programmation. Pour d'autres exemples de modes majeurs, il suffit d'un dessin (ou deux, en fait).

mode Tetris mode Pong

Ce que je n'ai pas l'habitude de faire ni sous Vi ni sous Emacs

Les séquences de touches programmées

Bien que j'en ai déjà parlé dans un compte-rendu de réunion, je n'utilise quasiment pas les fonctions d'insertion automatique, qu'elles soient héritées de Vi ou d'Emacs. J'ai plutôt tendance à écrire du Lisp pour ce faire :

(defun html-espace-insec () (interactive) (insert "&nbsp;"))
(define-key html-mode-map "\C-c " 'html-espace-insec)
et cela fonctionne aussi bien en mode commande qu'en mode saisie de texte.

Le débugage intégré

Comme pas mal de monde, ma méthode habituelle de débugage consiste à insérer des print à divers endroits de mes scripts. Il m'est toutefois arrivé d'utiliser le débugueur intégré de Perl. Je ne crois pas l'avoir utilisé depuis la ligne de commande avec perl -d. En revanche, j'ai dû utiliser une fois Devel::ptkdb, deux ou trois fois ddd et une fois la commande Emacs M-x perldb.

Intégration de Perl dans l'éditeur

À l'époque de Perl 5.5.3 ou 5.6.0 et d'Emacs 20.6, j'ai réussi à compiler Emacs::Lisp, qui fournit un éditeur « Perlmacs » que l'on peut scripter aussi bien en Perl qu'en e-Lisp. Ce module n'a pas l'air d'être maintenu et mes tentatives de l'utiliser avec des versions plus récentes de Perl et d'Emacs ont échoué.

Je sais que Vim comporte un interpréteur Perl intégré, mais en lisant la doc, cela a l'air de se limiter au filtrage d'une portion de texte par du code Perl. Notamment, il ne semble pas possible d'avoir des fonctions interactives pour proposer un choix à l'utilisateur ou lui demander une confirmation. Les différentes utilisations de ! de Vi présentées plus haut procurent des possibilités similaires.

Marque-pages de longue durée

Les marques posées par la commande Vi mx ou par la commande Emacs C-x r [ESP] x sont momentanément indisponibles lorsque le buffer correspondant est inactif et elles disparaissent complètement lorsque le buffer est supprimé. Il existe en revanche des marque-pages de longue durée, qui survivent à la suppression du buffer. Notamment, Vi utilise le fichier tags créé par la commande shell ctags. Et pour Emacs, il y a toutes les commandes énumérées par apropos-command bookmark. Je n'ai jamais éprouvé le besoin de les utiliser. Je préfère repartir de rien lorsque je lance une nouvelle session d'édition.

Considérations diverses

Éditeur vile

Lors de ma présentation, quelqu'un a évoqué l'éditeur vile, l'acronyme signifiant VI Like Emacs. J'ai survolé la documentation et j'ai l'impression que la partie « comme Emacs » consiste juste à avoir des commandes appelées par des séquences en C-a ou C-x sans rechercher systématiquement à reprendre les séquences utilisées dans Emacs. Je préfère Viper.

Dissimulation de texte

Le site sur les éditeurs de texte présente une catégorie importante d'éditeurs de texte, les folding editors. Ce sont des éditeurs qui sont capables de masquer un certain nombre de lignes de texte pour faire apparaître dans la même fenêtre des fragments éloignés du fichier en cours d'édition. Hélas, cette fonctionnalité est implémentée en général d'une façon trop restrictive. Cela ne fonctionne que pour les fichiers contenant un source de programme et les portions de texte que l'on peut masquer sont directement déterminées par la syntaxe du langage de programmation : définition de fonction dans certains éditeurs ou bloc délimité par des accolades (dans le cas de Perl et C) ou des couples Begin / End pour d'autres éditeurs. Il n'y a pas moyen de choisir les lignes à masquer. Ça m'écorche le cœur de l'écrire, mais dans un système aussi archaïque et désagréable que MVS, l'éditeur ISPF offre la possibilité à l'utilisateur de masquer le nombre de lignes qu'il a envie de masquer, quel que soit le langage de programmation utilisé et même pour du texte en langage naturel.

Post-scriptum : en discutant avec Marc Chantreux, j'ai appris que la dissimulation de texte sous Vim était beaucoup plus évoluée que ce que présente le site web ci-dessus. Notamment, l'utilisateur a la possibilité de spécifier quelles lignes de texte il souhaite dissimuler et faire réapparaître, sans nécessairement tenir compte de la syntaxe. Ou alors, il s'en remet à la syntaxe ou à l'indentation pour ce faire.

Deuxième post-scriptum : lors de YAPC::Europe 2016, Rolf Langsdorf a présenté un exposé sur Emacs. Dans cet exposé, il a évoqué le mode Evil, qui émule non pas simplement vi, mais vim, comme il est marqué dans le paragraphe « Discussion ». Le principal défaut du mode Evil, c'est qu'il n'est pas installé en standard avec Emacs, alors que viper fait partie de l'installation standard. Et quelques semaines plus tard, paraissait une information présentant Spacemacs

Conclusion

Que préférez-vous ? Un éditeur qui évoque des jolies femmes aussi séduisantes que Vivica Fox, Lucy Liu et Uma Thurman ? Un éditeur digne d'une voiture de sport ou d'un avion de chasse supersonique ? Ou bien un éditeur qui évoque la poudre à récurer ?


Texte diffusé sous la license CC-BY-NC-ND : Creative Commons avec clause de paternité, excluant l'utilisation commerciale et excluant la modification.

Accueil