eglot: lsp para Emacs
En las últimas versiones de Emacs se ha añadido eglot1 a los paquetes instalados por defecto. En este artículo hablaré sobre esto y sobre LSP2.

Hace unos días en el grupo de XMPP donde comentamos cosas, no sólo
hablamos sobre el blog, Mester lanzó una pregunta sobre la
configuración de eglot
, sobre si es mejor que lsp-mode
y prometí
probar el primero y comentarlo en un artículo. Ya lo adelanté en el
grupo, en su día lsp-mode
no terminó de convencerme y eglot
está
siguiendo los mismos pasos.
Por qué no me llaman la atención eglot y lsp
De momento me encuentro cómodo con la flexibilidad que proporcionan
las herramientas que he venido utilizando empleando hasta ahora y me
parece que depender de un servicio externo al editor, no tiene por
qué mejorar la experiencia de uso. Al contrario, me encontré cuando
probé lsp-mode
que al levantar el modo LSP para erlang
se caía
el modo LSP para Python. Se puede solventar reiniciando el
servidor lsp o utilizando sólo un lenguaje en la misma sesión o como
en mi caso, no utilizando LSP, porque Emacs ya proporciona todas
esas herramientas sin necesidad de contar con un servidor externo.
Por otro lado, por lo que vi en lsp-mode
y por lo que veo en
eglot
, las herramientas que utilizan para hacer su trabajo son las
mismas que utilizan los modos de Emacs: ElDoc
, Flymake
, Xref
,
Imenu
... Es decir, tampoco me ahorra espacio en disco. Y si
comparamos la información que ofrece, por ejemplo la documentación que
muestran eldoc
y elpy
:

con la correspondiente con eglot
:

... no sé si rinden las ganancias o no. El que se muestre en el
mini-buffer
o en un frame depende del paquete eldoc-box
, que no
lo uso habitualmente, porque me he acostumbrado a eldoc
sin él.
Si alguien tiene curiosidad, para hacer las pruebas he instalado en mi
OpenSuse Tumbleweed el paquete pylsp
para que estuviera disponible
y he cambiado la configuración para que en python-mode
, cargue
eglot
. Por esto, toda la disertación la haré sobre las pruebas que
he hecho en ese lenguaje y sus herramientas de edición en Emacs.
Las pruebas las he metido en un archivo de configuración muy escueto y
básico: inicio.el
, para no estropear mi init.el
:
(add-to-list 'load-path "~/.emacs.d/site-packages") (add-to-list 'load-path "~/.emacs.d/elpa") (add-to-list 'load-path "~/.emacs.d/elpa/ivy-20230714.751") (add-to-list 'load-path "~/.emacs.d/elpa/swiper-20230410.1815") (add-to-list 'load-path "~/.emacs.d/elpa/counsel-20230619.1623") (add-to-list 'load-path "~/.emacs.d/elpa/company-20230703.2021") (add-to-list 'load-path "~/.emacs.d/elpa/eldoc-box-20230810.503") (add-to-list 'load-path "~/.emacs.e/elpa/eglot-1.15") (require 'ivy) (require 'swiper) (require 'counsel) (require 'company) (require 'eldoc-box) (require 'eglot) (ivy-mode 1) (setq global-company-mode t) (add-hook 'python-mode 'eglot) (add-hook 'eglot-managed-mode-hook #'eldoc-box-hover-mode t)
Primero le doy todos los paths a los paquetes que utilizo y después los cargo y configuro mínimamente.
Después, para arrancar Emacs con ese fichero lo llamo desde línea de comandos, en el directorio donde se encuentra el fichero de inicio:
emacs -q -l inicio.el
Lenguajes soportados por eglot
Sin configurar nada, eglot
, soporta la siguiente lista de servidores
LSP:
- Ada: ada_language_server
- Bash: bash-language-server
- C/C++: clangd o ccls
- C#: omnisharp
- Clojure: clojure-lsp
- CMake: cmake-language-server
- CSS: css-languageserver
- Dart: analysis_server
- Dockerfile: docker-langserver
- Elixir: elixir-ls
- Elm: elm-language-server
- Erlang: erlang_ls
- Fortran: fortls
- Futhark: futhark lsp
- Go: gopls
- Godot Engine: built-in LSP
- HTML html-languageserver
- Haskell: haskell-language-server
- JSON: vscode-json-languageserver
- Java: Eclipse JDT Language Server
- Javascript: TS & JS Language Server
- Kotlin: kotlin-language-server
- Lua: lua-lsp
- Markdown: marksman
- Mint: mint-ls
- Nix: rnix-lsp
- Ocaml: ocaml-lsp
- Perl: Perl::LanguageServer
- PHP: php-language-server
- PureScript: purescript-language-server
- Python: pylsp, pyls pyright, o jedi-language-server
- R: languageserver
- Racket: racket-langserver
- Ruby: solargraph
- Rust: rust-analyzer
- Scala: metals
- TeX/LaTeX: Digestif</a> ot [[https://github.com/latex-lsp/texlab][texlab
- VimScript: vim-language-server
- YAML: yaml-language-server
- Zig: zls
Con estos lenguajes no hace falta hacer nada más que lanzar eglot
en
el modo correspondiente (y tener instalado el servidor externo, claro).
Por ejemplo, para configurar el modo de Python, como vimos antes,
podemos utilizar sólamente el hook
:
(add-hook 'python-mode 'eglot-ensure)
Características
- Documentación en el punto: cuando el cursor se encuentra sobre un
identificador se muestra información del mismo en el
mini-buffer
, para ello utiliza el paqueteeldoc
. Si además tenemos instalado el paquetemarkdown-mode
nos mostrará dicha documentación con negritas, cursivas y demás. Si no te acostumbras a que la información se muestre en elmini-buffer
y quieres que lo muestre en un desplegable, puedes descargarte el paqueteeldoc-box
y configurarlo para que muestre la información junto al cursos o arriba a la izquierda o arriba a la derecha. - Comprobación al vuelo de errores: En este caso utiliza el paquete
flymake
. Es decir, la comprobación de errores la hace este paquete y noeglot
. - Buscar definiciones o implementación del código: En este caso
utiliza el paquete
xref
. Si lo tienes bien configurado basta con pulsarM-.
para ir a la definición yM-,
para regresar al punto anterior. Como ocurre con las características anteriores, esxref
quien hace el trabajo. - Navegar por el fichero por los nombres de función, de clase, de
métodos, etc. lo realiza con el paquete
imenu
. En mi caso, está configurado enM-p i
, muestra la lista en elmini-buffer
y permite saltar rápidamente entre funciones, clases, métodos... no sólo eso. También lo tengo activado enorg-mode
y me permite saltar entre las cabeceras del documento de una manera bastante cómoda. - Completion. En este caso
eglot
utiliza el paquete de Emacs, Symbol Completion, que es la versión de completado mediante buffer que viene por defecto con el editor. Pero si encuentra instalado algún tipo de paquete de completado comocompany-mode
, lo utilizará para mostrar la lista de alternativas, en lugar del otro paquete más básico. - Para insertar plantillas de código utiliza
yasnippet
. En mi caso además tengo instaladoivy-yasnippet
que le proporciona más interactividad a la hora de seleccionar el snippet que quieres cargar. - Para gestión de proyectos utiliza el paquete built-in
project
.
Muchos de estos paquetes son internos y básicos para la programación, algunos no los he traído al blog, pero sobre otros ya he hablado aquí.
De todas las funciones o comandos que he estado mirando y probando con
eglot
sólo no he encontrado alguna función ya instalada para el
comando eglot-rename
, que renombra la variable o función en todos
los archivos del proyecto que se gestionen con el servidor LSP. Lo
más parecido que tengo instalado y utilizo habitualmente es el paquete
iedit
o cursor múltiple, que modifica el nombre en todas las
apariciones de un archivo. Supongo que para esta función se podría
utilizar el paquete emr
, el Emacs refactoring system, que no tengo
instalado, pero sí ganas de probarlo.
Conclusiones
He intentado también configurar un servidor que no viniera en la lista
de los configurados por defecto. Elegí el alive-lsp
para Common
Lisp, pero he sido incapaz. Tampoco lo pude configurar para Kate,
otro editor que soporta LSP. También puedes observar que hay un
puñado de paquetes lsp-[lenguaje]
para configurar otros servidores
que no vienen por defecto.
De momento, para mí, Emacs provee todas las herramientas necesarias
para programar sin necesidad de LSP. Los modos de Emacs, como
slime
(para Common Lisp), cider
(para Clojure), geiser
(para
Scheme), edts
(para erlang
), elpy
(para Python) son
suficientes para lo que hago yo y además me proporcionan ayuda con
C-h i
en la mayoría de los casos.
Comentarios