Accueil > Informatique > Emacs > Un EDI pour python avec emacs.
Un EDI pour python avec emacs.
jeudi 12 novembre 2020, par
Introduction
L’objectif de cet article et de présenter comment configurer emacs pour développer en python.
Il existe de nombreux moyens d’obtenir une telle configuration ; ici je présenterai une solution reposant sur :
- pyenv pour gérer les environnements virtuels ;
- lsp-mode et pyright pour le contrôle de type statique ;
- dap-mode et debugpy pour débugger ;
- isort, black et pyment pour la mise en forme.
Principe de fonctionnement
Le contrôle syntaxique et des types est délégué à pyright via le "language server protocol" et de la même manière le débuggage est réalisé par
debugpy via le "debug adpatater protocol". Cela permet de transformer emacs en EDI et de bénéficier de service spécifique pour python développer initialement pour vscode. Les logiciels pyright et debugpy sont développés par Microsoft et placés sous licence MIT.
Il existe de nombreux langages supportés par lsp-mode
Les avantages de cette démarche sont doubles :
- bénéficier de logiciels spécialisés dans le langage utilisé ;
- avoir un comportement d’emacs unifié pour plusieurs langage.
Le logiciel pyright fait du contrôle de type statique, un message d’erreur est envoyé dès la saisie s’il détecte une erreur de type :
Pour en savoir plus sur le typage statique en python voir le site de mypy ou ce tutoriel.
Mise en oeuvre
Pré-requis et contexte
- Debian buster sid
- emacs 26+ (testé avec emacs 27)
- une installation de développement minimale :
apt-get install libsqlite3-dev libreadline-dev libbz2-dev zlib1g-dev build-essential python3-setuptools tk-dev libssl-dev libffi-dev - npm (pyright est écrit en NodeJS)
apt-get install npm - straight pour la gestion de paquets d’emacs
- pyenv installé et fonctionnel voir ce billet.
Installation de pyright
Nous allons réaliser une installation dans le répertoire utilisateur.
mkdir ~/.local/share/node_modules
echo 'export NPM_CONFIG_PREFIX="$HOME/.local/share"' >> ~/.bashrc
echo 'export PATH="$NPM_CONFIG_PREFIX/node_modules/.bin:$PATH"' >> ~/.bashrc
source ~/.bashrcL’installation est rapide avec npm
npm install pyright --prefix $NPM_CONFIG_PREFIX/
Installation de quelques paquets python
Nous allons installer dans l’environnement virtuel default dont debuggpy.
pyenv activate default
pip install ipython black isort debugpy pymentConfiguration d’emacs
Flycheck, diminish et projectile
- Flycheck : vérificateur de syntaxe
- diminish : pour ne pas encombrer la modeline
- projectile : un gestionnaire de projet
(use-package flycheck
:straight t
:init
(global-flycheck-mode))
(use-package diminish
:straight t
)
(use-package projectile
:straight t
:init
;; this must be done before :config so we can't use :bind
(define-key global-map (kbd "C-c p") 'projectile-command-map)
:config
(projectile-mode t)
(setq
projectile-globally-ignored-files
(append '("*.aux" "*.out" "._sync*" ) projectile-globally-ignored-files)
projectile-indexing-method (quote alien)
projectile-git-command "git ls-files -zc --exclude-standard"
)
)pyenv, ipython
Intégration de pyenv et utilisation de ipython comme shell python
(use-package pyenv-mode
:straight t
:diminish
:config
(defun projectile-pyenv-mode-set ()
"Set pyenv version matching project name."
(let ((project (projectile-project-name)))
(if (member project (pyenv-mode-versions))
(pyenv-mode-set project)
(pyenv-mode-unset))))
(add-hook 'projectile-after-switch-project-hook 'projectile-pyenv-mode-set)
:init
(add-to-list 'exec-path "~/.pyenv/bin")
(add-to-list 'exec-path "~/.pyenv/shims")
(pyenv-mode t)
(pyenv-mode-set "default")
)
(use-package python
:config
(setq python-shell-interpreter "ipython"
python-shell-interpreter-args "--simple-prompt -i --pprint"
python-indent-offset 4
eldoc-documentation-function #'ignore
)
)lsp-mode
Les options de configuration de lsp et lsp-ui sont très nombreuses. La page suivante permet de régler l’interface selon ses envies.
(use-package lsp-mode
:straight t
:config
(setq ;; performance
lsp-enable-file-watchers nil
read-process-output-max (* 1024 1024)
gc-cons-threshold 100000000
lsp-idle-delay 0.5
;;
lsp-eldoc-hook nil
;;pas de fil d'ariane
lsp-headerline-breadcrumb-enable nil
;; pas de imenu voir menu-list
lsp-enable-imenu nil
;; lentille
lsp-lens-enable t
lsp-semantic-highlighting t
lsp-modeline-code-actions-enable t
)
:hook
(
(python-mode . lsp)
)
:commands lsp
)
(use-package lsp-ui
:straight t
:config
(setq lsp-ui-doc-show-with-cursor nil ;; pas de doc lorsque le curseur est placé sur le mot
lsp-ui-doc-use-childframe t
lsp-ui-sideline-diagnostic-max-line-length 80
;; lsp-ui-imenu
lsp-ui-imenu-enable nil
;; lsp-ui-peek
lsp-ui-peek-enable t
;; lsp-ui-sideline
lsp-ui-sideline-enable t
lsp-ui-sideline-ignore-duplicate t
lsp-ui-sideline-show-symbol t
lsp-ui-sideline-show-hover nil
lsp-ui-sideline-show-diagnostics t
lsp-ui-sideline-show-code-actions t
)
:bind
(:map lsp-ui-mode-map
("M-." . lsp-ui-peek-find-definitions)
("M-?" . lsp-ui-peek-find-references)
)
:commands
lsp-ui-mode )
(use-package lsp-pyright
:ensure t
:straight t
:hook (python-mode . (lambda ()
(require 'lsp-pyright)
(lsp)))) ; or lsp-deferreddap-mode
(use-package dap-mode
:straight t
:ensure t
:config
(setq dap-mode t)
(setq dap-ui-mode t)
;; enables mouse hover support
(setq dap-tooltip-mode t)
;; use tooltips for mouse hover
;; if it is not enabled `dap-mode' will use the minibuffer.
(setq tooltip-mode t)
(setq dap-ui-controls-mode t)
(setq dap-python-debugger 'debugpy)
(require 'dap-python))(re)formatage de code
À la différence de pyls (un autre langage serveur pour python), pyright ne formate pas le code. Nous allons configurer emacs de telle sorte que le buffer soit formaté au moment où il est enregistré.
(use-package buftra ;;https://github.com/paetzke/buftra.el
:straight (:host github :repo "humitos/buftra.el"))
(use-package py-pyment
:straight (:host github :repo "humitos/py-cmd-buffer.el")
:config
(setq py-pyment-options '("--output=reST"))
(add-hook 'python-mode-hook 'py-pyment-enable-on-save) )
(use-package py-isort
:straight (:host github :repo "humitos/py-cmd-buffer.el")
:config
(setq py-isort-options '("--profile=black"))
(add-hook 'python-mode-hook 'py-isort-enable-on-save)
)
(use-package python-black
:straight t
:demand t
:after python
:config (add-hook 'python-mode-hook 'python-black-on-save-mode) )
(use-package python-docstring
:straight t
:diminish
:hook (python-mode . python-docstring-mode) )Un menu avec les variables et la complétion de commande
On accède au menu par Ctrl - ’
(use-package imenu-list
:straight t
:bind
("C-'" . imenu-list-smart-toggle)
)
(use-package company
:straight t
:config
(add-hook 'after-init-hook 'global-company-mode)
)Le fichier init.el complet :
Exemples d’utilisation
Pour changer d’environement python : C-x C-s
Pour recharger lsp : M-x lsp-workspace-restart
Pour lancer l’interpréteur python (ipython) : C-c C-p
Pour évaluer un buffer : C-c C-c
Pour évaluer une région : C-c C-r
Pour lancer le debugger : Debug->Start, puis choisir : Python : : Run file (buffer)
Conclusion
Comme toujours avec emacs, il y a un peu de travail !! Mais le jeu en vaut la chandelle, surtout si vous travaillez avec plusieurs langages de programmation que vous pouvez intégrer d’autre langage serveur à lsp-mode et à dap-mode. Les liens qui suivent donnent un aperçu des possibilités et de la richesse de l’éco-système d’emacs. Amusez-vous bien !
Liens
- Pour utiliser mslsp un autre langage serveur : Configuring Emacs, lsp-mode and Microsoft’s Visual Studio Code Python language server.
- Emacs Wiki PythonProgrammingInEmacs
- Pour une solution reposant sur elpy : Emacs : The Best Python Editor ?
- Pour utiliser Palantir langage server : Getting started with lsp-mode for Python
- Use pyright with CentOS7, emacs lsp-mode
Heptagone

