Accueil > Outils > Emacs > L’Éditeur de texte Emacs
jeudi 2 septembre 2010
Emacs est un éditeur de texte extrêmement puissant, conçu pour tourner sous UNIX, mais disponible sous à peu près toutes les plateformes. Je l’utilise depuis quelques années déjà, et je suis encore loin de maîtriser toutes ses possibilités ...
Je ne ferais pas ici une encyclopédie sur Emacs, mais je présente les (toutes) petites extensions que j’ai écrites, et d’une manière générale, la démarche pour installer n’importe quelle extension (bibliothèque) d’Emacs. Vous trouverez également quelques précieuses instructions pour utiliser le retour à la ligne automatique d’Emacs, si vous ne le connaissez pas déjà.
Bien sûr, je ne peux lire le tutorial à votre place. Si vous ne l’avez pas déjà lu, alors, ouvrez un Emacs, et tapez Control-h, puis t, ou bien cherchez dans le menu help, à Emacs tutorial. Il y en a dans plusieurs langues, et une <a href="http://www.linux-france.org/article/appli/emacs/TUTORIAL.fr">traduction française du tutorial est disponible ici. Si vous avez déjà quelques notions, il y a un petit aide mémoire très bien foutu : la refcard Emacs (ou cette autre refcard plus visuelle et moins dense).
Ces explications s’addressent pour l’instant surtout à des débutants, mais devraient être utiles également à des utilisateurs un peu plus expérimentés. Les gourous peuvent aller trouver les liens vers les fichiers lisp, mon .emacs et .gnus à la fin de la page.
La dernière version de ce document se trouve sur la page //matthieu-moy.fr/spip/?L-Editeur-d....
Une bibliothèque (ou, par abus de langage, librairie) peut se présenter sous plusieurs formes : Un fichier avec l’extension .el, qui est en fait un code source elisp, un ensemble de fichiers .el, souvent rassemblés dans une archive, ou encore un package pour XEmacs. Je n’ai jamais utilisé de package pour XEmacs, donc, je serais bien en mal de les documenter !
Les instructions données ici sont adaptées à un environnement UNIX (Linux en fait bien sûr partie), et devront sans doute être adaptées pour fonctionner sous Windows.
Dans tous les cas, il va falloir mettre ces fichiers quelque part. Je suppose ici que vous souhaitez une installation pour un seul utilisateur, donc, que vous souhaitez les installer dans votre répertoire personnel.
Il faut créer un répertoire dédié aux fichiers lisp. Par exemple,
`emacs-lisp’. Il faut alors dire à Emacs que ce répertoire contient
des fichiers qu’il peut utiliser. Pour ça, ajouter ces lignes à votre
fichier de configuration (~/.emacs.el
, ou
~/.emacs
). Si vous n’en avez pas, depuis Emacs, tapez C-x C-f
~/.emacs.el
RET (Même sous Windows, si, si !).
;; Positionner la variable `my-lisp-directory' sur une chaine de ;; caractères contenant le chemin complet du repertoire contenant les ;; fichiers lisp. (setq my-lisp-directory (expand-file-name "~/emacs-lisp/")) ;; Ajouter ce répertoire à la liste des répertoires contenant les ;; bibliothèques : (add-to-list 'load-path my-lisp-directory)
Bien sur, il faut commencer par décompresser l’archive. La plupart des lecteurs doivent déjà connaître ça, mais ça ne fait pas de mal de le rappeler :
tar xzvf fichier.tar.gz
Dans un environnement GNU (Linux & Cie). Explications :
Si cela ne marche pas, c’est que la version de tar utilisée n’est pas GNU. Alors, il faut appeler Gzip à la main pour décompresser l’archive : gunzip fichier.tar.gz, qui crée le fichier fichier.tar, puis tar xvf fichier.tar, qui extrait tous les fichiers contenus dans l’archive dans un répertoire.
Lire les fichiers README et/ou INSTALL ! En général, il suffit d’executer successivement les commandes
./configure --lispdir=$HOME/emacs-lisp make make install
Puis ajouter quelques lignes à votre .emacs. Tout ceci est forcément expliqué dans le fichier INSTALL ou README.
Pour des petits programmes, il n’est pas nécessaire de sortir l’artillerie lourde des ./configure, make, ... Le fichier elisp peut être distribué seul, et l’installation est encore plus simple :
Lire le fichier INSTALL, c’est bien, mais le comprendre, c’est mieux. Voilà quelques indications : Par soucis d’efficacité, Emacs attends qu’on lui demande quelque chose pour charger le contenu d’un fichier. Il y a principalement deux moyens de gérer cela :
La fonction autoload permet de dire à Emacs qu’une fonction existe, et dans quel fichier. Il se chargera ensuite de charger le fichier en question au premier appel de cette fonction. Dans la configuration par défaut d’Emacs, prèsque toutes les fonctions sont déclarées en autoload, et par exemple, les fonctions du mode emacs-lisp ne sont chargées que lorsqu’on ouvre un fichier emacs-lisp, et donc jamais pour ceux qui n’en ouvrent jamais. La syntaxe est
(autoload 'fonction "fichier (sans .el)" "La documentation de cette fonction" t)
Pour les détails, C-h f autoload RET
Les autoload sont donc très pratiques, mais si j’installe une bibliothèque contenant beaucoup de fonctions, je ne veux pas voir mon .emacs augmenter de façon démesurées. Les grosses bibliothèques contiennent en général un fichier contenant tous les autoloads nécessaires, et il suffit de charger ce fichier pour installer le tout. En plus, on ne veut pas recharger une deuxième fois un fichier déjà chargé. Pour cela, la fonction adaptée est require.
(require '<fichier(sans .el)>)
Si le fichier est déjà chargé, rien ne se passe, sinon, le fichier est chargé. Il faut pour cela que le fichier contienne l’instruction (provide ’<fichier>), mais ça, c’est le problème du développeur. Dans certains cas, le (provide ’<symbol>) et le nom du fichier ne correspondent pas. Dans ce cas, on s’en sort avec (require ’<symbol> "<fichier>.el").
Pour automatiser tout ça
Compiler les fichiers, ajouter les autoloads, ce n’est pas grand chose, mais c’est encore mieux quand c’est fait automatiquement. Et c’est bien sur possible. Il faut pour cela télécharger un petit <a href="emacs/Makefile">Makefile
(à nommer Makefile), éditer le début du fichier pour l’adapter à votre configuration, puis tapper "make". Il vous dira même quelles lignes ajouter votre .emacs. Il y a 3 variables à configurer au début du fichier :
Une condition, toutefois : Que les fichiers aient été bien écrits. La compilation en byte-code est tout à fait standard, donc ne devrait jamais poser de problèmes, mais la génération d’autoloads ne peut se faire que si les fonctions concernées sont déclarées en temps que tel, c’est à dire précédées exactement de la ligne
;;;###autoload
Comme par exemple, dans le morceau de code suivant :
;;;###autoload (defun bbdb/send-hook () "Parse headers of outgoing message, insert the addresses of the recipients one by one into BBDB if they do not exist already" (interactive)
Un mode Emacs n’est guère plus qu’une fonction qui est appelée automatiquement à chaque chargement d’un fichier. En général, ladite fonction s’intitule <nom-du-language>-mode. Par exemple, le mode Ada appelle ada-mode, le mode C appelle c-mode.
La première chose à faire, c’est de vérifier que tout marche bien. Supposons que vous venez d’installer un mode PHP. Ouvrez un fichier .php. Avec de la chance, vous passerez automatiquement en mode PHP. Sinon, tappez M-x php-mode. Si vous obtenez un message d’erreur, c’est que l’installation du package n’a pas ét faite correctement. Fermez Emacs, relancez-le, et réessayez, avec un peu de chance ...
Sinon, quelque part dans la modeline (la barre en bas de l’écran), doit apparaitre PHP, et avec encore un peu de chance, vous aurez la coloration syntaxique. Sinon, M-x font-lock-mode devrait faire l’affaire.
Bon, si la partie précédante a bien marché, vous pouvez bien sur automatiser tout ça en modifiant votre .emacs.
Pour lancer un mode automatiquement, c’est la variable auto-mode-alist qui s’en occupe. C’est une liste de doublets (expression régulière, mode). Par exemple, pour lancer php-mode pour tous les fichiers ayant l’extension .php, il faut écrire :
(add-to-list 'auto-mode-alist (cons "\\.php$" 'php-mode))
Explications : le "." est un caractère spécial pour les expressions régulières, et doit être échappé avec un "\". Mais le "\" est un caractère spécial pour les chaînes en elisp, et doit lui-même être échappé par un autre "\". Le "$" à la fin est un caractère de fin de chaîne. En bref, "\.php$" veut dire "Toute chaine se terminant par la séquence .php".
Allez, pour la route, un exemple plus compliqués : ".[eE]macs[0-9]+\.[0-9]+".
Pour avoir la coloration syntaxique automatiquement, c’est
(global-font-lock-mode 1)
Toujours dans le fichier ~/.emacs.el
.
Quelques petites extensions pour Emacs que j’ai écrites, ou bien auxquelles j’ai participé :
— >
J’en profite pour publier mes fichiers de configuration :
Et un petit fichier de configuration pour le fantastique window-manager Ion qui reprend les racourcis clavier d’Emacs pour limiter le dépaysement.
include("emacs-bindings")
Quand on écrit du code ou des mails, la convention est de jamais dépasser 80 caractères dans la longueur des lignes. Pour les mails (et donc les news), la netiquette impose, selon les versions, de tronquer à 70 ou 76 caractères, pour que les réponses précédées de > > ne débordent pas. S’il vous plaît, respectez ces consignes.
Après la 5ème ligne, vous en avez tous eu marre de compter les caractères et de placer vous même les RET à la main.
Là, vous découvrez M-q : Cette commande permet de reformater un paragraphe. Par exemple, le texte
ceci est un paragraphe, mais avec une ligne vraiment très très très très longue. Elle dépasse même sans doute la largeur de l'écran. par contre, celle-ci est plus courte.
en
ceci est un paragraphe, mais avec une ligne vraiment très très très très longue. Elle dépasse même sans doute la largeur de l'écran. par contre, celle-ci est plus courte.
C’est mieux, non ?
Mais vous ne vous arrêtez pas là. On vous a dit qu’Emacs pouvait tout faire, alors vous vous demandez comment aller plus loin, et automatiser cela pour ne même pas avoir à tapper ce M-q ... Et vous avez raison : essayez M-x auto-fill-mode dans un buffer de texte, puis tappez une longue ligne. lorsque vous pressez la touche espace, Emacs revient à la ligne automatiquement si la ligne est trop longue.
Bon, c’est mieux, mais c’est encore fatiguant de devoir passer à la main en mode auto-fill. Il faudrait le faire automatiquement. Et c’est encore une fois assez simple : Pour passer en mode auto-fill dans tous les buffers en mode texte, ajouter cette ligne à votre fichier .emacs :
(add-hook 'text-mode-hook 'turn-on-auto-fill)
Que fait-elle ? Elle ajoute la fonction turn-on-auto-fill au crochet text-mode-hook. Un crochet est une liste de fonctions qui sont executées quand Emacs rentre dans un mode. Si vous voulez ne passer en auto-fill que pour les compositions de message sous Gnus, par exemple, la ligne devient :
(add-hook 'message-mode-hook 'turn-on-auto-fill)
Bon, là, vous avez l’essentiel.
Personnellement, j'aime bien justifier mon texte à gauche et à droite, pour avoir des paragraphes comme celui-ci, qui ressemble à un vrai rectangle, quelque soit la longueur des mots qui le composent. Certaines personnes ne trouvent pas cela joli ni pratique, donc, si c'est votre cas, passez votre chemin. Dans le cas contraire, il suffit de positionner la variable `default-justification' 'full. Comment ? Comme-ça : (add-hook 'text-mode-hook (lambda () (auto-fill-mode 1) (setq default-justification 'full))) Par exemple.
Une petite exception pour le mode AUC-TeX : M-q formate un paragraphe sans le justifier, et C-u M-q le justifie.
Après quelque temps d’utilisation, on est souvent génés par les coupures mal placées, typiquement avec les ` :’ en fin de ligne. Et bien il suffit de dire à Emacs de ne pas couper à ces endroits là !
(defun my-fill-nobreak-predicate () (save-match-data (or (looking-at "[ \t]*[])}»!?;:]") (looking-at "[ \t]*\\.\\.\\.") (save-excursion (skip-chars-backward " \t") (backward-char 1) (looking-at "[([{«]"))))) (setq fill-nobreak-predicate 'my-fill-nobreak-predicate)
Mais les endroits ou l’on ne veut pas couper peuvent changer selon les modes. Par exemple, j’ai ça dans mon .emacs.el pour ne pas couper au milieu d’une chaine dans le mode Ada :
(add-hook 'ada-mode-hook '(lambda () (make-local-variable 'fill-nobreak-predicate) (setq fill-nobreak-predicate 'ada-in-string-p)))
le make-local-variable est là pour que la valeur de fill-nobreak-predicate ne soit positionnée que pour le buffer courrant.
Pour tout le reste, je vous suggère un M-x customize-group fill RET. Vous y trouverez certainement votre bonheur pour toutes les autres paramètrages que vous pourriez imaginer.
Certaines personnes tiennent absoluement à sauvegarder leurs fichiers avec des lignes de 3kms de long, mais veulent visualiser leurs fichiers avec des lignes tronquées. Il y a le mode longlines pour cela, mais il faut l’installer, par exemple à partir d’<a href="http://www.geocities.com/kensanata/elisp/longlines.el.txt">ici.
Emacs est avant tout un éditeur de texte. Du texte, c’est une suite de caractères, et pour un ordinateur, c’est une suite de bits (0 ou 1). Pour arriver a afficher cette suite de bits sous une forme lisible par l’homme, il y a deux étapes :
Le problème, c’est qu’un fichier texte ne spécifié pas l’encodage qu’il utilise. Si j’édite un fichier texte avec un éditeur configuré en latin-9, et que j’utilise le symbole €, et que quelqu’un d’autre ouvre ce fichier avec un éditeur configuré en latin-1, il verra un ¤ à la place ...
À moins que vous n’ayez herité d’un Emacs préconfiguré (ce qui est heureusement de plus en plus souvent le cas), vous avez sans doutes eu des problemes avec les accents. Après avoir bidouillé un moment, voila une solution à mettre dans le <a href="dotemacs.html">.emacs.el :
(set-terminal-coding-system 'latin-1) (set-keyboard-coding-system 'latin-1) (set-language-environment 'latin-1)
Sinon, on peut aussi positionner la variable d’environnement $LANG (ou bien $LC_CTYPE) a "fr_FR". Ça, c’est pour les gens qui sont sous Unix, et c’est une configuration globale qui s’appliquera à toutes les applications.
De nos jours, le codage latin-1 est progressivement remplacé par l’UTF-8, qui permet de coder toutes sortes d’alphabets. C’est l’encodage par défaut sur la plupart des distributions Linux par exemple. Pour utiliser UTF-8 par défaut, on peut remplacer les 3 lignes ci-dessus dans le ˜/.emacs.el par :
;; ;; utf-8 ;; (setq locale-coding-system 'utf-8) (set-selection-coding-system 'utf-8) (prefer-coding-system 'utf-8)
La bonne nouvelle, c’est qu’avec ça, Emacs va essayer d’ouvrir les fichiers en UTF-8, mais si il n’y arrive pas (la plupart des fichiers latin-1 ne sont pas des fichiers UTF-8 valides), il va repasser en latin-1 tout seul. Il indique dans tous les cas l’encodage du fichier dans la modeline, en bas à gauche, avec un u pour UTF-8, ou un l, pour latin-1.
Si vous avez des soucis avec des encodages en provenance de Windows, ceci peut aider :
;; ;; cp-1252 ;; http://theotp1.physik.uni-ulm.de/~ste/comp/emacs/misc/rs-ucs-coding-system.el ;; (require 'rs-ucs-coding-system) (rs-ucs-use-iso-8859) (rs-ucs-use-windows-12xx) (define-coding-system-alias 'cp-1252 'windows-1252) (define-coding-system-alias 'cp1252 'windows-1252)
Si avec ça vous avez encore des problèmes en mode console, ceci peut peut-être aider, mais c’est censé être obsolete, donc à éviter :
(if (not (eq window-system 'x)) (standard-display-european t))
La valeur de la variable d’environnement $TERM peut avoir son importance également. Essayer les valeurs xterm, linux, vt100 ou rxvt par exemple.
Et si le copier-coller depuis les autres applications pose des problèmes avec les caractères accentués sous Emacs 21.2, alors, voici la solution :
(setq selection-coding-system 'compound-text-with-extensions)
Vous avez peut-etre noté qu’Emacs avait des problemes pour unifier les charsets latin-1 (sans l’euro) et latin-9 (avec euro) : il ne sait pas que le `é’ d’un mail encodé en latin-9 est le même que le `é’ d’un mail en latin-1, et il perd les pédales si on fait du copier-coller et qu’on obtient un document mixte latin-1/latin-9. La solution ? Utiliser ucs-tables.el avec ceci dans votre .emacs.el :
(require 'ucs-tables) (unify-8859-on-encoding-mode 1) (unify-8859-on-decoding-mode 1)
C’est bien d’avoir l’encodage par défaut pour son Emacs, mais parfois, on a besoin d’avoir un encodage particulier pour certains fichiers, et accessoirement, permettre a d’autres gens d’éditer le même fichier avec une configuration différente. Un fichier texte brut ne permet pas de spécifier son propre encodage, mais on peut dire a Emacs lequel utiliser en utilisant la <a href="http://www.linux-france.org/article/appli/emacs/manuel/html/variables.html#FILE-VARIABLES">variable locale coding. Par exemple, mon Emacs est configuré en latin-1 par défaut, mais ce fichier est encodé en UTF-8 : Il contient
Une autre syntaxe (pour du C++ par exemple), c’est, sur la première ligne du fichier :
// -*- coding: utf-8 -*-
Donc, Emacs passe en UTF-8 dès qu’il ouvre ce fichier. (Par contre, il y a d’autres instructions pour dire aux navigateurs d’utiliser UTF-8 pour afficher la page, mais ça, c’est une autre histoire.)
Si vous voulez avoir un Gnus « Netiquette compliant », evitez de poster du Quoted-Printable, avec ça dans votre .gnus.el (pas dans le .emacs.el !) :
(setq gnus-default-charset (quote iso-8859-1) message-default-charset (quote iso-8859-1) mm-coding-system-priorities '(us-ascii iso-latin-1 iso-latin-9 utf-8) mm-body-charset-encoding-alist '((iso-8859-1 . 8bit) (iso-8859-15 . 8bit)))
(Ici, on demande à Gnus de rester en iso-8859-1, alias latin-1, tant qu’il peut, et d’utiliser utf-8 sinon. On peut aussi passer un UTF-8 par défaut en mettant des ’utf-8 à la place des ’latin-1, mais on prend le risque de se faire jetter de certains serveurs de news, comme celui de free. C’est dommage, mais c’est comme ça !)
Ah, ça va mieux, mais des fois, je n’arrive pas à lire les messages des autres parce qu’ils sont mal encodes. Ceci resoudra une partie des problèmes (toujours dans le .gnus.el) :
(add-to-list 'mm-charset-synonym-alist '(iso8859-15 . iso-8859-15)) (add-to-list 'mm-charset-synonym-alist '(iso885915 . iso-8859-15)) (add-to-list 'mm-charset-synonym-alist '(ISO-8859-1 . iso-8859-1)) (add-to-list 'mm-charset-synonym-alist '(fr_FR . iso-8859-1))
Une mine d’information est disponible sur <a href="http://www.emacswiki.org/cgi-bin/wiki/CategoryInternationalization">EmacsWiki (mais c’est en anglais, cette fois).