Notxor tiene un blog

Defenestrando la vida

Emacs y lsp-mode

2021-03-11

Hoy vengo con un modo que hace poco que empecé a utilizar: lsp-mode. La verdad es que no lo utilizo demasiado, la mayor parte de mi trabajo la hago en org-mode y lo que menos hago es programar, que es para lo que es más útil lsp, aunque también podría usarlo para LaTeX. Language Server Protocol se está convirtiendo en un estándar para todos los editores de código e incluso los editores viejunos como Emacs y vim lo soportan. Este artículo hablará de cómo configurarlo mínimamente en Emacs y sobre un par de pruebas que he hecho para ver su funcionamiento.

Como decía, mi trabajo habitual, como corresponde a un psicólogo, no es programar sino escribir mucha documentación, informes, registros de visitas, planes de prevención, cursos de formación, blog... en fin, la mayor parte de lo que hago es escribir con org-mode o con LaTeX y para ello no necesito utilizar lsp-mode. En realidad, tampoco lo necesito utilizar cuando programo, algo que últimamente hago en elixir y para el que utilizo el paquete alchemist de Emacs, que cubre todas mis necesidades de sobra.

Descubrí lsp-mode cuando hice la aproximación o intento de aprender Rust. Lenguaje, que como ya dije en este blog, abandoné por desconfianza en los miembros de la fundación que se ha hecho cargo de su desarrollo. Cuando empecé a trastear con ese lenguaje, el modo de Emacs pedía insistentemente el lsp-mode y al final cedí y lo instalé. La experiencia fue breve pero pensé que debía probar un poco más ese paquete. La verdad es que lsp convierte cualquier editor en un IDE completo y proporciona funcionalidad de completado de sintaxis, ayuda contextual, navegación por el código, etc. Todo lo que puedas esperar de un buen editor. Para muchas de esas cosas Emacs tiene suficientes herramientas para trabajar y no necesita, en principio, servidores externos. Recuerdo que alguien me preguntó una vez qué editor actual usaría, que no sean mis dos preferidos Emacs y vim. Quizá la respuesta esperada estaría entre los famosos sublime, atom y similare... sin embargo, creo que mi respuesta ahora, conociendo lsp sería Kate: tiene todo lo que tienen los mencionados (y más), y kate traga menos recursos además de tener el soporte de lsp, que lo convierte en una magnífica alternativa.

Para entender cómo funciona lsp hay que comenzar diciendo que es el acrónimo de Protocolo de Servidor de Lenguaje. Es decir, hay un servidor con el que se comunica el editor para dotarle de todas esas características. Cada lenguaje tiene su servidor independiente, lo que obliga a que tendremos que tener un servidor de esos por lenguaje. No voy a entrar más allá en cómo funciona pero hay que dejar claro que la funcionalidad la proporciona un elemento externo al editor.

Instalación de lsp-mode

Tenemos la habitual instrucción de package-install. Como tampoco voy a ser muy exhaustivo, si estáis pensando en utilizarlo, es que os leáis su web:

M-x package-install <RET> lsp-mode <RET>

El paquete ya estará instalado en nuestro editor aunque de una manera muy básica. Lo que hace lsp-mode es intentar integrar el funcionamiento de lsp con los habituales paquetes de Emacs company, flycheck o flymake, projectile son los básicos, pero también utiliza otros como dired, treemacs, iedit... Por tanto hay que tener en cuenta que debemos tener instalados todos esos paquetes en nuestro Emacs para tener toda la funcionalidad. Al menos para lo básico:

  • company: es un paquete para el autocompletado de código. Hay paquetes para multitud de lenguajes específicos.
  • flymake: viene instalado con Emacs en sus últimas versiones y sirve para evaluar errores y warnings del código sobre la marcha.
  • projectile: es un paquete para la gestión de proyectos.

También es muy recomendable instalar junto con lsp-mode el paquete lsp-ui porque éste nos facilita también la navegación visual por el código, desplegables de documentación, selector de acciones de código, etc. Otro paquete que puede ser interesante es dap-mode para integrar el debugger. Aunque según qué lenguaje, sobre todo si podemos utilizar gdb, también podemos utilizar el modo de depuración propio de Emacs. Y por último, también es recomendable que si usas ivy o helm es recomendable que instales el paquete lsp-ivy o lsp-helm.

Configuración

La configuración que tengo activada para las pruebas incluye tan solo dos lenguajes. Uno es C++, para el que no he tenido que hacer nada especial durante su configuración. Parece que lsp-mode ya lo trae preparado todo. Fue abrir un fichero con en ese lenguaje y todo funcionó sin problemas. El segundo lenguaje es Python, que necesité instalar el servidor del lenguaje. Lo que me viene bien para mostrar las dos alternativas.

No voy a entrar en la configuración de todos los otros paquetes auxiliares, porque sería extenderme innecesariamente. La configuración que tengo en mi init.el es muy sencilla:

;;; Establecer prefijo para lsp-mode
(setq lsp-keymap-prefix "C-l")

;;; Configuración de lsp-mode
(require 'lsp-mode)
(add-hook 'python-mode-hook #'lsp)
(add-hook 'c++-mode-hook #'lsp)

La primera línea no necesita mucha explicación: establece como prefijo para los comandos de lsp la combinación C-l. Las dos últimas líneas indican que cuando se entre en los modos para programar en Python o c++ se lance el modo lsp. Como sabéis #' es un atajo para función en elisp. Lo que hace esa función es levantar el servidor y entrar en lsp-mode. Arrancar el servidor, puede llevar unos segundos. Además hay que añadir que al entrar en lsp-mode este configura de forma automática tanto lsp-ui como company-mode. Si se quiere retrasar el lanzamiento del servidor hasta que sea visible el contenido del buffer, se puede utilizar lsp-deferred en lugar de lsp.

Utilizando flymake, en su día, también definí un par de combinaciones para navegar por los errores y que vienen bien mientras programas con flymake activado:

(global-set-key (kbd "C-c f n") 'flymake-goto-next-error)
(global-set-key (kbd "C-c f p") 'flymake-goto-prev-error)

Como digo, en mi caso ya tenía algunas de estas herramientas configuradas y preparadas para trabajar. Pero para profundizar un poco haciendo pruebas y poder escribir este artículo he utilizado el lsp-mode con los dos lenguajes que dije antes. Aunque programo más en otros lenguajes y no uso para ellos esta herramienta.

Para más precisión en la configuración, es recomendable, que antes te leas detenidamente todas las opciones que hay en su web para ajustar todos los aspectos y comportamientos.

Captura-pantalla_lsp-cplusplus.png

En ambos lenguajes parece funcionar correctamente:

Captura-pantalla_lsp-python.png

Al menos todo lo bien en las pruebas que he hecho, que aunque no han sido exhaustivas ni durante demasiado tiempo, puedo asegurar que en ambos casos me ha funcionado el modo con soltura. Sin embargo, para usar lsp-mode con Python he tenido que instalar el paquete del servidor de lenguaje.

Instalando servidores de lenguaje

Como dije antes, para trabajar con C++ no necesité ningún paso intermedio, simplemente, instalé el modo y lo configuré como hemos visto antes. Automáticamente funcionó con ese lenguaje. No fue así con Python: abría un fichero .py, intentaba activar el modo lsp-mode y lanzaba un error. El problema lo pude resumir en que no encontraba el Language Server y tuve que instalarlo.

La instalación fue tan sencilla como abrir una consola y teclear:

pip install pyls

A partir de ese momento comenzó a funcionar lsp-mode. Estuve barajando también el instalar jedi-language-server, en lugar de pyls, pero implicaba que también había que instalar lsp~jedi en Emacs para funcionar y me pareció que ya eran demasiados paquetes sólo para hacer pruebas. La alternativa parece también válida e interesante, pero no quería liarlo más.

En todo esto de instalar o no servidores ls supongo que influye también el haber utilizado con ese lenguaje algún editor que ya soportaba de antes lsp y de tener instalado precisamente el que necesitas. De todas formas, también podemos encontrar que el mismo modo lsp puede instalar una serie de servidores con el comando lsp-install-server.

Es también conveniente echar un vistazo a todos los servidores soportados por lsp-mode y seguir las instrucciones para instalar el que nos convenga.

Funciones principales de lsp-mode

Las funciones principales, o que más se utilizan, vienen definidas a partir del atajo de teclado que hayamos establecido en la configuración. En mi caso utilizo como combinación base para lsp-mode el atajo C-l:

lsp-format-buffer
C-l = =, unifica el formato del buffer para unificar el aspecto y hacer el código más legible.
lsp-format-region
C-l = r. Da formato a la región seleccionada.
lsp-find-declaration
C-l g d, nos lleva a la declaración de una función, constante o variable.
lsp-find-definition
C-l g g, nos lleva donde esté definida la función, constante o variable.
lsp-find-references
C-l g r, nos muestra una lista de todas las apariciones y referencias de una función, constante o variable dentro del proyecto permitiéndonos saltar a ellas.
lsp-rename
C-l r r, renombra un identificador en todas sus apariciones.
lsp-workspace-shutdown
C-l s q, sale del espacio de trabajo cerrando el servidor y saliendo del modo.
lsp-workspace-restart
C-l s r, reinicia el espacio de trabajo.
lsp
C-l s s, lanza el espacio de trabajo levantando el servidor y entrando en el modo.

Hay más funciones que explorar pero esta es la lista de las que más he usado y que más útiles puede resultar.

Conclusión

El modo lsp-mode es bastante completo, pero al final se integra con otros modos y paquetes que ya puedes utilizar directamente en Emacs sin necesitarlo: como dired (para la gestión de directorios) o iedit (para escribir a la vez en varias zonas de un buffer), etc.

¿Qué aporta entonces lsp-mode a Emacs? Pues básicamente uniformidad entre lenguajes... Poco más que reseñar. Por ejemplo, toda la funcionalidad que proporciona lsp lo proporciona, por ejemplo, alchemist, el modo de programación para elixir, pero con sus atajos de teclas y sus idiosincrasias. Quizá también aporte que algunos programadores decidan pasarse a editores viejunos, pero potentes, que les proporcionen las mismas funcionalidades que los modernos pero sin tantos quebraderos de cabeza como las configuraciones: configuras mínimamente el editor, configuras lsp y todo funciona como esperas de un IDE.

Categoría: emacs lsp-mode programación

Comentarios

Debido a algunos ataques mailintencionados a través de la herramienta de comentarios, he decidido no proporcionar dicha opción en el Blog. Si alguien quiere comentar algo, me puede encontrar en Mastodon y en Diaspora con el nick de Notxor.

También se ha abierto un grupo en Telegram, para usuarios de esa red.

Disculpen las molestias.