joaotavora/eglot
{ "createdAt": "2017-08-16T01:41:16Z", "defaultBranch": "master", "description": "A client for Language Server Protocol servers", "fullName": "joaotavora/eglot", "homepage": null, "language": "Emacs Lisp", "name": "eglot", "pushedAt": "2025-10-29T15:47:20Z", "stargazersCount": 2436, "topics": [], "updatedAt": "2025-11-26T20:16:15Z", "url": "https://github.com/joaotavora/eglot"}M-x Eglot
Section titled “M-x Eglot”Emacs Polyglot is the Emacs [LSP][lsp] client that stays out of your way:
- 📽 Scroll down this README for some pretty gifs
- 📚 Read Eglot’s [manual][manual] and [release notes][release-notes]
- 🏆 Folks over at Google [seem to like it][gospb]. Thanks!
- ✨ Get the stable or the latest version
- 👾 Eglot now lives in Emacs itself! Learn how to contribute!
Also see [eglot-x][eglot-x] for non-standard protocol extensions support.
Get stable [GNU ELPA][gnuelpa] version
Section titled “Get stable [GNU ELPA][gnuelpa] version”Just type M-x package-install RET eglot RET into Emacs 26.3+.
Now find some source file, any source file, and type M-x eglot.
That’s it. If you’re lucky, this guesses the LSP program to start for the language you’re using. Otherwise, it prompts you to enter one.
Get latest [GNU-Devel ELPA][gnudevelelpa] version
Section titled “Get latest [GNU-Devel ELPA][gnudevelelpa] version”First, configure GNU-Devel ELPA as your ELPA source repository.
(add-to-list 'package-archives '("gnu-devel" . "https://elpa.gnu.org/devel/"))Then, use M-x package-install or M-x package-update as before install
an ELPA package from the latest upstream. You will be running the same
Eglot version as if you were running Emacs master!
M-x eglot-upgrade-eglot should also work if you have already installed
it.
Connecting to a server
Section titled “Connecting to a server”These are just some of the servers that M-x eglot can use out of the
box. The full list can be consulted in the eglot-server-programs
variable, where you can [easily add your own servers][manual].
- Ada’s [ada_language_server][ada_language_server]
- Bash’s [bash-language-server][bash-language-server]
- C/C++‘s [clangd][clangd] or [ccls][ccls]
- C#‘s [omnisharp][omnisharp]
- Clojure’s [clojure-lsp][clojure-lsp]
- CMake’s [cmake-language-server][cmake-language-server]
- CSS’s [css-languageserver][css-languageserver]
- Dart’s [analysis_server][dart-analysis-server]
- Dockerfile’s [docker-langserver][docker-langserver]
- Elixir’s [elixir-ls][elixir-ls]
- Elm’s [elm-language-server][elm-language-server]
- Erlang’s [erlang_ls][erlang_ls]
- Fortran’s [fortls][fortls]
- Futhark’s [futhark lsp][futhark-lsp]
- Go’s [gopls][gopls]
- Godot Engine’s [built-in LSP][godot]
- HTML [html-languageserver][html-languageserver]
- Haskell’s [haskell-language-server][haskell-language-server]
- JSON’s [vscode-json-languageserver][vscode-json-languageserver]
- Java’s [Eclipse JDT Language Server][eclipse-jdt]
- Javascript’s [TS & JS Language Server][typescript-language-server]
- Kotlin’s [kotlin-language-server][kotlin-language-server]
- Lua’s [lua-lsp][lua-lsp]
- Markdown’s [marksman][marksman]
- Mint’s [mint-ls][mint-ls]
- Nix’s [rnix-lsp][rnix-lsp]
- Ocaml’s [ocaml-lsp][ocaml-lsp]
- Perl’s [Perl::LanguageServer][perl-language-server]
- PHP’s [php-language-server][php-language-server]
- PureScript’s [purescript-language-server][purescript-language-server]
- Python’s [pylsp][pylsp], [pyls][pyls] [pyright][pyright], or [jedi-language-server][jedi-language-server]
- R’s [languageserver][r-languageserver]
- Racket’s [racket-langserver][racket-langserver]
- Ruby’s [solargraph][solargraph]
- Rust’s [rust-analyzer][rust-analyzer]
- Scala’s [metals][metals]
- TeX/LaTeX’s [Digestif][digestif] ot [texlab][texlab]
- VimScript’s [vim-language-server][vim-language-server]
- YAML’s [yaml-language-server][yaml-language-server]
- Zig’s [zls][zls]
Eglot is in Emacs’s core since Emacs 29!
Section titled “Eglot is in Emacs’s core since Emacs 29!”⚠️ This repository is not the development upstream anymore ⚠️
It’s not dead (yet 🧟)
-
Pull requests won’t be merged. You can still use them to show ideas for patches. See below for how to properly contribute.
-
You can start a [discussion][discussion]
Say what is on your mind. It’s possible discussion or bug report will be moved to [Emacs’s bug tracker][emacs-bug-tracker-eglot]. You may jump straight to that forum using
M-x report-emacs-bugor simply sending mail tobug-gnu-emacs@gnu.org.Please the [Eglot-specific bug-reporting instructions][bug-reporting].
-
The [
eglot.el][eglot.el] file here is periodically updated to mirror the [Emacs upstream][upstream-eglot.el] -
The existing tests of [
eglot-tests.el][eglot-tests.el], also periodically updated, may be used to rehearse and validate patches using [GitHub CI infrastructure][build-status].
Contribute to Eglot’s development
Section titled “Contribute to Eglot’s development”Contributing to Eglot is done by contributing to the Emacs project. Read below for how Eglot fits in and how to quickly submit a patch.
Understanding :core packages
Section titled “Understanding :core packages”From a development perspective, moving to core allows us to work on Eglot in tandem with other related packages already in Emacs, such as [Flymake][flymake], [ElDoc][eldoc], [Xref][xref], [Project][project].
This means adding or tweaking an Emacs LSP feature is a matter of submitting a single patch to Emacs targetting multiple relevant packages, not just Eglot. You may even propose a new package altogether.
These — Eglot included — are so-called :core packages. They
are released periodically to GNU ELPA, so users of older Emacs
versions can get all the goodies via M-x package-install.
Actually submitting a patch
Section titled “Actually submitting a patch”The recommended way to experiment with changes to the code is to compile Emacs from a Git repo like this one or this one. Here are [three][compile-emacs1] [separate][compile-emacs2] [guides][compile-emacs3-official] for doing so.
When you are content with your tweaks to Eglot (and/or its sibling
:core packages), submit your patch 💪via email💪 to
bug-gnu-emacs@gnu.org. You may CC the authors/maintainers of
packages if you know their emails, but it isn’t strictly necessary.
We’ll guide you if any more steps are needed (like copyright
assignments, etc).
Obligatory animated gif section
Section titled “Obligatory animated gif section”Completion
Section titled “Completion”![eglot-completions]!(./gif-examples/eglot-completions.gif)
The animation shows [company-mode][company] presenting the completion
candidates to the user, but Eglot works with the built-in
completion-at-point function as well, which is usually bound to
C-M-i.
Snippet completion
Section titled “Snippet completion”![eglot-snippets-on-completion]!(./gif-examples/eglot-snippets-on-completion.gif)
Eglot provides template based completion if the server supports
snippet completion and [yasnippet][yasnippet] is enabled before
Eglot connects to the server. The animation shows
[company-mode][company], but completion-at-point also works with
snippets.
Diagnostics
Section titled “Diagnostics”![eglot-diagnostics]!(./gif-examples/eglot-diagnostics.gif)
Eglot relays the diagnostics information received from the LSP server
to Emacs’s [Flymake][flymake], which annotates/underlines the
problematic parts of the buffer. The information is shared with the
[ElDoc][eldoc] system, meaning that the commands eldoc and
eldoc-doc-buffer (the latter bound to C-h-. for convenience) show
diagnostics along with other documentation under point.
[Flymake][flymake] provides other convenient ways to view and manage diagnostic errors. These are described in its [manual][flymake].
When Eglot manages a buffer, it disables pre-existing Flymake
backends. See variable eglot-stay-out-of to change that.
Code Actions
Section titled “Code Actions”![eglot-code-actions]!(./gif-examples/eglot-code-actions.gif)
The LSP server may provide code actions, for example, to fix a
diagnostic error or to suggest refactoring edits. The commands are
frequently associating with Flymake diagnostic annotations, so that
left-clicking them shows a menu. Additionally, the command
eglot-code-actions asks the server for any code spanning a given
region.
Sometimes, these code actions are initiated by the server. See
eglot-confirm-server-initiated-edits to control that behaviour.
Hover on symbol /function signature
Section titled “Hover on symbol /function signature”![eglot-hover-on-symbol]!(./gif-examples/eglot-hover-on-symbol.gif)
Here, too, the LSP server’s view of a given symbol or function
signature is relayed to the [ElDoc][eldoc] system. The commands
eldoc and eldoc-doc-buffer commands access that information.
There are customization variables to help adjust [ElDoc][eldoc]‘s
liberal use of the lower “echo area”, among other options. If you
still find the solicitous nature of this LSP feature too distracing,
you can use eglot-ignored-server-capabilities to turn it off.
Rename
Section titled “Rename”![eglot-rename]!(./gif-examples/eglot-rename.gif)
Type M-x eglot-rename RET to rename the symbol at point.
Find definition
Section titled “Find definition”![eglot-xref-find-definition]!(./gif-examples/eglot-xref-find-definition.gif)
To jump to the definition of a symbol, use the built-in
xref-find-definitions command, which is bound to M-..
Find references
Section titled “Find references”![eglot-xref-find-references]!(./gif-examples/eglot-xref-find-references.gif)
Eglot here relies on Emacs’ built-in functionality as well.
xref-find-references is bound to M-?. Additionally, Eglot
provides the following similar commands: eglot-find-declaration,
eglot-find-implementation, eglot-find-typeDefinition.
Historical differences to lsp-mode.el
Section titled “Historical differences to lsp-mode.el”Around May 2018, I wrote a comparison of Eglot to lsp-mode.el, and
was discussed with its then-maintainer. That mode has since been
refactored/rewritten and now
purports to support
a lot of features that differentiated Eglot from it. It may now be
very different or very similar to Eglot, or even sing with the birds
in the trees, so [go check it out][emacs-lsp]. That said, here’s the
original comparison, which I will not be updating any more.
“Eglot is considerably less code and hassle than lsp-mode.el. In most cases, there’s nothing to configure. It’s a minimalist approach focused on user experience and performance.
User-visible differences:
-
The single most visible difference is the friendly entry point
M-x eglot, notM-x eglot-<language>. Also, there are noeglot-<language>extra packages. -
There’s no “whitelisting” or “blacklisting” directories to languages.
M-x eglotstarts servers to handle file of a major mode inside a specific project, using Emacs’s built-inproject.ellibrary to discover projects. Then it automatically detects current and future opened files under that project and syncs with server; -
Easy way to quit/restart a server, just middle/right click on the connection name;
-
Pretty interactive mode-line section for live tracking of server communication;
-
Automatically restarts frequently crashing servers;
-
Slow-to-start servers start asynchronously in the background;
-
Server-initiated edits are confirmed with the user;
-
Diagnostics work out-of-the-box (no
flycheck.elneeded); -
Smoother/more responsive (read below).
Under the hood:
- Message parser is much simpler.
- Defers signature requests like
textDocument/hoveruntil server is ready. - Sends
textDocument/didChangefor groups of edits, not one per each tiny change. - Easier to read and maintain elisp. Yeah I know, very subjective, so judge for yourself.
- Doesn’t require anything other than Emacs, but will automatically
upgrade to work with stuff outside Emacs, like
company,markdown-mode, if you happen to have these installed. - Has automated tests that check against actual LSP servers.”
Copyright Assignment
Section titled “Copyright Assignment”Eglot is subject to the same [copyright assignment][copyright-assignment]
policy as GNU Emacs.
Any [legally significant][legally-significant] contributions can only be merged after the author has completed their paperwork. Please ask for the request form, and we’ll send it to you.
[ada_language_server] !: https://github.com/AdaCore/ada_language_server [bash-language-server] !: https://github.com/mads-hartmann/bash-language-server [clangd] !: https://clang.llvm.org/extra/clangd.html [omnisharp] !: https://github.com/OmniSharp/omnisharp-roslyn [clojure-lsp] !: https://clojure-lsp.io [cmake-language-server] !: https://github.com/regen100/cmake-language-server [css-languageserver] !: https://github.com/hrsh7th/vscode-langservers-extracted [dart-analysis-server] !: https://github.com/dart-lang/sdk/blob/master/pkg/analysis_server/tool/lsp_spec/README.md [elixir-ls] !: https://github.com/elixir-lsp/elixir-ls [elm-language-server] !: https://github.com/elm-tooling/elm-language-server [fortls] !: https://github.com/hansec/fortran-language-server [futhark-lsp] !: https://futhark-lang.org [gopls] !: https://github.com/golang/tools/tree/master/gopls [godot] !: https://godotengine.org [html-languageserver] !: https://github.com/hrsh7th/vscode-langservers-extracted [haskell-language-server] !: https://github.com/haskell/haskell-language-server [jedi-language-server] !: https://github.com/pappasam/jedi-language-server [vscode-json-languageserver] !: https://github.com/hrsh7th/vscode-langservers-extracted [eclipse-jdt] !: https://github.com/eclipse/eclipse.jdt.ls [typescript-language-server] !: https://github.com/theia-ide/typescript-language-server [kotlin-language-server] !: https://github.com/fwcd/KotlinLanguageServer [lua-lsp] !: https://github.com/Alloyed/lua-lsp [marksman] !: https://github.com/artempyanykh/marksman [mint-ls] !: https://www.mint-lang.com/ [rnix-lsp] !: https://github.com/nix-community/rnix-lsp [ocaml-lsp] !: https://github.com/ocaml/ocaml-lsp/ [perl-language-server] !: https://github.com/richterger/Perl-LanguageServer [php-language-server] !: https://github.com/felixfbecker/php-language-server [purescript-language-server] !: https://github.com/nwolverson/purescript-language-server [pyls] !: https://github.com/palantir/python-language-server [pylsp] !: https://github.com/python-lsp/python-lsp-server [pyright] !: https://github.com/microsoft/pyright [r-languageserver] !: https://cran.r-project.org/package=languageserver [racket-langserver] !: https://github.com/jeapostrophe/racket-langserver [solargraph] !: https://github.com/castwide/solargraph [rust-analyzer] !: https://github.com/rust-analyzer/rust-analyzer [metals] !: https://scalameta.org/metals/ [digestif] !: https://github.com/astoff/digestif [texlab] !: https://github.com/latex-lsp/texlab [vim-language-server] !: https://github.com/iamcco/vim-language-server [yaml-language-server] !: https://github.com/redhat-developer/yaml-language-server [zls] !: https://github.com/zigtools/zls
[manual] !: https://elpa.gnu.org/devel/doc/eglot.html [lsp] !: https://microsoft.github.io/language-server-protocol/ [company-mode] !: https://github.com/company-mode/company-mode [ccls] !: https://github.com/MaskRay/ccls [cquery] !: https://github.com/cquery-project/cquery [docker-langserver] !: https://github.com/rcjsuen/dockerfile-language-server-nodejs [emacs-lsp-plugins] !: https://github.com/emacs-lsp [emacs-lsp] !: https://github.com/emacs-lsp/lsp-mode [erlang_ls] !: https://github.com/erlang-ls/erlang_ls [gnuelpa] !: https://elpa.gnu.org/packages/eglot.html [gnudevelelpa] !: https://elpa.gnu.org/devel/eglot.html [melpa] !: https://melpa.org/#/eglot [news] !: https://github.com/joaotavora/eglot/blob/master/NEWS.md [windows-subprocess-hang] !: https://www.gnu.org/software/emacs/manual/html_node/efaq-w32/Subprocess-hang.html [company] !: https://elpa.gnu.org/packages/company.html [flymake] !: https://www.gnu.org/software/emacs/manual/html_node/flymake/index.html#Top [xref] !: https://www.gnu.org/software/emacs/manual/html_node/emacs/Xref.html [imenu] !: https://www.gnu.org/software/emacs/manual/html_node/emacs/Imenu.html [eldoc] !: https://github.com/emacs-mirror/emacs/blob/master/lisp/emacs-lisp/eldoc.el [yasnippet] !: https://elpa.gnu.org/packages/yasnippet.html [markdown] !: https://github.com/defunkt/markdown-mode [gospb] !: https://opensource.googleblog.com/2020/10/announcing-latest-google-open-source.html [copyright-assignment] !: https://www.fsf.org/licensing/contributor-faq [legally-significant] !: https://www.gnu.org/prep/maintain/html_node/Legally-Significant.html#Legally-Significant [dir-locals-emacs-manual] !: https://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-Variables.html [configuration-request] !: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_configuration [did-change-configuration] !: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_didChangeConfiguration [json-serialize] !: https://www.gnu.org/software/emacs/manual/html_node/elisp/Parsing-JSON.html [plist] !: https://www.gnu.org/software/emacs/manual/html_node/elisp/Property-Lists.html [discussion] !: https://github.com/joaotavora/eglot/discussions [upstream-eglot.el] !: https://github.com/emacs-mirror/emacs/blob/master/lisp/progmodes/eglot.el [eglot.el] !: https://github.com/joaotavora/eglot/blob/master/eglot.el [eglot-tests.el] !: https://github.com/joaotavora/eglot/blob/master/eglot-tests.el [announcement] !: https://github.com/joaotavora/eglot/discussions [compile-emacs1] !: https://lars.ingebrigtsen.no/2014/11/13/welcome-new-emacs-developers/ [compile-emacs2] !: https://batsov.com/articles/2021/12/19/building-emacs-from-source-with-pgtk/ [compile-emacs3-official] !: https://github.com/emacs-mirror/emacs/blob/master/INSTALL [emacs-bug-tracker-eglot] !: https://debbugs.gnu.org/cgi/pkgreport.cgi?include=subject%3Aeglot;package=emacs [bug-reporting] !: https://joaotavora.github.io/eglot/#Troubleshooting-Eglot [project] !: https://www.gnu.org/software/emacs/manual/html_node/emacs/Projects.html [emacs-upstream] !: https://github.com/emacs-mirror/emacs [release-notes] !: https://github.com/emacs-mirror/emacs/blob/master/etc/EGLOT-NEWS [build-status] !: https://github.com/joaotavora/eglot/actions/workflows/test.yml [eglot-x] !: https://github.com/nemethf/eglot-x