Next Previous Contents

4. Emacsulation

Par Eric Marsden emarsden@mail.dotcom.fr

4.1 Les patrons

Les documents se conforment souvent à une structure régulière qu'il est ennuyeux de taper pour chaque nouveau document. La plupart des traitements de texte savent gérer cela et vous permettent de créer des patrons pour les courriers d'entreprise, les rapports techniques, les mémos, etc. Emacs peut faire mieux que ces « squelettes » statiques car son mécanisme de patrons vous permet de générer et d'insérer dynamiquement du texte en fonction du nom du fichier, de votre nom d'utilisateur, de la date ou des résultats d'une commande shell.

Le mécanisme d'auto-insertion d'Emacs vous permet de configurer des structures qui seront instanciées lors de la création des fichiers en fonction du nom ou du mode du nouveau fichier. Par exemple, lorsque vous créerez un fichier appelé lsys.h, il vous demandera Perform C / C++ header auto-insertion? (Insertion automatique d'en-tête C/C++ ?) et, si vous répondez oui, insérera quelque chose comme ça :

/**********************************************************************
* lsys.h                                                              * 
* Eric Marsden emarsden@mail.dotcom.fr                                *
* Time-stamp:                                                         *
**********************************************************************/
#ifndef _LSYS_H_ 
#define _LSYS_H_ 
#endif /* _LSYS_H_ */

Remarquez que #ifdefs a été généré pour éviter les inclusions multiples du fichier d'en-tête. Vous pouvez ajouter d'autres éléments, comme le copyright de votre société, un squelette pour les notes de version ou un $Id de version RCS. Le contenu inséré automatiquement dépend du mode majeur : lors de la création d'un fichier nommé lsys.sgml le texte inséré pourrait être :

    <!DOCTYPE ARTICLE PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [
    ]>
    <article>
      <artheader>
        <date>1999-03-01</date>
        <title> </title>
        <subtitle> </subtitle>
        <author>
          <firstname>Eric</firstname>
          <surname>Marsden</surname>
          <affiliation><orgname>CULTe</orgname></affiliation>
        </author>
        <authorinitials>ecm</authorinitials>
        <abstract>
          <para>
          </para>
        </abstract>
      </artheader>  
      
      <sect1><title> </title>
        <para>
        
        </para>    
      </sect1>
    </article>

L'Auto-insertion peut être activée en écrivant :

    (add-hook 'find-file-hooks 'auto-insert)
    (setq auto-insert-directory (expand-file-name "~/.autoinsert/"))

Le paquetage autoinsert (écrit par Charlie Martin) est distribué avec des patrons par défaut pour plusieurs modes. Il y a deux façons de personnaliser le contenu inséré : la plus simple (qui ne nécessite aucune connaissance d'elisp) consiste à placer des fichiers dans le répertoire ~/.autoinsert/ et à les enregistrer avec autoinsert :

    (define-auto-insert "\\.html\\'" "autoinsert.html")

Le "\\.html\\'" est une expression rationnelle qui correspond aux noms de fichiers se terminant par .html (remarquez l'utilisation de \\' pour capturer la fin d'une chaîne, au lieu de $ qui capture la fin d'une ligne car les noms de fichiers peuvent contenir des caractères « newline »). Cela fera que le contenu du fichier ~/.autoinsert/autoinsert.html sera automatiquement inséré lorsque vous créerez un fichier dont le nom se termine par .html. Cette méthode ne permet que l'insertion de contenus statiques. L'insertion de contenus générés dynamiquement est aussi possible si vous connaissez quelques rudiments d'Emacs Lisp : voici un exemple de code qui crée un squelette pour des en-têtes C ou C++, comme dans le premier exemple de cet article :

;; autoinsert.el
(define-auto-insert
   (cons "\\.\\([Hh]\\)\\'" "Mon en-tête C/C++")
      '(nil
           "/*" (make-string 69 ?*) "\n"
           " *" (file-name-nondirectory buffer-file-name) "\n"
           " *\n"
           " *  (user-full-name)  </user-mail-address> \n"
           " * Time-stamp: <>\n"
           " *" (make-string 69 ?*) "*/\n"
           (let* ((noext (substring buffer-file-name 0 (match-beginning 0)))
                  (nopath (file-name-nondirectory noext))
                  (ident (concat "_" (upcase nopath) "_H_")))
             (concat "#ifndef " ident "\n"
                     "#define " ident "\n\n\n"
                     "\n\n#endif /* " ident " */\n"))))

Comment fonctionne cette insertion automatique ? À chaque fois que vous ouvrez un fichier dans Emacs, il évalue la fonction hookée, find-file-hooks. C'est là qu'interviennent des actions comme l'activation de la mise en valeur syntaxique ou la vérification si un fichier est géré par un système de contrôle de version (RCS ou CVS). La ligne add-hook ci-dessus déclenche l'insertion automatique sur ce hook.

4.2 Dmacro

Le paquetage Dynamic Macro de Wayne Mesard vous permet d'insérer du texte structuré à tout moment, pas seulement lors de la création du document. dmacro offre des services comme l'insertion du contenu d'un fichier ou du résultat d'une commande shell et le positionnement du curseur ou de la marque après cette insertion. Une caractéristique particulièrement utile est la possibilité d'indenter le contenu inséré en fonction du mode courant. Il pourrait être utilisé pour obliger au respect (en tous cas, pour encourager les développeurs à s'y conformer) des standards de codage et peut réduire le temps de développement en évitant les erreurs de frappe dans les textes répétitifs. dmacro n'est pas distribué avec Emacs ; vous devrez le téléchargez depuis ftp://ftp.sgi.com/other/dmacro/dmacro.tar.gz et l'installer (ce qui ne consiste qu'à faire make). Il peut être activé en mettant les lignes suivantes dans votre ~/.emacs (le fichier .dm contient vos macros personnelles, voir plus loin pour des exemples) :

(require 'dmacro) ;;dynamic macros
(dmacro-load "~/elisp/ecm.dm")

Le paquetage dmacro est très bien documenté, je me contenterai donc de donner quelques exemples motivants. En voici un qui insère le squelette d'un bloc for en C-mode (les macros peuvent être globales ou spécifiques à un mode majeur précis) :

    # file ~/elisp/ecm.dm
    # ================================== Stuff for C-derived modes =======
    # MODE:     c-mode c++-mode java-mode
    ifor        indent  interactive for statement (prompts for variable name)
    for (~(prompt var "Variable: ") = 0; ~prompt < ~@; ~prompt++)
    {
     ~mark
    }
    #    

On active la macro en tapant C-c d ifor (avec la complétion par tab sur le nom de la macro). Elle devrait vous demander le nom de la variable :

[image dmacro1.gif]

et le résultat devrait ressembler à [image dmacro2.gif]

L'exemple suivant montre comment insérer une marque de temps de la forme -ecm1999-02-29 dans le tampon courant (étant donnée la valeur d'une représentation externe uniforme et standardisée des dates, j'utilise systématiquement le format ISO 8601 ( http://www.cl.cam.ac.uk/~mgk25/iso-time.html). Pour invoquer cette macro, tapez C-c d dstamp. Le code correspondant (qui montre aussi comment utiliser un alias pour mettre en facteur les définitions souvent utilisées) est :

    # ALIAS: iso-date (eval (format-time-string "%Y-%m-%d"))
    
    # ================================= Stuff for all modes ============
    # MODE:     nil 
    
    dstamp      expand  user id and date
     -~user-id~(iso-date)
    #   

4.3 Paquetages concernés

Plusieurs autres paquetages fournissent des fonctionnalités similaires à celles de dmacro. tempo.el (inclus avec GNU Emacset XEmacs) a d'abord été écrit comme un ajout au html-helper-mode, afin de permettre d'insérer des balises HTML appariées, mais peut être utilisé pour d'autres buts. Il est aussi possible d'étendre le mécanisme standard des abréviations pour insérer dynamiquement du texte généré en bidouillant le abbrev-mode-hook, comme cela est expliqué dans le message suivant, posté par un anonyme sur gnu.emacs.help. Enfin, il existe un template.el, écrit par Christoph Wedler et qui semble très complet.

4.4 Feedback

Mon article de Janvier 1999 sur les mécanismes d'abréviation avait un problème de démarrage : j'expliquais comment créer des abréviations et comment les lire automatiquement au démarrage d'Emacs, mais les instructions que je donnais n'étaient pas suffisantes pour les sauver automatiquement à la sortie d'Emacs. Merci à Nat Makarevitch et à Dave Bennet pour me l'avoir fait remarquer. Voici une modification du code que j'ai proposé (la dernière ligne est celle qui manquait) :

    ;; if there is an abbrev file, read it in
    (if (file-exists-p abbrev-file-name)
       (read-abbrev-file))
   (setq-default save-abbrevs t)

Certains lecteurs européens m'ont aussi questionné à propos des abréviations contenant des caractères non ASCII sur 8 bits. Par défaut, Emacs ne les prend pas en compte car il suppose que les caractères ayant le 8ième bit à 1 ne font pas partie d'un mot. Pour modifier ce comportement (afin de prendre en compte les caractères accentués du jeu de caractères ISO-8859-1, par exemple), vous devez faire ce qui suit :

    (set-language-environment 'Latin-1) ; GNU Emacs 20.x
    (require 'iso-syntax)               ; GNU Emacs 19.x

(il y a de grosses différences dans la façon dont GNU Emacs 19.x et 20.x gèrent les différents encodages des caractères ; les versions récentes peuvent gérer des caractères codés sur plusieurs octets, requis pour les langages asiatiques. Plutôt que d'utiliser Unicode, Emacs se sert de caractères de taille variable (pour XEmacs, ce support MULE (MULtilingual enhancements for Emacs) est une option de compilation des versions récentes).

4.5 La prochaine fois...

Le mois prochain, nous étudierons la vérification orthographique avec Emacs. Merci à Jean-Christophe Arnu pour avoir commenté mon brouillon de cet article. N'hésitez pas à me contacter pour tous commentaires, corrections ou suggestions (quel est votre paquetage d'extension je-ne-peux-vivre-sans-lui favori pour Emacs ?) C-u 1000 M-x hail-emacs !

PS : Emacs n'est en aucune façon limité à Linux, car des implantations existent pour de nombreux autres systèmes d'exploitation (dont certaines ne fonctionnent qu'à moitié). Cependant, étant l'un des pièces maîtresses du logiciel libre, l'un des plus puissants, des plus complexes et des plus personnalisables, je pense qu'il à toute sa place dans la Linux Gazette.

Copyright © 1999, Eric Marsden - Publié dans le numéro 39 de la Linux Gazette, Avril 1999.

Adaptation française : Éric Jacoboni.


Next Previous Contents