Convertir emacs en un IDE de python

4 minutos de lectura Publicado:

Dicen que con emacs, a parte de hablar por irc, mandar correos y ver los cómics de xkcd se puede editar texto! Hasta se puede convertir emacs en un ide! Una locura. Hoy vamos a ver como programar en python y tener soporte para todo lo que suelen tener los IDE de programación.

Empecemos por el principio. Qué es elpy? Viene a ser un envoltorio de varios módulos. Por defecto viene con soporte de identación automática, auto-completado, documentación de los módulos, corrector de errores, virtualenv, inserción de snippets y más. Todo esto lo envuelve en un proceso que corre en segundo plano. Iremos viendo poco a poco como se usa todo.

Pero antes que nada, instalemos lo necesario. Primero algunas dependencias en pip. Por si se programa en python 2 y en python 3, mejor instalar las dependencias de ambas versiones:

Para que elpy funcione hay que instalar las siguientes dependencias:

sudo pip3 install rope importmagic autopep8 yapf
sudo pip2 install rope importmagic autopep8 yapf

Además, es conveniente que estas dependencias se instalen en cada virtualenv que se cree. Para hacerlo, hay que añadir lo siguiente al archivo ~/.virtualenvs/postmkvirtualenv:

pip install rope importmagic autopep8 yapf

La configuración de elpy:

(defun elpy-goto-definition-or-rgrep ()
  "Go to the definition of the symbol at point, if found. Otherwise, run `elpy-rgrep-symbol'."
    (interactive)
    (ring-insert find-tag-marker-ring (point-marker))
    (condition-case nil (elpy-goto-definition)
        (error (elpy-rgrep-symbol
                   (concat "\\(def\\|class\\)\s" (thing-at-point 'symbol) "(")))))

(use-package elpy
  :ensure t
  :init
  (use-package pyvenv :ensure t)
  (setq elpy-modules '(elpy-module-sane-defaults elpy-module-company elpy-module-eldoc elpy-module-pyvenv))
  (setq elpy-rpc-backend "jedi")
  :config
  (add-to-list 'ivy-completing-read-handlers-alist '(elpy-doc . completing-read-default)) ;; véase https://github.com/abo-abo/swiper/issues/892
  ;; Use pytest
  (setq elpy-test-runner 'elpy-test-pytest-runner)
  (setq elpy-test-pytest-runner-command '("tox"))
  (add-to-list 'elpy-project-ignored-directories "__pycache__")
  (add-to-list 'elpy-project-ignored-directories ".cache")
  (setq compilation-scroll-output 'first-error)
  (add-to-list 'auto-mode-alist '("\\.py" . python-mode))
  (add-to-list 'auto-mode-alist '("\\.py" . elpy-mode))
  (elpy-enable)
  (evil-define-key 'normal elpy-mode-map
      "gd" 'elpy-goto-definition-or-rgrep))

Hay que recordar que evaluando la configuración de use-package se instalan los paquetes automáticamente, gracias al :ensure t, como vimos en el articulo para instalar automáticamente la configuración de emacs.

Es posible que tarde un rato en instalarse todo, ya que elpy tiene varias dependencias. Estas son company, find-file-in-project, highlight-indentation, pyvenv y yasnippet. En la configuración anterior se puede ver que he re-definido la variable elpy-modules. Por defecto trae un par de módulos más, como yasnippet o highlight-indentation, pero como no los uso, pues fuera. También he quitado flymake, por que prefiero flycheck que tiene soporte para otros lenguajes, aunque de momento solo tengo agregado el lenguaje python.

Este paquete muestra una ralla que marca los 79 carácteres, para cumplir con el pep8.

(use-package fill-column-indicator
  :init
  (setq fci-rule-color "purple")
  (setq fill-column 79)
  (setq fci-rule-column 79)
  (add-hook 'python-mode-hook 'fci-mode)
  (add-hook 'emacs-lisp-mode-hook 'fci-mode)
  (add-hook 'sh-mode-hook 'fci-mode)
  :ensure t)

Y aquí configuramos flycheck, en vez de flake8:

(use-package flycheck
  :config
  ;; (setq flycheck-global-modes '(python-mode))
  ;; (global-flycheck-mode)
  (add-hook 'after-init-hook #'global-flycheck-mode)
  (spc-map
     "i" '(nil :which-key "flycheck prefix")
     "in" 'flycheck-next-error
     "ip" 'flycheck-previous-error
     "il" 'flycheck-list-errors)
  :diminish flycheck-mode
  :ensure t)

De tema de configuración ya estamos. Veamos ahora como se utiliza esto. Solo mencionaré los que uso o los que tengo intención de usar más.

Atajo de teclado Función Explicación
S/N elpy-config Muestra la configuración actual de elpy
S/N pyvenv-workon Equivalente al workon del virtualenvwrapper. Permite escoger entre todos los virtualenv existentes.
S/N pyvenv-deactivate Desactiva el virtualenv.
M-TAB elpy-company-backend Auto completado. Para moverse entre las opciones, presionar M-n y M-p.
M-. elpy-goto-definition Va a la localización de la definición del elemento en el que está el cursor.
M-* pop-tag-mark Vuelve al punto en el que estaba el cursor antes de ejecutar elpy-goto-definition.
C-c C-o elpy-occur-definitions Abre un minibuffer con las definiciones de todas las clases y funciones del buffer.
C-c C-z elpy-shell-switch-to-shell Abre un buffer con un intérprete de python. Usará el entorno virtual si está activo.
C-c C-c elpy-shell-send-region-or-buffer Envia la región o el buffer al intérprete de python.
C-c C-v elpy-check Ejecutará el corrector de sintaxis.
C-c C-d elpy-doc Abrirá la documentación para el elemento del cursor.
C-c C-e elpy-multiedit-python-symbol-at-point Edita todas las ocurrencias en el cursor. Para cambiar solo las de la función, C-x n d y C-x n w.
C-c C-r f elpy-format-code Formatea automáticamente.
C-c C-r i elpy-importmagic-fixup Auto importar módulos que se estén usando.

A continuación unas cuantas imágenes de algunas funciones:

Figura 1: elpy-config
Figura 1: elpy-config
Figura 2: pyvenv-workon
Figura 2: pyvenv-workon
Figura 3: elpy-company-backend
Figura 3: elpy-company-backend
Figura 4: elpy-occur-definitions
Figura 4: elpy-occur-definitions
Figura 5: elpy-check
Figura 5: elpy-check
Figura 6: elpy-doc
Figura 6: elpy-doc
Figura 7: elpy-multiedit-python-symbol-at-point
Figura 7: elpy-multiedit-python-symbol-at-point

Fuentes:

Cualquier duda o comentario, me puedes contactar en los canales descritos en la página principal