Configurando Dape: el nuevo cliente DAP para emacs

Abril 30, 2024

Hace un tiempo eglot, un cliente LSP (Language Server Protocol) fue introducido al núcleo de emacs, convirtiéndolo en más o menos el cliente de LSP oficial de emacs, para la desgracia de lsp-mode. Me gusta eglot, es fácil de usar, configurar y simplemente funciona, y su integración con otros paquetes y componentes de emacs como company y flycheck no tiene roces. Pero, si hay un aspecto con el que emacs ha batallado, ese es, en mi opinión, el debugging.

dape

Los desarrolladores del anteriormente mencionado lsp-mode también trabajan en dap-mode, un cliente de DAP (un LSP pero para debuggers) para emacs. Pero, como ya podrán adivinar, necesita lsp-mode para funcionar, para el detrimento de los usuarios de eglot.

Pero ahora tenemos un competidor a dap-mode en la misma forma en la que eglot es un competidor de lsp-mode. Dape (que no es tan nuevo para ser honesto, su primer commit data del 29 de septiembre de 2023).

A diferencia de dap-mode, aspira a ser un cliente de dap minimalista, y no hace uso de un archivo launch.json, utilizando configuraciones escritas enteramente en elisp en su lugar.

En este post, mostraré una configuración de ejemplo para usar dape con python y flask, pero planeo actualizarlo con más configuraciones. Dape es un proyecto extremadamente interesante y el hecho de que sea compatible con la gem de ruby rdbg llamó mi atención: emacs actualmente no puede competir con vs code como EL entorno de desarrollo para ruby, principalmente a causa del debugging. No he tenido suerte configurando dap-mode para ruby y no utiliza rdbg, la cual es la gem más nueva, actualizada, y en general, mejor gema para debuggear ruby. Me gustaría también checar en un futuro una configuración para debuggear javascript vanilla.

Pero bueno, leyendo el código fuente de dape nos encontramos con esto:

command "python"
               command-args ("-m" "debugpy.adapter" "--host" "0.0.0.0" "--port" :autoport)
               port :autoport
               :request "launch"
               :type "python"
               :cwd dape-cwd))
            (common
             `(:args []
               :justMyCode nil
               :console "integratedTerminal"
               :showReturnValue t
               :stopOnEntry nil))

Esta es la configuración básica para python con debugpy. Cuando instalas dape, y lo ejecutas con M-x dape, puedes seleccionar esta configuración. Y puedes asignar todas las variables que necesitas para debuggear tu proyecto en flask, principalmente :args y :module. Pero no es práctico escribir todo eso siempre que quieras depurar tu proyecto, así que vayamos a tu archivo init, y escribe lo siguiente:

(require 'dape)
;; Dape configs
(add-to-list 'dape-configs
	     `(debugpy-flask
	       modes (python-mode jinja2-mode)
	       command "python"
	       command-args ["-m" "debugpy.adapter" "--host" "0.0.0.0" "--port" :autoport]
	       port :autoport
	       :type "python"
	       :request "launch"
	       :module "flask"
	       :args ["--app" "src" "run" "--no-debugger" "--no-reload"]
	       :console "integratedTerminal"
	       :showReturnValue t
	       :justMyCode nil
	       :jinja t
	       :cwd dape-cwd-fn))

Primero, requerimos dape, y entonces, añadimos otra configuración a la lista de dape-configs, definida en dape.el. Como puedes ver, es básicamente una copia descarada de la configuración base de debugpy, pero con todas las variables definidas para desarrollo con flask, como el módulo a usar (flask) y los argumentos para la línea de comandos (–app, run, etc.) Hay un detalle, como puedes ver, el arreglo de argumentos define el nombre de mi aplicación como “src”. Intenté referirme al nombre de mi aplicación como una variable, para que pudiera ser utilizada con otros proyectos con diferentes nombres, pero bueno, no estoy muy familiarizado con dape, o con elisp incluso. Una posible solución (aunque lejos de ideal) sería copiar esta configuración a un archivo .dir-locals.el para la configuración de un proyecto específico.