Elisp et la versatilité d'Emacs

Par abaudouinvegas, 16 mars, 2024

Depuis la fin de la session passée, j'utilise Emacs comme "environnement de développement", puisque, comme notre professeur Lafrance l'a démontré lors de ses cours, Emacs est un éditeur de texte extrêmement versatile, permettant d'utiliser le terminal, faire des connections ssh, naviguer le web, consulter ses mails, créer un agenda, et parfois, d'éditer du texte. Tout cela, et bien plus, est possible puisqu'Emacs est essentiellement un interpréteur Lisp, et c'est ainsi que toutes ces fonctionnalitées peuvent être ajoutées à Emacs.

Puisqu'Emacs fait partie de la suite d'outils GNU, nous pouvons modifier et distribuer Emacs librement, ce qui mène à la création de multiples versions d'Emacs, offrant chacunes leurs propres fonctionnalités. Les deux exemples les plus populaires sont Doom Emacs et Spacemacs. Que ce soit l'intégration de fonctions basées sur la navigation Vim ou la refonte de l'interface afin d'y donner une apparence plus moderne, tout passe par Emacs Lisp.

Emacs Lisp, ou Elips, est un language appartenant à la famille Lisp, conçu spécifiquement pour le développement et l'extension d'Emacs. Comme plusieurs programmes éditables, Emacs a un fichier de configuration permettant aux utilisateurs d'y insérer ce qu'ils veulent; c'est à l'intérieur du dossier emacs (.emacs/ , .emacs.d/ et autres variations) que l'on peut trouver le fichier init.el (el étant l'extension des scripts écrits en Elisp). Ici, nous pourrons ajouter toutes les extensions et fonctions que nous voulons. 

 Par défaut, il se peut que ce fichier n'existe pas, et il faura donc le créer dans le dossier approprié. Une fois créé, nous pouvons commencer à modifier notre version d'Emacs.

Les changements les plus faciles à faire sont ceux liés aux variables intégrées dans Emacs. Nous pourrions donc enlever certains éléments graphiques d'Emacs afin de conserver une apparence plus aérée :

;; Enlève l'écran initial
(setq inhibit-startup-message t)

;; Désactive plusieurs outils
(tool-bar-mode -1)
(menu-bar-mode -1)
(scroll-bar-mode -1) 

Dans la première partie, l'on assigne t (true) à la variable inhibit-startup-message. Cette variable est utilisée par Emacs afin de déterminer si l'écran initial devrait être affiché. Ensuite, nous appellons 3 fonctions consécutives, leur passant en paramètre -1, ce qui a comme effet de cacher chaque élément correspondant.

Il est aussi possible d'ajouter des extensions (communément appellées 'packages') ainsi :

(use-package nom-extension
    :ensure t)

Bien qu'un peu de configuration soit nécessaire, l'on peut se servir de la fonction use-package pour installer des outils provenant de dépots Git.

Finalement, je vais vous démontrer la première fonction Elisp que j'ai écrite il y a quelques temps afin de régler un problème que j'avais. Je vais d'abord faire une petite mise en contexte. 

Un des avantages d'Emacs est le fait que l'on puisse rouler un Daemon d'Emacs, ce qui fait en sorte qu'il y a un serveur Emacs qui roule continuellement dans l'arrière-plan. Cela à comme effet de raccourcir considérablement les temps de chargements en ouvrant l'application, et de sauvegarder nos fenêtres ouverte lors d'une session précédente (il faut noter que ce serait techniquement la même session vu que le serveur ne serait pas éteint). C'est à cause de cette conservation d'état que j'ai fait face à un petit problème :  chaque fois que j'ouvrais un terminal virtuel à l'aide du client Emacs (et non une instance unique d'Emacs), je recevais la même session de terminal que j'utilisait déjà. Malheureusement, cela n'est clairement pas idéal quand on souhaite avoir plusieurs terminaux de ligne de commande ouverts en même temps, que ce soit pour naviguer ou pour faire des connections SSH. La solution que j'ai trouvée pour remédier à ce problème fût de créer une fonction qui ouvre le terminal et lui assigne un nom unique, ce qui sépare chaque instance, me permettant tout de même d'accéder aux instances précédantes par leur nom de buffer. J'ai donc fait la fonction suivante : 

(defvar vterm-buffer-counter 0
 "Compteur permettant de générer des noms uniques pour les buffers vterm.")

(defun spawn-vterm ()
 "Crée un buffer vterm avec un identifiant unique"
 (interactive)
 (setq vterm-buffer-counter (1+ vterm-buffer-counter))
 (let ((buffer-name (format "*vterm-%d*" vterm-buffer-counter)))
   (vterm buffer-name)))
(global-set-key (kbd "C-c s") 'spawn-vterm)
 

Je déclare d'abord une variable qui sert de compteur afin d'avoir des buffers numérotés et je crée ensuite une fonction qui crée des buffers vterm et les renomme en se servant de la variable précédente après l'avoir incrémenté de 1.
Je déclare finalement un raccourci pour accéder cette fonction rapidement. Évidemment, cette solution est loin d'être élégante et j'adresserait ce problème différemment avec ce que j'ai appris au cours des dernières semaines, mais je crois que c'est tout de même un example concret de modifications que l'on peut apporter au code pour subvenir à nos besoins spécifiques. Je trouve que c'est une chose formidable que de pouvoir modifier un programme en toute liberté.

Dans cet article, nous avons vu des applications concrète de Lisp et nous avons exploré quelques possibilités de personnalisation à l'intérieur d'Emacs. Pour les étudiants qui utilisent Emacs, j'espère vous avoir inspirés à apprendre ce language et à améliorer par vous même les fonctionnalités de votre éditeur, et pour ceux qui ne l'utilisent pas encore, j'espère avoir éclairci un peu ce qui fait en sorte qu'Emacs est un éditeur puissant.

Extra : une vidéo sur Emacs Lisp entre un chercheur de l'UdeM et un Chef d'entreprise allemand

Références

Étiquettes

Commentaires3

aouzou

il y a 11 mois 1 semaine

Bonjour Alexandre,

merci pour cet article très détaillé sur Emacs Lisp. Vous avez mentionné votre expérience avec Emacs et sa puissante capacité de personnalisation. Cependant, je me demande quelles ont été vos principales réticences ou hésitations à franchir le pas et à commencer à utiliser Emacs.

Merci