Emacs Lisp - Emacs Lisp

Emacs Lisp
EmacsIcon.svg
Logo Emacs
Paradigme Fonctionnel , méta , réfléchissant
Famille Zézayer
Conçu par Richard Stallman ,
Guy L. Steele, Jr.
Développeur Projet GNU
Première apparition 1985 ; il y a 36 ans ( 1985 )
Version stable
27.2 / 25 mars 2021 ; il y a 3 mois ( 2021-03-25 )
Discipline de frappe Dynamique , fort
Portée Dynamique, éventuellement lexical
Plate-forme Emacs
Système d'exploitation Multiplateforme
Licence GPLv3
Extensions de nom de fichier .el, .elc
Influencé par
Lisp commun , Maclisp

Emacs Lisp est un dialecte du langage de programmation Lisp utilisé comme langage de script par Emacs (une famille d' éditeurs de texte le plus souvent associée à GNU Emacs et XEmacs ). Il est utilisé pour implémenter la plupart des fonctionnalités d'édition intégrées à Emacs, le reste étant écrit en C , tout comme l' interpréteur Lisp . Emacs Lisp est également appelé Elisp , bien qu'il existe également un dialecte Lisp plus ancien et sans rapport avec ce nom.

Les utilisateurs d'Emacs écrivent généralement du code Emacs Lisp pour personnaliser et étendre Emacs. D'autres options incluent la fonctionnalité Personnaliser qui est dans GNU Emacs depuis la version 20. Lui-même écrit en Emacs Lisp, Customize fournit un ensemble de pages de préférences permettant à l'utilisateur de définir des options et de prévisualiser leur effet dans la session Emacs en cours. Lorsque l'utilisateur enregistre ses modifications, Customize écrit simplement le code Emacs Lisp nécessaire dans le fichier de configuration de l'utilisateur , qui peut être défini sur un fichier spécial que seul Customize utilise, pour éviter la possibilité de modifier le propre fichier de l'utilisateur.

Emacs Lisp peut également fonctionner comme un langage de script , un peu comme le shell Unix Bourne ou Perl , en appelant Emacs en mode batch . De cette façon, il peut être appelé depuis la ligne de commande ou via un fichier exécutable, et ses fonctions d'édition, telles que les tampons et les commandes de mouvement, sont disponibles pour le programme comme en mode normal. Aucune interface utilisateur n'est présentée lorsque Emacs est démarré en mode batch ; il exécute simplement le script transmis et se termine, affichant toute sortie du script.

Par rapport aux autres dialectes Lisp

Emacs Lisp est le plus étroitement lié à Maclisp , avec une influence ultérieure de Common Lisp . Il prend en charge les méthodes de programmation impérative et fonctionnelle . Richard Stallman a choisi Lisp comme langage d'extension pour sa réécriture d'Emacs (l' éditeur et correcteur de texte utilisé à l'origine (TECO) comme langage d'extension) en raison de ses fonctionnalités puissantes, notamment la possibilité de traiter les fonctions comme des données. Bien que la norme Common Lisp n'ait pas encore été formulée, Scheme existait au moment où Stallman réécrivait Gosling Emacs en GNU Emacs. Il a choisi de ne pas l'utiliser en raison de ses performances relativement médiocres sur les postes de travail (par opposition aux mini - ordinateurs qui étaient la maison traditionnelle d'Emacs), et il voulait développer un dialecte qu'il pensait être plus facilement optimisé.

Le dialecte Lisp utilisé dans Emacs diffère sensiblement des dialectes Common Lisp et Scheme plus modernes utilisés pour la programmation d'applications. Une caractéristique importante d'Emacs Lisp est son utilisation par défaut d'une portée dynamique plutôt que lexicale . C'est-à-dire qu'une fonction peut référencer des variables locales dans la portée à partir de laquelle elle est appelée, mais pas dans la portée où elle a été définie. Récemment, des efforts continus ont été déployés pour mettre à jour le code afin d'utiliser la portée lexicale, pour les raisons décrites ci-dessous.

Exemple

Pour comprendre la logique derrière Emacs Lisp, il est important de se rappeler que l'accent est mis sur la fourniture de structures de données et de fonctionnalités spécifiques à la création d'un éditeur de texte polyvalent plutôt que sur l'implémentation d'un langage de programmation à usage général. Par exemple, Emacs Lisp ne peut pas facilement lire un fichier ligne par ligne—le fichier entier doit être lu dans un tampon Emacs. Cependant, Emacs Lisp fournit de nombreuses fonctionnalités pour naviguer et modifier le texte du tampon au niveau d'une phrase, d'un paragraphe ou d'un niveau syntaxique supérieur tel que défini par modes.

Voici un exemple simple d'une extension Emacs écrite en Emacs Lisp. Dans Emacs, la zone d'édition peut être divisée en zones distinctes appelées fenêtres , chacune affichant un tampon différent . Un tampon est une région de texte chargée dans la mémoire d'Emacs (éventuellement à partir d'un fichier) qui peut être enregistrée dans un document texte.

Les utilisateurs peuvent appuyer sur la combinaison de C-x 2 touches par défaut pour ouvrir une nouvelle fenêtre. Cela exécute la fonction Emacs Lisp split-window-below. Normalement, lorsque la nouvelle fenêtre apparaît, elle affiche le même tampon que la précédente. Supposons que nous souhaitions lui faire afficher le prochain tampon disponible. Pour ce faire, l'utilisateur écrit le code Emacs Lisp suivant, soit dans un fichier source Emacs Lisp existant, soit dans un tampon Emacs vide :

(defun my-split-window-func ()
  (interactive)
  (split-window-below)
  (set-window-buffer (next-window) (other-buffer)))

(global-set-key (kbd "C-x 2") #'my-split-window-func)

La première instruction, (defun ...), définit une nouvelle fonction, my-split-window-func, qui appelle split-window-below(l'ancienne fonction de fractionnement de fenêtre), puis indique à la nouvelle fenêtre d'afficher un autre (nouveau) tampon. La deuxième instruction (global-set-key ...)lie à nouveau la séquence de touches "Cx 2" à la nouvelle fonction.

Cela peut également être écrit à l'aide de la fonctionnalité appelée conseil , qui permet à l'utilisateur de créer des enveloppes autour des fonctions existantes au lieu de définir les leurs. Cela a l'avantage de ne pas nécessiter de modification des raccourcis clavier et de fonctionner partout où la fonction d'origine est appelée, ainsi que d'être plus simple à écrire mais l'inconvénient de rendre le débogage plus compliqué. Pour cette raison, les conseils ne sont pas autorisés dans le code source de GNU Emacs, mais si un utilisateur le souhaite, la fonctionnalité de conseils peut être utilisée dans son code pour réimplémenter le code ci-dessus comme suit :

(defadvice split-window-below
  (after my-window-splitting-advice first () activate)
  (set-window-buffer (next-window) (other-buffer)))

Cela indique split-window-belowd'exécuter le code fourni par l'utilisateur chaque fois qu'il est appelé, avant d'exécuter le reste de la fonction. Les conseils peuvent également être spécifiés pour s'exécuter après la fonction d'origine, autour de celle-ci, enveloppant littéralement l'original ou pour exécuter de manière conditionnelle la fonction d'origine en fonction des résultats des conseils.

Emacs 24.4 remplace ce defadvicemécanisme par advice-add, qui se veut plus flexible et plus simple. Les conseils ci-dessus pourraient être réimplémentés en utilisant le nouveau système comme suit :

(defun switch-to-next-window-in-split ()
  (set-window-buffer (next-window) (other-buffer)))

(advice-add 'split-window-below :before #'switch-to-next-window-in-split)

Ces modifications prennent effet dès que le code est évalué . Il n'est pas nécessaire de recompiler, de redémarrer Emacs ou même de ressasser un fichier de configuration. Si le code est enregistré dans un fichier d'initialisation d'Emacs, alors Emacs chargera l'extension au prochain démarrage. Sinon, les modifications doivent être réévaluées manuellement au redémarrage d'Emacs.

Code source

Le code Emacs Lisp est stocké dans les systèmes de fichiers sous forme de fichiers texte , par convention avec le suffixe de nom de fichier " .el". Le fichier d'initialisation de l'utilisateur est une exception, apparaissant souvent comme " .emacs" bien qu'il soit évalué comme n'importe quel code Emacs Lisp. Les versions récentes d'Emacs ("récentes" dans un programme vieux de 40 ans signifiant à peu près n'importe quelle version publiée depuis le milieu des années 1990) chargeront également ~/.emacs.elet ~/.emacs.d/init.el. De plus, les utilisateurs peuvent spécifier n'importe quel fichier à charger en tant que fichier de configuration sur la ligne de commande, ou déclarer explicitement qu'aucun fichier de configuration ne doit être chargé. Lorsque les fichiers sont chargés, un composant interpréteur du programme Emacs lit et analyse les fonctions et les variables, les stockant en mémoire. Ils sont alors disponibles pour d'autres fonctions d'édition, et pour les commandes utilisateur. Les fonctions et variables peuvent être librement modifiées et redéfinies sans redémarrer l'éditeur ni recharger le fichier de configuration.

Afin d'économiser du temps et de l'espace mémoire, la plupart des fonctionnalités d'Emacs ne se chargent que lorsque cela est nécessaire. Chaque ensemble de fonctionnalités optionnelles livrées avec Emacs est implémenté par une collection de code Emacs appelée package ou bibliothèque . Par exemple, il existe une bibliothèque pour mettre en évidence les mots-clés dans le code source du programme et une bibliothèque pour jouer au jeu de Tetris . Chaque bibliothèque est implémentée en utilisant un ou plusieurs fichiers source Emacs Lisp. Les bibliothèques peuvent définir un ou plusieurs modes principaux pour activer et contrôler leur fonction.

Les développeurs Emacs écrivent certaines fonctions en C. Ce sont des primitives , également appelées fonctions intégrées ou subrs . Bien que les primitives puissent être appelées à partir du code Lisp, elles ne peuvent être modifiées qu'en éditant les fichiers source C et en les recompilant. Dans GNU Emacs , les primitives ne sont pas disponibles en tant que bibliothèques externes ; ils font partie de l'exécutable Emacs. Dans XEmacs , le chargement à l'exécution de telles primitives est possible, en utilisant le support du système d'exploitation pour la liaison dynamique . Les fonctions peuvent être écrites en tant que primitives parce qu'elles ont besoin d'accéder à des données externes et à des bibliothèques non disponibles autrement dans Emacs Lisp, ou parce qu'elles sont appelées assez souvent pour que la vitesse comparative de C par rapport à Emacs Lisp fasse une différence intéressante.

Cependant, parce que les erreurs dans le code C peuvent facilement conduire à des violations de segmentation ou à des bogues plus subtils, qui font planter l'éditeur, et parce que l'écriture de code C qui interagit correctement avec le ramasse-miettes Emacs Lisp est sujette aux erreurs, le nombre de fonctions implémentées en tant que primitives est réduit au minimum nécessaire.

Code d'octet

La compilation d'octets peut accélérer l'exécution du code Emacs Lisp. Emacs contient un compilateur qui peut traduire les fichiers source Emacs Lisp en une représentation spéciale appelée bytecode . Les fichiers de bytecode Emacs Lisp ont le suffixe de nom de fichier " .elc". Par rapport aux fichiers source, les fichiers de bytecode se chargent plus rapidement, occupent moins d'espace sur le disque, utilisent moins de mémoire lorsqu'ils sont chargés et s'exécutent plus rapidement.

Le bytecode s'exécute toujours plus lentement que les primitives, mais les fonctions chargées en tant que bytecode peuvent être facilement modifiées et rechargées. De plus, les fichiers de bytecode sont indépendants de la plate-forme. Le code Emacs Lisp standard distribué avec Emacs est chargé en tant que bytecode, bien que les fichiers source correspondants soient généralement également fournis pour la référence de l'utilisateur. Les extensions fournies par l'utilisateur ne sont généralement pas compilées en octets, car elles ne sont ni aussi grandes ni aussi gourmandes en calculs.

Caractéristiques linguistiques

Notamment, le paquet "cl-lib" implémente un sous-ensemble assez important de Common Lisp . Ce paquet remplace un paquet "cl" antérieur, qui écraserait les définitions de fonction Emacs Lisp existantes par des définitions plus similaires à celles trouvées dans Common Lisp. Le paquet "cl-lib", d'autre part, suit de plus près les directives de style Emacs Lisp et préfixe chaque fonction et macro qu'il définit avec "cl-" (par exemple, cl-defun, qui n'entre pas en conflit avec le nom du defun), évitant les changements de comportement inattendus qui pourraient se produire chaque fois que le package "cl" était chargé.

Emacs Lisp (contrairement à d'autres implémentations de Lisp) ne fait pas d'optimisation d'appel de queue . Sans cela, les récursions de queue peuvent éventuellement conduire à un débordement de pile .

La bibliothèque apel aide à écrire du code Emacs Lisp portable, à l'aide du pont de plate-forme polysylabi.

Emacs Lisp est un Lisp-2, ce qui signifie qu'il a un espace de noms de fonction qui est séparé de l'espace de noms qu'il utilise pour les autres variables.

De la portée dynamique à la portée lexicale

Comme MacLisp, Emacs Lisp utilise une portée dynamique , offrant une option statique (ou lexicale) à partir de la version 24. Elle peut être activée en définissant la variable locale du fichier lexical-binding. Avant que cette option ne soit ajoutée, on pouvait utiliser la lexical-letmacro du package "cl" (maintenant obsolète) pour fournir une portée lexicale efficace.

Dans la portée dynamique, si un programmeur déclare une variable dans la portée d'une fonction, elle est disponible pour les sous-programmes appelés à partir de cette fonction. A l'origine, il s'agissait d'une optimisation ; la portée lexicale était encore rare et de performance incertaine. "J'ai demandé à RMS quand il implémentait Emacs lisp pourquoi il avait une portée dynamique et sa réponse exacte était que la portée lexicale était trop inefficace." La portée dynamique visait également à offrir une plus grande flexibilité pour les personnalisations des utilisateurs. Cependant, la portée dynamique présente plusieurs inconvénients. Premièrement, cela peut facilement conduire à des bogues dans les grands programmes, en raison d'interactions involontaires entre les variables de différentes fonctions. Deuxièmement, l'accès aux variables sous portée dynamique est généralement plus lent que sous portée lexicale.

Les références

Liens externes