Utiliser Emacs dans les années 2020.🔗
- Introduction
- Mon contexte
- Quelle version d'Emacs utiliser ?
- Si vous débutez avec Emacs
- Le minimum à lire pour comprendre
- Utiliser use-package pour faciliter la configuration d'Emacs
- Faciliter la vie sous Emacs
- Le contexte
- Découvrir les combinaisons de touches avec which-key
- Faciliter la recherche de commandes avec Ivy
- Configurer Emacs en mode pratique
- Faciliter la sélection et la frappe
- Vérification orthographique et grammaticale
- Améliorer l'aspect visuel d'Emacs
- Choisir une bonne police
- all-the-icons
- Modifier le thème principal
- Utiliser des onglets
- Autocomplétion avec Company
- Editeur de Markdown
- Gestion de projets
- Faire du dev sous Emacs
- Principes de LSP
- Faire du dev python
- Introduction
- Choisir un serveur de langage Python
- Configuration de pylsp
- Améliorer Projectile
- Conclusions
- Conclusions
Introduction
J'utilise Emacs depuis pratiquement quinze ans. J'ai testé plein d'autres éditeurs au cours de ces années, mais je suis toujours revenu à Emacs. Au début, c'était pour des raisons éthiques: Emacs c'était l'éditeur GNU de référence, codé par RMS en personne. Et puis avec le temps, je me suis mis à l'utiliser comme un programme normal et courant. Mais ça c'était avant 2020 !
J'y ai passé pas mal d'heures à le configurer finement. Pourtant pendant des années, j'ai fait ce qu'il ne fallait pas faire: essayer de copier-coller des morceaux de configuration sans vraiment essayer de comprendre à quoi ça servait. Après une configuration stagnante, j'ai ajouté quelques éléments qui m'ont vraiment permis d'améliorer le comportement d'Emacs par rapport à mes besoins.
Après 15 années à être resté fidèle à cet éditeur, je crois que maintenant c'est foutu: vu le temps que j'y ai investi, je ne pourrais jamais en changer. Car, en 2022, j'ai vraiment poussé la barre d'Emacs plus loin.
Dans cet article, que je ne veux pas de référence parce qu'Emacs, ça nous dépasse tous, je vais vous présenter les principaux éléments de ma configuration. Vous pourrez vous en inspirer pour creuser les sujets et définir la configuration adaptée à vos besoins.
Mon contexte
- Je suis sous Debian stable ou testing (suivant les moments de l'année).
- D'une manière générale, j'essaye d'utiliser les paquets natifs de la distribution plutôt que de tout charger depuis ELPA/MELPA.
- La seule exception à cette règle c'est si le paquet Debian fait face à un réel problème de comportement ou un bug corrigé depuis.
- Personnellement, je gère la configuration d'Emacs en suivant les recommandations XDG, à savoir, utiliser
~/.config/emacs
. C'est comme ça que toutes mes configurations de logiciels sont faits et comme Emacs gère ça, autant l'adopter. J'ai choisi de tout mettre dans un seul fichier de configuration (.config/emacs/init.el
) plutôt que d'éparpiller tout avec des includes (par fainéantise, je dois l'avouer).
Quelle version d'Emacs utiliser ?
Avant, j'utilisais la version “-nox” d'Emacs qui ne fonctionne qu'en mode texte, dans un terminal. Pendant 10 ans, je n'ai eu aucun problème avec cette version. C'était même assez intéressant car j'avais une configuration ultra-stable et visuellement identique que je sois sur une station de travail graphique ou en pur mode texte. Néanmoins emacs-nox pose de réels soucis lorsque vous devez utiliser des choses réservées à un mode graphique. Par exemple, il sera impossible de choisir une police différente de celle du terminal qui englobe Emacs, ou bien d'avoir plusieurs polices différentes sur le même écran.
Dans certains cas, ça ne pose pas de problèmes réels et avec un peu de temps et d'adaptation de sa configuration, j'aurais très bien pu rester en mode texte pur. Mais, des choses comme la gestion des onglets ou l'utilisation d'icônes se sont révélées assez intéressantes pour me faire convertir à l'utilisation d'Emacs avec le moteur graphique sous GTK.
Si vous débutez avec Emacs
On ne va pas se le cacher, Emacs ça demande de l'investissement de temps de cerveau disponible. Si vous n'avez pas au moins une dizaine d'heures à dédier à son apprentissage, à la lecture d'une bonne partie du manuel, à la compréhension minimale d'eLisp, alors ça ne sert à rien. Vous finirez ultra-frustrés et vous jetterez Emacs par la fenêtre en disant que c'est de la merde.
Vous allez me dire, pourquoi consacrer autant de temps à un simple éditeur de texte ? Alors d'abord, Emacs n'est pas un simple éditeur de texte. C'est un truc qui fait tout si vous le configurez bien ou utilisez les bons paquets. À la limite, il pourrait remplacer un tiling window manager et vous permettre de tout faire dedans. Ça peut même remplacer un OS complet. On est donc (vraiment très) loin du notepad de Microsoft.
Ensuite, Emacs suppose que toute l'interaction entre vous et lui passe par un clavier. De fait, vous allez devoir entraîner votre cerveau et vos doigts à apprendre et maîtriser des raccourcis-claviers. Vous pouvez certes utiliser la souris, mais vous allez finir par trouver ça pas efficace.
Enfin, Emacs utilise un langage de dev pour gérer sa configuration et une partie de son fonctionnement: Lisp (en fait une version spéciale de Lisp pour Emacs: Emacs Lisp ou eLisp) ! De fait, on est loin du fichier .ini
de base et donc, dès le départ, Emacs semble compliqué à configurer, même pour un administrateur système qui en a déjà vu d'autres.
L'intérêt de Lisp, c'est qu'on peut vraiment faire ce qu'on veut. De fait, Emacs est souvent vu comme un environnement Lisp qui dispose d'un bon éditeur de texte et ça se voit, dans ce mode de configuration. De plus, Lisp permet de pallier au fait que, bien souvent, dans des fichiers .ini
, on a du mal à gérer les conditions ou les cas de configuration sur des situations variables.
Tout ça fait qu'il faut y passer du temps parce que ce n'est pas un simple traitement de texte.
Le minimum à lire pour comprendre
Bon, on ne va pas se mentir, apprendre à utiliser Emacs et surtout comprendre comment ça marche, ça prend du temps et ça demande de travailler avec la documentation.
Ça tombe bien, elle est bien faite. Si vous êtes débutants, je vous invite à lire les éléments suivants:
- Lisez le tutoriel dans son intégralité.
- Lisez le manuel d'Emacs au moins jusqu'au Modes.
- Lisez l'introduction à eLisp le plus possible, voir intégralement.
- Lisez quelques pages du manuel d'eLisp.
- Apprenez à vous servir du gestionnaire de paquets.
- Enfin, lisez quelques éléments sur le fichier de configurationd'Emacs.
Une fois que vous aurez fait ça, vous pourrez lire la suite de cet article sans trop de problème. Encore une fois, si vous n'avez pas le temps, alors passez votre chemin et utilisez un autre logiciel.
Utiliser use-package pour faciliter la configuration d'Emacs
Bon, Emacs à configurer, ce n'est pas si compliqué mais, à l'usage, je trouve que Lisp, c'est assez moche en termes de rendu visuel. On finit par en avoir partout et ça ne pousse pas à regrouper ça de manière logique. Comme on va ajouter de nombreux packages à Emacs, notre fichier de configuration va devenir touffu.
Une bonne pratique (enfin que moi je trouve bonne), c'est d'utiliser le package use-package qui permet de configurer les packages sous forme déclarative et normée. À l'usage, ça force aussi à rassembler la configuration d'un package au même endroit et c'est plus sain.
use-package est disponible nativement sous Debian et cette version ne pose pas de problème:
# apt install elpa-use-package
Pour utiliser use-package, c'est simple: il suffit de dire qu'on en a besoin absolument et placer ça, après la commande package-initialize
:
(require 'use-package)
À partir de là, en dehors des trucs qui ne sont pas gérés spécifiquement par des modes Emacs (genre l'affichage de l'écran d'accueil, la configuration globale), nous allons utiliser (use-package package) dès que possible.
Faciliter la vie sous Emacs
Le contexte
Emacs, c'est vraiment complet: tout est personnalisable, il y a même un langage dédié basé sur Lisp pour gérer les cas les plus tordus qui soient. Néanmoins, un grand pouvoir implique souvent une grande complexité. Si vous allez vous en sortir assez facilement avec les commandes que vous utilisez souvent, vous allez en revanche galérer pour celles que vous n'utilisez pas tout le temps.
Et puis, il faut toujours rester humble par rapport à Emacs. Il y a tellement de paquets, inclus ou non dans le logiciel qu'il est pratiquement impossible d'avoir une connaissance absolue de toutes les commandes, toutes les variables, toutes les combinaisons de touches. Donc utilisez des aides pour se faciliter la vie, c'est bien.
Pour faire ça, on va installer quelques paquets bien utiles.
Découvrir les combinaisons de touches avec which-key
Le paquet Emacs which-key permet de présenter une liste de raccourcis clavier à partir du moment où vous avez commencé à taper un raccourci de groupe de commandes. Par exemple, si vous tapez C-x
et que vous attendez quelques millisecondes, le minibuffer s'enrichit de la liste des raccourcis clavier qui commencent par C-x
avec une description simple des commandes.
C'est très pratique pour un certain nombre de commandes que vous utilisez peu souvent et pour lesquelles il faudrait que vous re-listiez tous les bindings claviers.
Voici ma configuration au format use-package:
;; Configuration de which-key ;; par le paquet Debian: elpa-which-key (use-package which-key :diminish which-key-mode :init (setq which-key-sort-uppercase-first nil max-mini-window-height 15) ;; On va utiliser une fenêtre dédiée plutôt que le minibuffer (which-key-setup-side-window-bottom) ;; On l'active partout, tout le temps (which-key-mode t) )
Franchement, aujourd'hui, je ne pourrais plus m'en passer.
Faciliter la recherche de commandes avec Ivy
Ivy et ses compagnons counsel et swiper se proposent de faciliter la recherche de commandes en tout genre et aussi propose de meilleurs outils de base que ceux d'Emacs pour faire ça. Ivy s'occupe de la présentation principalement et counsel et swiper apportent de meilleurs outils, comme une recherche plus ciblée et facilitée.
Par exemple counsel-M-x
permet de rechercher plus facilement des commandes ou encore, swiper-isearch
est un remplaçant sympa de isearch, car il vous affiche les lignes qui correspondent et vous permet de les sélectionner rapidement avec les flèches, pour aller directement sur ce que vous chercher sans avoir à taper une foutue regexp. Ou encore ivy-buffer
qui permet presque de se passer de recentf, car il liste aussi dans les buffers, les fichiers que vous avez récemment ouverts.
Debian Bullseye propose les dernières versions de ces paquets déjà éprouvés depuis quelques années alors, autant en profiter directement:
# apt install elpa-ivy elpa-counsel elpa-swiper
Ensuite pour la configuration, je me suis contenté de la base et de quelques raccourcis-clavier pour remplacer les principales commandes d'Emacs:
(use-package ivy :config (setq ivy-use-virtual-buffers t ivy-count-format "(%d/%d) ") (ivy-mode 1) :bind (:map global-map ( ("C-s" . swiper-isearch) ("M-x" . counsel-M-x) ("C-x C-f" . counsel-find-file) ("M-y" . counsel-yank-pop) ("<f1> f" . counsel-describe-function) ("<f1> v" . counsel-describe-variable) ("<f1> l" . counsel-find-library) ("<f2> i" . counsel-info-lookup-symbol) ("<f2> u" . counsel-unicode-char) ("<f2> j" . counsel-set-variable) ("C-x b" . ivy-switch-buffer) ("C-c v" . ivy-push-view) ("C-c V" . ivy-pop-view))) )
Dans ma pratique, cette configuration de base me suffit largement mais sachez que vous pouvez, comme d'habitude, customiser encore plus loin. Nous n'avons fait qu'effleurer la surface.
Configurer Emacs en mode pratique
Cette partie englobe quelques éléments de configuration qui facilitent la vie au quotidien sous Emacs. J'ai vu ces éléments de conf tellement reproduits dans les dotfiles de conf visibles publiquement sur Internet que je pense que ce sont de bons comportements par défaut:
;; Configuration générale ;; On affiche les colonnes dans la modeline (column-number-mode) ;; Par défaut, on coupe la ligne à 80 caractères (setq fill-column 80) ;; On enlève la barre d'outil en mode graphique (tool-bar-mode 0) ;; Idem pour les scrollbars (scroll-bar-mode 0) ;; On met en évidence la ligne en cours (global-hl-line-mode +1) ;; On efface la sélection lorsqu'on appui sur une touche (delete-selection-mode +1) ;; On ne demande pas confirmation pour tuer les sous-processus en sortant d'Emacs (setq confirm-kill-processes nil) ;; On affiche les limites du buffer dans la fringe line (setq-default indicate-buffer-boundaries 'left) ;; On met en évidence les lignes vides (setq-default indicate-empty-lines +1) ;; On déplace les fichiers de sauvegarde dans /tmp (setq backup-directory-alist `((".*" . ,temporary-file-directory))) (setq auto-save-file-name-transforms `((".*" ,temporary-file-directory t))) ;; Encodage en UTF-8 (set-terminal-coding-system 'utf-8) (set-keyboard-coding-system 'utf-8) (set-language-environment "UTF-8") (prefer-coding-system 'utf-8) ;; Taper y ou n à la place de yes ou no (fset 'yes-or-no-p 'y-or-n-p) ;; On enlève l'écran d'accueil (setq inhibit-splash-screen t)
C'est commenté pour la compréhension.
Faciliter la sélection et la frappe
Il existe un paquet assez sympa qui permet de sélectionner rapidement et de manière incrémentale une région d'un buffer. C'est expand-region.
Il est packagé dans Debian et comme je n'utilise que deux de ses fonctions, c'est celui que j'utilise avec la configuration suivante:
# apt install elpa-expand-region
;; Utilisation de expand-region ;; par le paquet Debian: elpa-expand-region (use-package expand-region :ensure nil ;; Globalement, j'utilise que deux raccourcis :bind ("C-=" . er/expand-region) ("C--" . er/contract-region) )
Ensuite, un simple C-=
ou C--
pour augmenter ce qui est sélectionné. Ça permet de sélectionner rapidement des zones de texte contiguës.
Vérification orthographique et grammaticale
J'utilise Emacs aussi pour écrire du texte, genre, cet article. Mon français et ma maîtrise d'un clavier sont plutôt bons mais parfois, comme tout le monde, je fais des erreurs. Donc, comme tout le monde, il me faut un correcteur orthographique et grammatical aussi.
Pour la correction orthographique, j'utilise flyspell. C'est un module intégré à Emacs qui s'occupe d'utiliser un programme externe de vérification d'orthographe. Pour ma part, j'utilise hunspell pour ça, c'est aussi ce qui est utilisé par LibreOffice. Il faut à la fois le programme hunspell et également au moins un dictionnaire. Sous Debian, ça prend la forme de la commande suivante pour installer aussi un dictionnaire français:
# apt install hunspell hunspell-fr
Ensuite, il reste à déployer flyspell sous Emacs. Pour ma part, j'indique simplement que je souhaite utiliser hunspell comme programme de vérification orthographique, le dictionnaire qu'on vient d'installer par défaut. Malgré ça, il manque un truc natif à flyspell: le changement de l'interface de correction orthographique. Pour gérer ça, j'utilise le paquet flyspell-correct qui permet de choisir l'interface de correction. Pour ma part, j'utilise tout simplement ivy, qu'on a vu avant. En termes de configuration, ça donne ça:
;; Correction orthographique avec flyspell (use-package flyspell :config (setq ispell-program-name (executable-find "hunspell") ispell-really-hunspell t ispell-dictionary "fr_FR") ) (use-package flyspell-correct :ensure t :after flyspell :bind (:map flyspell-mode-map ("C-;" . flyspell-correct-at-point)) ) (use-package flyspell-correct-ivy :ensure t :demand t :after flyspell-correct )
Parfois, vous pouvez vouloir sauvegarder un mot dans votre dictionnaire personnel. En mode ivy, activez l'aide Hydra (? ou C-o) puis les actions et choisissez Save.
Vous pouvez penser aussi à virer aspell, car vous n'en aurez plus besoin (du moins sous Emacs mais c'est aussi vrai dans la majorité des cas):
# apt purge aspell
En ce qui concerne la grammaire, j'avais été plutôt bien surpris du fonctionnement de grammalecte sous LibreOffice. En regardant, j'ai trouvé flycheck-grammalecte qui se propose d'utiliser grammalecte (en mode «serveur») avec flycheck. Je vous conseille d'utiliser la version sur Melpa (unstable) qui n'aura pas de problème pour détecter votre version de Python3.
La configuration est assez simple:
;; Correction grammaticale (use-package flycheck-grammalecte :ensure t :after flycheck :init ;; Par défaut, grammalecte est très exigeant, je le suis moins (setq flycheck-grammalecte-report-apos nil flycheck-grammalecte-report-esp nil flycheck-grammalecte-report-nbsp nil) :config (flycheck-grammalecte-setup) )
Ça s'occupe de récupérer le paquet flycheck-grammalecte sur Melpa, de l'installer et de le lancer. Au premier lancement, ça vous demande de télécharger le «serveur» grammalecte (depuis le site officiel).
En gros, quand flycheck se lance, le module grammalecte se lance également.
Améliorer l'aspect visuel d'Emacs
Choisir une bonne police
Vous allez utiliser Emacs pour tout ce qui concerne du texte mais aussi du code. Vous allez lire/écrire pendant des heures, plusieurs fois par jour. Alors, il est grand temps pour vous de tester la bonne police de caractères, celle qui sera adaptée à vos besoins.
Avant d'aller plus loin, vous pouvez utiliser un départageur de polices de caractères pour trouver celle que vous préférez. Moi, j'ai utilisé le site web coding font et c'est la police Cousine qui a trouvé grâce à mes yeux. Heureusement, elle est packagée dans Debian:
# apt install fonts-croscore
;; Police par défaut: Cousine (set-face-attribute 'default nil :font "Cousine 11" ) (set-frame-font "Cousine 11" nil t)
all-the-icons
all-the-icons est un paquet qui installe de nombreuses icônes. Ces icônes peuvent ensuite être déployées dans d'autres paquets (treemacs mais aussi dired).
Ne pas oublier de lancer la commande Emacs all-the-icons-install-fonts
à la fin du déploiement du package Emacs, sinon toutes les icônes ne seront pas activées.
Pour ma part, ma configuration est simple et j'utilise all-the-icons dans dired, treemacs et Ivy:
;; Gestion des icônes par all-the-icons (use-package all-the-icons :ensure t ) ;; Ajout des icônes pour dired (use-package all-the-icons-dired :ensure t :hook (dired-mode . all-the-icons-dired-mode) ) ;; Ajout des icônes pour ivy (use-package all-the-icons-ivy :ensure t :init (all-the-icons-ivy-setup) )
Modifier le thème principal
Bon, je dois reconnaître que le thème principal d'Emacs n'est pas super beau. À côté de ça, quand on voit les démos ou les captures d'écrans de Spacemacs et de Doom Emacs, on bave ! Oui parce qu'un bon thème ça fait du bien au moral et ça donne envie d'utiliser Emacs.
Et puis aussi parce qu'un thème Emacs sympathique permet de se faire moins mal aux yeux, un outil principal du développeur. Pour ma part, j'ai choisi le thème dracula que j'utilise un peu partout depuis plusieurs années.
Pour le déployer facilement, je me contente d'utiliser le package Emacs doom-themes avec la configuration suivante:
;; Configuration du thème doom (use-package doom-themes :ensure t :config ;; Global settings (defaults) (setq doom-themes-enable-bold t ; if nil, bold is universally disabled doom-themes-enable-italic t ; if nil, italics is universally disabled doom-dracula-brighter-modeline t ; modeline plus visible. ) (load-theme 'doom-dracula t) ;; Enable flashing mode-line on errors (doom-themes-visual-bell-config) ;; Corrects (and improves) org-mode's native fontification. (doom-themes-org-config) ;; doom-theme for treemacs (setq doom-themes-treemacs-theme "doom-colors" doom-themes-treemacs-bitmap-indicator-width 14) (doom-themes-treemacs-config) (setq whitespace-style '(face tabs tab-mark trailing)) (setq whitespace-display-mappings '((tab-mark 9 [124 9] [92 9]))) )
Utiliser des onglets
Depuis la version 27 d'Emacs, il existe plusieurs éléments qui permettent de mettre en place une barre d'onglets comme tab-bar-mode ou tab-line-mode. Néanmoins, il y manque les icônes, l'intégration avec d'autres packages, la gestion des projets, etc.
Le meilleur paquet que j'ai trouvé pour avoir un rendu comme dans VSCode se nomme centaur-tabs. C'est un package assez cool qui fait des choses intéressantes, notamment en ce qui concerne le regroupement des onglets, l'affichage sympa des onglets, la visualisation des onglets modifiés, etc.
Je vous conseille d'installer la version située sur Melpa-stable, elle fait bien le job. Ma configuration est la suivante:
;; Configuration des tabs avec centaur-tabs (use-package centaur-tabs :demand :init (setq centaur-tabs-style "rounded" centaur-tabs-set-bar 'left centaur-tabs-height 24 centaur-tabs-cycle-scope 'groups centaur-tabs-show-navigation-buttons t centaur-tabs-set-icons t) (defun centaur-tabs-buffer-groups () "`centaur-tabs-buffer-groups' control buffers' group rules. Group centaur-tabs with mode if buffer is derived from `eshell-mode' `emacs-lisp-mode' `dired-mode' `org-mode' `magit-mode'. All buffer name start with * will group to \"Emacs\". Other buffer group by `centaur-tabs-get-group-name' with project name." (list (cond ((or (string-equal "*" (substring (buffer-name) 0 1)) (memq major-mode '(magit-process-mode magit-status-mode magit-diff-mode magit-log-mode magit-file-mode magit-blob-mode magit-blame-mode ))) "Emacs") ((derived-mode-p 'prog-mode) "Editing") ((derived-mode-p 'dired-mode) "Dired") ((derived-mode-p 'vterm-mode) "Terminal") ((memq major-mode '(helpful-mode help-mode)) "Help") ((memq major-mode '(org-mode org-agenda-clockreport-mode org-src-mode org-agenda-mode org-beamer-mode org-indent-mode org-bullets-mode org-cdlatex-mode org-agenda-log-mode diary-mode)) "OrgMode") (t (centaur-tabs-get-group-name (current-buffer)))))) :hook (recentf-mode . centaur-tabs-local-mode) (dashboard-mode . centaur-tabs-local-mode) (term-mode . centaur-tabs-local-mode) (calendar-mode . centaur-tabs-local-mode) (org-agenda-mode . centaur-tabs-local-mode) (helpful-mode . centaur-tabs-local-mode) :config (centaur-tabs-headline-match) (centaur-tabs-group-by-projectile-project) (centaur-tabs-mode t) :bind ("C-<prior>" . centaur-tabs-backward) ("C-<next>" . centaur-tabs-forward) )
En dehors des trucs visuels, j'ai un peu modifié la fonction qui regroupe les onglets entre eux pour l'adapter à mes besoins, notamment en plaçant les terminaux vterm à part.
Parfois, dans certains modes, je n'ai pas envie d'activer centaur-tabs. C'est le cas de recentf, ça sert à trouver des fichiers, pas la peine de le foutre dans un onglet. Pour ça, j'ajoute un hook dans le mode en question:
:hook (recentf-dialog-mode . centaur-tabs-local-mode)
A l'usage, centaur-tabs permet de savoir quels sont les fichiers déjà ouverts dans un projet, de manière visuelle. En plus de ça, c'est très visuel et utilisable à la souris si on a oublié les commandes pour basculer d'un onglet à l'autre ou pour revenir sur un onglet particulier, situé plus loin. On est loin d'un gadget, ça augmente très légèrement la productivité et ça rassure en étant simple d'utilisation. Je ne peux plus m'en passer.
Autocomplétion avec Company
Company est un mode mineur qui permet l'autocomplétion sur un peu tout dans Emacs. On peut s'en servir dans le minibuffer ou dans le texte directement. C'est bien de l'avoir, ça permet de faire de l'autocomplétion dans Emacs de manière simple et efficace.
D'ailleurs, en règle générale, Company peut s'adapter au mode majeur dans lequel vous êtes.
La version Debian fait le job car company est un paquet maintenant stable. On peut l'installer facilement:
# apt install elpa-company
Dans init.el:
;; Company (use-package company :diminish company-mode :config (global-company-mode) )
Editeur de Markdown
markdown-mode est un paquet Emacs qui ajoute la prise en charge des fichiers markdown. C'est plutôt bien fait et facile à prendre en main. Ça permet d'éditer des fichiers markdown avec un meilleur visuel. Comme j'écris beaucoup de markdown, je l'ai forcément ajouté.
C'est packagé dans Debian:
# apt install elpa-markdown-mode
On peut le déployer assez simplement:
(use-package markdown-mode :ensure t :commands (markdown-mode gfm-mode) :mode (("README\\.md\\'" . gfm-mode) ("\\.md\\'" . markdown-mode) ("\\.markdown\\'" . markdown-mode)) :init (setq markdown-command "markdown" markdown-asymmetric-header 1 markdown-header-scaling 1) :hook (markdown-mode . auto-fill-mode) )
Gestion de projets
Introduction
En règle générale, mon utilisation d'Emacs se fait par projets. Pour moi, un projet, c'est un répertoire, pratiquement systématiquement foutu dans un dépôt git à part entière. C'est comme ça que je regroupe les fichiers communs et constitutifs d'un projet. Par défaut, Emacs se tape complètement de cette organisation, sauf si vous avez des choses dans git. On va donc combler un peu ce manque avec les paquets projectile, treemacs et dashboard.
Projectile
Projectile est un paquet permettant la gestion de projets sous forme d'arborescence. Par projets on entend surtout projet de développement informatique (source code), même s'il y a sans doute des modes pour les projets de fichiers texte.
Projectile est un paquet qui a déjà dix ans en 2021. Il a été créé pour faciliter la vie d'un développeur sur un projet pour:
- naviguer dans l'arborescence du projet.
- compiler/packager/tester un projet en une commande.
- se balader dans les tags d'un projet.
- Faire de la recherche dans un projet (rgrep mais sur les limites de l'arborescence du projet).
- Faire du remplacement de chaîne de caractères dans tout le projet.
- Passer du fichier de déclaration (.h ou .hxx) au fichier source (.c ou .cxx) en une commande clavier.
- etc.
Dans la pratique, j'utilise essentiellement projectile pour son interfaçage avec treemacs et company. Pour le reste, je dois avouer que j'utilise essentiellement les commandes de navigation de fichiers dans un projet, pour aller plus vite. Néanmoins Treemacs fait très bien le job visuellement aussi. Centaur-tabs me permet également de basculer au moins aussi vite que Projectile sur les buffers ouverts de Projectile. Et puis, lsp-mode est quand même plus pertinent pour se balader de définitions en références ou faire du renommage en masse.
Mais surtout, pour mes projets Python, j'utilise généralement pytest comme élément de gestion des tests unitaires et c'est là que Projectile se révèle intéressant: on peut tester tout le projet avec une seule commande C-p P
dans mon cas. Ça lance un terminal et on a le rendu direct, sans même ouvrir de shell. C'est une fonctionnalité très pratique.
Bien entendu, c'est la même chose pour mes projets C/C++ mais avec l'option de pouvoir compiler en une commande. Et ça, c'est bien fait quand même.
Il existe également un paquet officiel intégré à Emacs (project.el) mais il n'a pas autant de fonctionnalités. Et surtout, moi ce qui m'intéresse, c'est les tests et la compilation.
Le paquet Debian de projectile est un poil ancien (v2.1 alors que la version stable est en v2.5) donc j'utilise celui de Melpa stable.
Pour résumer, voici ma configuration de projectile:
;; Configuration de base de projectile (use-package projectile :ensure t ;; Sur un petit écran, projectile bouffe un peu de modeline :diminish projectile-mode :init (setq projectile-sort-order 'recentf projectile-enable-caching t projectile-enable-cmake-presets t projectile-completion-system 'ivy) ;; Je binde tout ça avec C-p, pas standard mais pratique pour s'en souvenir :bind (:map projectile-mode-map ("C-p" . projectile-command-map)) :config ;; J'ajoute mon type de projet principal sous Python (projectile-register-project-type 'python3-pytest '("pytest.ini" "setup.py") ;;:project-file "setup.py" :compile "python3 setup.py build" :test "python3 -m pytest" :run "python3 -m gis2fg" :test-dir "tests" :test-prefix "test_" :test-suffix "_test.py") ;; on active projectile tout le temps (projectile-mode +1) )
Sans révolutionner Emacs, projectile c'est quand même pratique pour le développeur. L'essayer, c'est l'adopter.
Treemacs
Treemacs propose d'ajouter un panneau d'exploration de fichiers à Emacs. Il gère ça sous forme de Workspaces qui sont des espaces virtuels dans lesquels on peut mettre un ou plusieurs projets, projets qui contiennent eux-mêmes une arborescence de fichiers. Le tout est bien sûr compatible avec Projectile, présenté juste au-dessus et ce, nativement.
Avec Treemacs, Emacs ressemble plus à VSCode qu'à autre chose:
C'est packagé dans Debian, mais il manque des choses et la version est un poil ancienne, donc j'utilise la version proposée sur le dépôt Melpa.
L'activation par use-packages se fait simplement:
;; Configuration de Treemacs (use-package treemacs :ensure t :defer t :after (treemacs-all-the-icons) :hook (treemacs-mode . no_code_mode) ;; J'utilise la touche dans le coin haut à droite du clavier ;; pour afficher la fenêtre de treemacs :bind (("M-²" . treemacs-select-window) ("M-œ" . treemacs-select-window)) :config (setq treemacs-width 20 treemacs-indentation '(4 px) treemacs-is-never-other-window t treemacs-width-is-initially-locked nil treemacs-space-between-root-nodes nil treemacs-collapse-dirs 4 treemacs-text-scale -1) ;;(treemacs-indent-guide-mode) (treemacs-resize-icons 14) (treemacs-follow-mode t) (treemacs-tag-follow-mode t) (treemacs-filewatch-mode t) (treemacs-fringe-indicator-mode 'always) (treemacs-hide-gitignored-files-mode nil) (treemacs-load-theme "all-the-icons") )
Un truc sympathique avec Treemacs, c'est l'utilisation des tags ou des symboles dans un fichier. Si vous êtes dans un fichier de code source, vous pourrez afficher en dessous du fichier ouvert dans l'arbre Treemacs, la liste (en fait l'arbre) de tous les symboles rencontrés dans le fichier. Cela vous permettra de naviguer facilement ou d'avoir une espèce de table des matières à disposition. C'est très pratique, même dans les fichiers markdown ou Org ou les symboles sont les titres des chapitres.
Voilà, à part ça, Treemacs c'est essentiellement une aide visuelle. Sur des projets un peu touffus où vous avez beaucoup de répertoires et de fichiers de code, c'est vraiment pratique. C'est aussi très utile lorsque vous souhaitez découvrir le contenu d'un projet. Avec dired (l'explorateur de fichiers d'Emacs), c'est faisable mais moins dynamique et il faut ouvrir beaucoup de buffers pour ça.
Enfin, le fait d'avoir les tags qui s'affichent rapidement est un vrai plus pour se repérer dans un fichier de code un peu épais. Le fait aussi qu'il soit dynamique (on se balade dans le fichier, ça bouge au niveau des tags, on se balade dans un autre fichier, ça se positionne sur le bon fichier) est un vrai plus pour se repérer, savoir où on est. Et ça, c'est assez important, surtout sous Emacs qui a tendance à tout foutre dans des buffers visuellement masqués (c'est aussi la force d'Emacs: présenter uniquement ce qui est utile) avec lesquels on a parfois du mal à savoir où se situer.
On le verra un peu plus tard, mais Treemacs peut aussi s'interfacer avec Magit pour vous permettre de voir ce qui est commité ou pas dans votre arbre/projet.
En conclusions, Treemacs c'est vraiment un bon assistant visuel. Sa configuration est très souple ce qui occasionne parfois des frictions suivant ce que vous voulez en faire mais franchement, je ne pourrais plus m'en passer.
Dashboard
Tout ça c'est très bien mais souvent, on travaille sur plusieurs projets en même temps. Ou encore, on a travaillé sur des fichiers qui sont en dehors de projets. Et puis, on quitte Emacs. Et quand on le rouvre, il faut se souvenir d'où on était parti la dernière fois. Pour pallier à ça, j'ai utilisé longtemps recentf. J'ai même essayé d'utiliser desktop-save (le fou).
Mais à l'usage, c'était pénible car, en cas de changement de projet ou de travail, il me fallait transformer à nouveau la session de desktop. Et puis, j'ai visionné le paquet dashboard qui propose plus de choix en ouverture d'Emacs.
Pour cela, nous allons utiliser le package dashboard qui n'est pas disponible dans Debian, ni sur Elpa, mais sur le dépôt Melpa. Vous pouvez prendre la version non-stable qui a moins de dépendances.
Pour la configuration, j'ai adopté les éléments suivants:
;; Configuration de dashboard (use-package dashboard :ensure t :config ;; On active la prise en charge des projets avec projectile (setq dashboard-projects-backend 'projectile) ;; On personnalise le logo (setq dashboard-startup-banner "~/.config/emacs/logo.png") ;; On ajoute les raccourcis de rubrique (setq dashboard-set-navigator t) ;; On centre le contenu (setq dashboard-center-content t) ;; On configure ce qu'on veut voir apparaître (setq dashboard-items '((recents . 5) (projects . 5) (bookmarks . 5))) ;; On met des icônes (setq dashboard-set-heading-icons t) (setq dashboard-set-file-icons t) ;; On vire le footer (je ne le lis pas) (setq dashboard-set-footer nil) ;; On démarre dashboard par défaut (dashboard-setup-startup-hook) )
Avec ça, j'ai une page d'accueil sympa, mais aussi utile, car elle me permet de me reconcentrer soit sur un projet dédié, soit d'en changer, soit de revenir sur un fichier particulier. L'autre chose que j'apprécie aussi, c'est la gestion des bookmarks depuis le dashboard. Ça, c'est carrément super pour aller directement au niveau de ce qu'on cherche à obtenir sur un endroit particulier d'un fichier.
Faire du dev sous Emacs
Gestion des sources avec git/magit
Oui, vous pouvez gérer vos dépôts git avec Emacs, directement depuis Emacs, sans utiliser de terminal. C'est le paquet magit (ou elpa-magit dans Debian). C'est très bien fichu et finalement assez simple à utiliser.
Le temps de prise en main est très court, à vrai dire, vous pouvez vous contenter de lire une seule page de manuel pour faire le classique add-commit-push et comprendre comment fonctionne magit. C'est ce que j'ai fait et ça me va très bien. Je ne suis pas du tout un expert de Git, je me contente de quelques commandes de base et ça me va très bien: quelques branches, quelques fusions de temps en temps, des tags, des push/pull, rien de bien méchant.
L'avantage de magit c'est qu'il permet de ne pas avoir à sortir un terminal pour faire les opérations manuellement. Mieux, comme il est intégré dans un éditeur de texte, on peut facilement voir ce qui a changé, sous forme de texte. Ou encore, on peut carrément utiliser l'éditeur pour annuler un changement spécifique dans un fichier. Magit permet aussi de naviguer plus facilement dans les logs et les changements impliqués.
Plus simplement, le fait de devoir rédiger un message de commit directement dans Emacs lors du commit m'amène à être plus explicite sur les modifications ajoutées. Je considère que rien que pour ça, ça vaut le coup d'utiliser Magit.
Franchement, je vous invite tout simplement à installer le paquet avec les instructions qui suivent, à lire le manuel en faisant un exercice sur un dépôt et à utiliser le plus fréquemment possible la commande C-x g
.
Ma configuration de magit est ultra-simple:
(use-package magit)
À partir de là, j'utilise C-x g
pour ouvrir le buffer d'état de magit du dépôt du fichier en cours d'édition et si j'ai du mal, j'appuie sur ?
. Avec l'aide qui s'affiche, c'est très difficile de se perdre. Les seuls cas où j'hésite, c'est quand j'ai du mal avec des commandes git que je n'utilise que très rarement ou quand je dois ajouter un fichier au dépôt non ouvert dans Emacs (des images, des fichiers binaires, etc.).
Pour aller un peu plus loin, on peut aussi vouloir afficher les éléments relatifs à magit dans l'arbre de treemacs. Pour cela il faut le paquet treemacs-magit, dans la même version que treemacs. Comme pour treemacs, j'utilise la version Elpa, plus à jour que celle de Debian.
;; Treemacs avec support magit (use-package treemacs-magit :after (treemacs magit) :ensure t )
Une fois configuré, treemacs affiche l'état des fichiers de l'arbre git dans l'arborescence suivant un code couleur. En général, c'est du bleu pour les trucs modifiés. treemacs-magit permet de réagir aux manipulations de magit et de modifier cette coloration de manière plus rapide (sinon, il faut attendre que le système de fichier soit mis à jour). Ça ne coûte pas cher donc si on utilise magit et treemacs, autant en profiter.
Minimap
La minimap, c'est le truc qui permet d'avoir un visuel rapide d'un code source. C'est une fonctionnalité qui est devenue à la mode avec l'éditeur de texte Sublime. J'avoue qu'en mode graphique, dans un gros fichier, ça peut servir à s'orienter et à passer rapidement d'un endroit à l'autre, une sorte de marque-page du pauvre. Ça peut également servir à voir si une ligne est vraiment trop longue ou si un passage a été entièrement commenté d'un coup d'oeil.
Pratique, sans révolutionner le quotidien mais assez pertinent.
Le paquet Debian de Bullseye fait bien son job:
(use-package minimap :diminish minimap-mode :init (setq minimap-window-location 'right minimap-width-fraction 0.04 minimap-hide-scroll-bar nil minimap-hide-fringes nil minimap-dedicated-window t minimap-minimum-width 15) :custom-face (minimap-font-face ((t (:height 13 :weight bold :width condensed :spacing dual-width :family "VT323")))) (minimap-active-region-background ((t (:extend t :background "gray24")))) )
Au final, je l'ai réglé pour prendre peu de place sur le côté droit d'une fenêtre de code.
Avoir un terminal au top
Si vous utilisez VSCode, vous savez qu'un terminal est indispensable pour certaines tâches. Avoir un terminal dans un IDE est chose courante.
Hé bien, sachez qu'Emacs dispose de nombreux émulateurs de terminal et ce, depuis ses débuts:
- shell-mode
- eShell
- term
- ansi-term
Selon mon humble expérience, voici l'intérêt d'avoir un terminal intégré à Emacs:
- On peut ouvrir un shell sans avoir à quitter Emacs. Ça n'a l'air de rien comme ça mais pour lancer des tests unitaires ou une compilation, c'est très pratique.
- Ca gère le système de buffer/fenêtre d'Emacs. On peut ainsi copier/coller du texte depuis Emacs dans le Shell et vice-versa. Très pratique à l'usage quand on a une longue commande à taper depuis un fichier texte.
- On peut, dans la majorité des cas, utiliser les fonctions d'édition de texte d'Emacs au sein du shell.
- Certains modes disposent de commandes pour envoyer directement des instructions au shell. Par exemple le mode Python natif d'Emacs dispose d'une commande pour exécuter ce que vous avez capturé (ou tout le buffer) directement par l'exécutable Python via une commande shell.
Néanmoins, tous les modes cités ont leurs avantages et inconvénients. Dans la pratique, les trucs chiants qu'on rencontre le plus souvent sont le non-respect des couleurs ou un comportement bizarre avec les commandes qui ont besoin de gérer la sortie texte en direct, des trucs interactifs comme ncdu par exemple. Mais, dans l'ensemble, ça marche quand même bien: rares sont les situations où vous allez être complètement bloqués et devoir ouvrir un vrai terminal.
Arrive vterm qui change un peu la donne sur ses prédécesseurs, sans tout révolutionner.
Dans le principe:
- vterm est un paquet Emacs qui gère un terminal via la libvterm. Ça permet d'avoir une fenêtre Emacs qui est un vrai terminal et qui va aussi vite en termes de performances et de configuration.
- vterm a besoin d'un module C nommé vterm-module pour faire le lien entre Emacs Lisp et libvterm.
- Il faut donc de quoi compiler vterm-module et pour ça, il faut un environnement de compilation en C, CMake, et le paquet libtool-bin ainsi que la bibliothèque de dev de libvterm, bien sûr.
- Une fois vterm installé, si le module vterm-module n'est pas présent, il est compilé à la volée.
- Une fois vterm configuré correctement, il reste à ajouter des éléments de configuration dans son .bashrc pour faciliter la communication entre les deux processus, notamment avec la fonction
Armé de ces informations, on peut s'attaquer à l'installation de vterm sous Debian Bullseye:
# apt install libvterm0 libvterm-dev libtool-bin cmake
Activer Melpa non stable dans init.el:
;; Ajout de melpa "non-stable" dans les dépôts (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) ;; Melpa-stable a une priorité plus grande (setq package-archive-priorities '(("melpa" . 0) ("melpa-stable" . 10) ("gnu" . 20)))
M-x package-install
→ Choisir vterm → Installer
Dans init.el:
(use-package vterm :ensure t :config (setq vterm-kill-buffer-on-exit t vterm-shell "/bin/bash") )
Au lancement de vterm, on vous demande s'il faut compiler vterm-module. Répondre y et le tour est joué: vterm est maintenant fonctionnel.
À partir de cet instant, M-x vterm
vous amène dans un nouveau monde: un truc simple où toutes les commandes de shell fonctionnent correctement, avec les couleurs et tout ce qui va avec. En plus, c'est rapide. Par contre, comme ce n'est pas intégré nativement à Emacs, c'est plus compliqué à mettre en place, à installer surtout. Peut-être qu'avec le temps, ça changera.
Dans tous les cas, je ne regrette pas: une fois qu'on a utilisé vterm, on a du mal à s'en passer. Ça devient le shell universel.
Principes de LSP
Bon, je ne vais pas vous faire la totale sur LSP. Sachez que ça veut dire Language Server Protocol, que c'est un protocole d'échange entre un client (Emacs) et un serveur de langage (un programme externe à Emacs). Le protocole est normalisé et le client s'en sert pour interroger le serveur qui, connaissant le langage, sa grammaire et ses règles peut répondre aux questions du client.
Des questions typiques du client vers le serveur:
- Donne moi une liste d'autocomplétion sur tel symbole.
- Donne moi la doc en markdown de cette fonction de la bibliothèque standard.
- Trouve moi les erreurs de ce code.
- Donne moi la liste des fichiers qui contiennent ces références.
- etc.
On voit tout de suite l'avantage de ça, c'est que la complexité de l'analyse du code est confiée à un programme dédié (le serveur) et qu'il n'y a pas besoin de l'implémenter dans Emacs. Mieux, ce truc vient de Microsoft et, alors que j'ai toujours tendance à me méfier comme la peste de cette boîte, ça a permis l'émergence de nombreux serveurs de langue pour différents langage, pour alimenter leur IDE populaire du moment (VSCode). En conséquences, en développant un client pour Emacs, on récupère les fonctionnalités des différents serveurs de langage.
Dans Emacs, lsp-mode, c'est le paquet qui fait le client et c'est celui que nous allons installer.
Configuration de lsp-mode
Bon, on va installer d'abord le paquet lsp-mode. Je vous conseille de prendre celui sur melpa stable. Il est plus à jour que celui packagé dans Debian et à ce stade de l'aventure, mieux vaut privilégier le up-to-date car lsp-mode ça reste encore un paquet jeune.
(use-package lsp-mode :ensure t :diminish lsp-mode :init ;; J'utilise lsp-mode avec C-l (setq lsp-keymap-prefix "C-l") ;; Mais il faut aussi le foutre en raccourci clavier :hook ((lsp-mode . lsp-enable-which-key-integration) (c-mode . lsp) (c++-mode . lsp) (python-mode . lsp)) :config ;; On enlève la ligne du haut, ça merde avec centaur-tabs (setq lsp-headerline-breadcrumb-enable nil lsp-headerline-breadcrumb-enable-symbol-numbers t lsp-headerline-breadcrumb-segments '(project file symbols)) (setq lsp-lens-enable t) (setq lsp-modeline-code-actions-enable t) ;; On va utiliser capf: company-capf pour la completion. ;; C'est intégré dans company (setq lsp-completion-provider :capf lsp-completion-show-detail t lsp-completion-show-detail t) ;; On ajoute aussi le binding pour le préfixe (define-key lsp-mode-map (kbd "C-l") lsp-command-map) )
Avec ça, lsp-mode se lance quand vous ouvrez un fichier C/C++ ou Python. On y ajoute de l'aide avec which-key et on met un préfixe de raccourci-clavier avec C-l
.
Attention, la headerline (un truc qui permet de savoir où est foutu votre fichier) de lsp-mode ne semble pas compatible avec centaur-tabs. C'est bien dommage, mais je privilégie centaur-tabs à la headerline de lsp-mode, car les tabs permettent de savoir les fichiers déjà ouverts en un coup d'oeil, ce que ne fait pas la headerline. C'est dommage mais parfois on ne peut avoir que le cul de la crémière et pas le beurre ni l'argent du beurre.
Ensuite, il vous faut un serveur de langue. Pour du dev en C/C++ en logiciel libre, il y a clangd, disponible dans le paquet Debian du même nom:
;; Configuration de lsp-ui (use-package lsp-ui :ensure t :config ;; On active l'affichage de la doc (setq lsp-ui-doc-enable t lsp-ui-doc-delay 0.5 lsp-ui-doc-show-with-mouse t lsp-ui-doc-show-with-cursor t lsp-ui-doc-header t lsp-ui-doc-include-signature t lsp-ui-doc-alignment 'window lsp-ui-doc-max-height 30) ;; Gestion de la sideline (setq lsp-ui-sideline-delay 0.2 lsp-ui-sideline-show-diagnostics t lsp-ui-sideline-show-hover t lsp-ui-sideline-show-code-actions t lsp-ui-sideline-update-mode 'line) )
Concrètement, avec cette configuration, vous pourrez afficher la documentation au survol en incluant un maximum de détails. Par ailleurs, vous aurez aussi l'apparition d'informations sur le côté (la sideline) vous informant des problèmes rencontrés ou des solutions possibles à cette position du curseur. Pour certaines personnes aimant les styles épurés, attention, il va y avoir de l'encombrement. Néanmoins, c'est de l'encombrement utile: les informations pour vous indiquer quoi faire ou vous aider à trouver ce que vous voulez.
Un dernier détail si vous avez un projet en C++ qui utilise Cmake, vous devez générer un fichier de commandes de compilation pour que le serveur LSP puisse avoir une vision totale du projet et savoir où vous rediriger quand vous en aurez besoin. Ce fichier est un fichier JSON et se nomme compile_commands.json
.
La commande ci-dessous permet de générer le fichier dans le répertoire build
make -Bbuild -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
Une fois que vous aurez généré ce fichier, vous êtes prêts à vous servir de lsp-mode. Vous pouvez simplement suivre la documentation de découverte des fonctionnalités et vous familiariser avec les commandes et les affichages.
Augmenter treemacs avec lsp-treemacs
Dans de nombreux IDE, l'arbre du code dispose souvent d'un navigateur de méthodes et de fonctions qui extrait les éléments du code. Ça permet de se déplacer dans le code rapidement ainsi que d'avoir une vue globale du contenu du code en cours.
Il suffit d'installer le paquet lsp-treemacs et de le configurer comme suit:
(use-package lsp-treemacs :ensure t :init (lsp-treemacs-sync-mode 1) )
Globalement, ici on active la synchronisation avec treemacs. Mettez ça après votre déclaration de lsp-mode.
Une fois que c'est activé, vous disposez de commandes supplémentaires qui affichent une nouvelle sous-fenêtre en dessous de la fenêtre Treemacs et dont le contenu varie suivant la commande:
- lsp-treemacs-symbols affiche un arbre de symboles (variables/méthodes/fonctions). Ça permet de naviguer facilement dans le code. On peut fermer la fenêtre avec q. Par défaut, la navigation n'est pas ultra-pratique en dehors de la souris et sur les petits écrans, il faut souvent naviguer.
- lsp-treemacs-references affiche un arbre qui liste les références de l'objet en cours de survol/position. Ça fait la même chose que lsp-find-references mais avec un arbre à la mode treemacs. C'est juste plus joli.
- lsp-treemacs-list-errors affiche un arbre qui liste les erreurs détectées dans tout le projet. C'est dynamique.
D'un point de vue graphique, c'est sûr que lsp-treemacs apporte des choses. Mais à l'usage, à part la partie sur les symboles, il faut disposer d'un écran assez grand pour que ce soit ergonomique, je trouve.
Faire du dev python
Introduction
Ca fait des années que j'utilise Emacs pour mes développements en Python. Tout a commencé par une configuration simple: celle du python-mode, livré en standard avec Emacs. Globalement, avec ça, j'avais moins d'erreurs d'indentations que par le passé. Avec la gestion des buffers, j'arrivais à passer facilement d'un fichier à l'autre.
Par la suite, j'ai découvert elpy qui m'a apporté essentiellement flymake. Ce dernier sur le mode python m'a permis de formater mes sources à peu près correctement ainsi que d'éviter des erreurs grossières.
J'aurai pu m'arrêter là mais après avoir travaillé sur lsp-mode en C/C++, je me suis demandé ce que ça pourrait donner pour Python. Je me suis attaqué à la configuration de lsp-mode pour Python dans ma configuration Emacs et puis j'ai travaillé sur un projet spécifique sur lequel j'avais déjà une expérience et une bonne connaissance de l'architecture du code. Et là, j'ai été bluffé, mon expérience est bien meilleure que tout ce que j'ai connu auparavant, notamment de Elpy. Tout marche pratiquement out-of-the-box et c'est vraiment très bien.
Choisir un serveur de langage Python
Bon, on ne va pas se mentir, sous Debian, il n'y a pas beaucoup de choix en ce qui concerne les serveurs de langage Python disponibles, mais il en faut juste un. Donc, on dispose des paquets suivants:
Pour vous faire gagner du temps, pyls est en rade de maintenance et pylsp est la flèche montante. Donc, je suis parti sur le deuxième.
Configuration de pylsp
Out-of-the-box, pylsp fait déjà beaucoup. La complétion, la doc, la recherche de symboles, presque le café. Mais j'ai rencontré quelques points d'accroche qu'on peut tout à fait corriger en modifiant la configuration du serveur de langage.
- Pas accès à la documentation des packages internes
__init__.py
. - Désactivation de pylint par défaut. Dommage, c'est ça que j'utilise.
Pour modifier les options du serveur de langage, ça se passe directement au niveau de la configuration d'Emacs du paquet lsp-mode. Pour faire simple, c'est dans lsp-mode que vous déclarez la valeur des variables de configuration du serveur. Ensuite, plus d'information est disponible sur cette page qui fait la référence des options de configuration comprises par Emacs dans lsp-mode. Pour information, on trouve la correspondance dans la documentation de pylsp.
En conclusions, voici la configuration que j'applique pour le moment:
;; Configuration de pylsp pour Python (setq lsp-pylsp-configuration-sources "pydocstyle" lsp-pylsp-plugins-pylint-enabled t)
Pour le reste, c'est comme pour LSP classique.
Améliorer Projectile
J'en ai déjà parlé au niveau de l'introduction dans Projectile mais dans la pratique, j'utilise la combinaison suivante pour mes projets Python:
- Python3 (on est en 2021).
- pytest pour les tests unitaires.
- setup.py pour la configuration et la déclaration des dépendances.
- pylint pour les contraintes de code.
Ça se traduit par l'ajout d'un nouveau type de projet dans projectile qui prend la forme de la configuration suivante:
;; J'ajoute mon type de projet principal sous Python (projectile-register-project-type 'python3-pytest '("pytest.ini" "setup.py") ;;:project-file "setup.py" :compile "python3 setup.py build" :test "python3 -m pytest" :run "python3 -m gis2fg" :test-dir "tests" :test-prefix "test_" :test-suffix "_test.py")
À partir de là, les commandes de test seront appliquées correctement (enfin, dans ma configuration).
Conclusions
Avec tout ça, j'ai viré Elpy qui était sans doute le paquet d'assistant de développement Python le plus utilisé sous Emacs et gardé pylsp qui fait vraiment bien le job. Il y a quelques éléments qu'il n'aime pas, notamment l'utilisation d'imports relatifs qu'il ne parvient pas à résoudre pour récupérer la documentation sur les symboles. Par exemple:
from gis2fg.Jobs import Job from gis2fg.btg import Curves
Et là, ça marche ! C'est probablement plus propre d'ailleurs.
À part ça, l'expérience utilisateur est bien meilleure. Avant, je devais jongler sans arrêt avec des buffers ouverts (ou pas) ou que je fermais alors que j'en avais encore besoin. Maintenant, une simple recherche de déclarations et je retrouve mes petits en quelques touches de clavier.
Idem pour les tests unitaires, plus besoin de terminal dédié en dehors d'Emacs pour ça, grâce à Projectile, ça marche plus facilement.
Bien entendu, si vous êtes un développeur Python débutant, vous allez rester très lent. Mais passé un certain niveau, Emacs, lsp-mode et projectile fait vraiment bien le job. On améliore sa productivité de manière réelle (enfin, c'est mon cas).
Conclusions
Si vous avez tenu jusqu'ici, bravo. Vous en savez un peu plus sur Emacs et sur ma configuration et j'espère que ça peut vous inspirer. Il peut sans doute y avoir des erreurs et il peut manquer aussi d'explications, mais l'objectif était de faire une présentation plus qu'une référence.
Pour terminer, sachez qu'Emacs continue d'évoluer et ce, pas si lentement que ça je trouve. Parmi les projets les plus prometteurs on a:
- un port GTK wayland natif pour Emacs qui a été mergé dans la branche master d'Emacs en décembre 2021 et qui sera disponible sous Emacs 29. L'intérêt de ce port, c'est que je suis sous Wayland et qu'Emacs gagnerait en fluidité et en intégration dans cet environnement graphique. Et puis aussi, Emacs est sans doute le dernier truc que j'ai qui m'oblige à garder XWayland (dont j'aimerais bien me passer).
- la compilation native (native comp) qui permet d'accélérer Emacs en compilant et en lançeant les modules eLisp en binaires ELF. Elle est déjà intégrée dans la branche master depuis un an et, sous réserve que les empaqueteurs Debian active l'option, elle devrait être disponible dans Emacs 28.