Emacs est un éditeur de texte libre et extensible via le language Emacs Lisp
On va ajouter à Emacs les fonctionnalités suivantes pour le développement en Typescript:
- Coloration syntaxique avancée avec tree-sitter
- Analyse de code avec LSP Mode
- Débogage avec DAP Mode
Installation d’un premier package
Chacun des logiciels cités dans les fonctionnalités à ajouter est distribué sous forme d’un paquet Emacs. Le mode de fonctionnement est similaire à Debian
On va installer un premier paquet pour l’exemple: dap-mode
Configuration du dépôt Melpa
Ce paquet est distribué via le dépôt Melpa. Pour
installer ce paquet, il faut donc ajouter Melpa à la liste des dépôts
d’Emacs dans le fichier ~/.emacs.d/init.el
~/.emacs.d/init.el
est le fichier de configuration d’Emacs qui est
exécuté à chaque fois que l’éditeur de texte est lancé. Il contient du
code Emacs Lisp (extension .el
)
;; Le paquet `package` est installé avec Emacs, on va l'utiliser pour
;; installer le paquet dap-mode
(require 'package)
;; Ajout de Melpa à la liste des dépôts Emacs
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
;; Chargement des paquets installés
(package-initialize)
Récupération de la liste des paquets disponibles dans Melpa
Ajouter un dépôt à la variable package-archives
n’a pas comme
effet de bord de récupérer la liste des paquets disponibles dans
Melpa.
Pour récupérer la liste des paquets disponible, il faut faire appel à
la fonction package-refresh-contents
de package
. C’est
l’équivalent d’un apt update
dans Emacs
On va automatiser cette action lors de la première ouverture d’Emacs. La logique est la suivante: si la liste des paquets connus est vide, alors on va récupérer la liste des paquets disponibles:
;; La variable package-archive-contents
;; contient la liste des paquets connus
(unless package-archive-contents (package-refresh-contents))
Une des propriétés d’Emacs est que l’éditeur permet de décrire
toutes les fonctions et variables utilisées avec les fonctions
describe-function
(raccourci C-h
f
) et describe-variable
(raccourci C-h
v
)
Pour lancer une fonction, utilisez le raccourci Alt-x noté M-x
puis
tapez le nom de la commande, par exemple M-x
describe-function
. Autre exemple de raccourci clavier: C-h
désigne Contrôle-h
Installation de dap-mode
On va maintenant installer le paquet dap-mode
;; Définition de la liste des paquets à installer dans une nouvelle variable
(setq package-list '(dap-mode))
;; Installation de chaque paquet défini dans package-list non installé
(dolist (package package-list)
(unless (package-installed-p package) (package-install package)))
Notez que vous pouvez aussi installer manuellement un paquet avec
M-x
package-install
ou M-x
package-list-packages
.
Configuration de Typescript
Mode majeur Typescript
Emacs permet d’avoir un mode d’édition majeur et plusieurs mode d’éditions mineurs
On installe le mode d’édition majeur pour Typescript:
;; Définition de la liste des paquets à installer dans une nouvelle variable
(setq package-list '(dap-mode typescript-mode))
Tous les fichiers Typescript seront maintenant ouverts avec le mode majeur Typescript
Coloration syntaxique
On va utiliser le paquet tree-sitter qui permet de colorer les mots clefs des languages de programmation avec plus de précision que ce que propose nativement Emacs:
;; Définition de la liste des paquets à installer dans une nouvelle variable
(setq package-list '(dap-mode typescript-mode tree-sitter tree-sitter-langs))
;; Configuration de la coloration syntaxique:
;; Chargement des paquets
(require 'tree-sitter-langs)
(require 'tree-sitter)
;; La coloration syntaxique sera active dans tous les buffers Emacs
(global-tree-sitter-mode)
(add-hook 'tree-sitter-after-on-hook #'tree-sitter-hl-mode)
Si vous préférez le thème Emacs de droite par rapport à celui de
gauche (le défaut), vous pouvez activer ce thème avec (load-theme 'tango-dark)
LSP Mode
LSP mode va permettre de donner des indications/actions sur le code, comme par exemple:
- Type des variables
- Aller à la définition
- Renommage d’une variable/fonction
- Erreur de type/syntaxe
- …et la plupart des fonctionnalités q’un IDE propose
;; Définition de la liste des paquets à installer dans une nouvelle variable
(setq package-list '(dap-mode typescript-mode tree-sitter tree-sitter-langs lsp-mode lsp-ui))
(require 'lsp-mode)
(add-hook 'typescript-mode-hook 'lsp-deferred)
(add-hook 'javascript-mode-hook 'lsp-deferred)
DAP Mode
On passe maintenant à l’installation, la configuration et le test du débogueur sur un projet Typescript
Installation de DAP Mode
La feature dap-node
du paquet dap-mode
contient le code spécifique
pour déboguer en utilisant NodeJS. On peut charger son code en
exécutant la fonction (require 'dap-node)
lorsqu’on se trouve dans
un fichier Typescript.
On peut réaliser cette action (charger le debugger quand on se trouve dans un fichier Typescript) avec les hooks
L’utilisation du débogueur dans Emacs nécéssite le téléchargement d’un
module VSCode via la fonction dap-node-setup
. On va également
l’automatiser lors du chargement de dap-node
;; Chargement du débogueur node lorsque le mode majeur est Typescript
(defun my-setup-dap-node ()
"Require dap-node feature and run dap-node-setup if VSCode module isn't already installed"
(require 'dap-node)
(unless (file-exists-p dap-node-debug-path) (dap-node-setup)))
(add-hook 'typescript-mode-hook 'my-setup-dap-node)
(add-hook 'javascript-mode-hook 'my-setup-dap-node)
Vérification de l’installation
Un bug récurrent lors du lancement de dap-node-setup
est que le
serveur de Microsoft hébergeant le serveur dap répond une erreur 429
(nombre limite de requêtes atteint)
Pour vérifier que l’installation a fonctionné, vous pouver lancer le script lisp suivant:
(require 'dap-node)
(if (file-exists-p (nth 1 dap-node-debug-program))
(message "Le débogueur node a été installé avec succès")
(message "Le débogueur node n'est pas installé, suivez la procédure manuelle"))
Pour lancer ce script, copiez le dans Emacs, surlignez le et lancez la
commande eval-region
Procédure d’installation manuelle
Pour installer manuellement le driver si le serveur Microsoft a refusé
vla requête de dap-node-setup
:
- Rendez vous sur la page de l’extension VSCode Node Debug
- Téléchargez l’extension
- Le fichier téléchargé est un fichier de type Zip, vous devez le dézipper dans le répertoire d’installation de dap-node
Vous pouvez utiliser le shell
d’Emacs
avec M-x
eshell
qui permet d’évaluer des fonctions/variables elisp
et donc de ne pas se tromper sur la destination des fichiers de
l’archive, ici (eval dap-node-debug-path)
Utilisation du débogueur avec Typescript
Le débogueur Node installé par dap-node-setup
et le client Emacs
dap-mode
permettent maintenant de déboguer un project Typescript
On va utiliser le projet d’affichage de flux rss et le déboguer avec Emacs
Vous pouvez utiliser Magit ou la ligne de
commande git clone git@gitlab.com:Adelorn/flux-articles-console.git
pour installer ce dépôt. Ensuite, ouvrez le fichier index.ts à la
racine du projet
LSP Mode va d’abord vous demander quel serveur vous souhaitez
installer. Sélectionnez ts-ls
Ensuite, LSP Mode va vous demander si vous souhaitez enregistrer ce projet dans
la liste des projets connus. C’est le cas, tapez i
Vous pouvez maintenant lancer votre débogueur. Je vous conseille
l’utilisation de la commande dap-hydra
qui permet d’avoir accès aux
commandes importantes du débogueur en quelques touches
Une fois M-x
dap-hydra
lancé, vous pouvez mettre un breakpoint
dans le code avec b
a
puis lancer le débogueur avec d
d
. Sélectionnez la configuration de débug Launch index
A ce stade, voici ce qu’on obtient:
Comment configurer le débogueur
Fichier launch.json
On a utilisé la configuration de débug Launch index
, décrite dans le
fichier
launch.json
stocké dans .vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch index",
"program": "${workspaceFolder}/index.ts",
"preLaunchTask": "npm: build",
"dap-compilation": "npm run build",
"outFiles": ["${workspaceFolder}/dist/**/*.js"]
}
]
}
Ce fichier contient la liste des configurations de débug. La
configuration nommée Launch index
est celle qu’on utilise pour
lancer le programme index.ts
Node ne peut pas lancer le fichier Typescript directement, il faut
d’abord compiler les fichiers Typescript du projet vers des fichiers
Javascript. Cela est fait avant de lancer le débogueur, via la clef
dap-compilation
dans Emacs qui est l’équivalent de preLaunchTask
dans VSCode
Dans le projet utilisé en exemple, le script npm build
va lancer le
compilateur Typescript, et placer les fichier Javascript résultant de
la compilation dans le dossier dist
On précise au débogueur que les fichiers associés aux fichiers
Typescripts se trouvent dans dist
avec la propriété outFiles
Cette propriété référence la variable workspaceFolder
qui fait
partie de la spécification
launch.json
et sera remplacée par le chemin de la racine du projet
Équivalent dans Emacs
Vous pouvez également configurer le débogueur dans Emacs avec la
fonction dap-register-debug-template
. Voici l’équivalent du fichier
launch.json
présenté ci-dessus en Elisp:
(dap-register-debug-template
"Launch index::(Emacs DAP template)"
(list :type "node"
:request "launch"
:program "${workspaceFolder}/index.ts"
:dap-compilation "npm run build"
:outFiles (list "${workspaceFolder}/dist/**/*.js")
:name "Launch index (Emacs DAP template)"))
Configuration Typescript
Pour déboguer, il est nécéssaire de compiler Typescript avec
génération des liens entre les fichiers source .ts
et les fichiers
compilés .js
. Cela est obtenu avec "sourceMap": true
dans le
fichier de configuration du projet tsconfig.json
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"outDir": "dist",
"sourceMap": true,
"esModuleInterop": true
}
}
Conclusion
On obtient finalement la configuration Emacs suivante: init.el
Ce tutoriel vous a permis de mieux comprendre comment installer un paquet sur Emacs, de créer un premier script en Elisp avec quelques fonctions et variables. Pour continuer à personnaliser Emacs, voici une sélection de très bon paquets triés par thème
Je vous conseille également de lire le tutoriel
Elisp
et d’utiliser les commandes C-h
f
et C-h
v
pour décrire les
fonctions et variables disponibles dans Emacs