Emacs y lsp-mode
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.
En ambos lenguajes parece funcionar correctamente:
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.
Comentarios