Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/joaotavora/eglot

A client for Language Server Protocol servers
https://github.com/joaotavora/eglot

Last synced: 19 days ago
JSON representation

A client for Language Server Protocol servers

Awesome Lists containing this project

README

        

[![Build status](https://github.com/joaotavora/eglot/actions/workflows/test.yml/badge.svg)][build-status]
[![GNU ELPA](https://elpa.gnu.org/packages/eglot.svg)](https://elpa.gnu.org/packages/eglot.html)
[![MELPA](https://melpa.org/packages/eglot-badge.svg)](https://melpa.org/#/eglot)

# M-x Eglot

*E*macs Poly*glot* is the Emacs [LSP][lsp] client that stays out of
your way:

* 📽 Scroll down this README for some [pretty gifs](#animated_gifs)
* 📚 Read Eglot's [manual][manual] and [release notes][release-notes]
* 🏆 Folks over at Google [seem to like it][gospb]. Thanks!
* 👾 Eglot now lives in [Emacs itself](#emacscore)!

See also [eglot-x][eglot-x] for non-standard protocol extensions support.

# 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 development version from [GNU-Devel ELPA][gnudevelelpa]

First, configure this repository.
```lisp
(add-to-list 'package-archives '("gnu-devel" . "https://elpa.gnu.org/devel/"))
```

Then, use `M-x package-install` or `M-x package-update` to install
an ELPA package from the latest upstream.


# Contribute to Eglot's development

_**Eglot is now in Emacs's core!**_ Upcoming Emacs 29 will have `M-x
eglot` built-in.

The recommended way to experiment with changes to the latest Eglot is
to [compile][compile-emacs1] [Emacs][compile-emacs2]
[yourself][compile-emacs3-official].

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 targetting multiple relevant packages, not
just Eglot.

These `:core` packages (Eglot included) are then released periodically
to GNU ELPA, so users of other Emacs's versions can get them via
`M-x package-install`.

# Status of this GitHub repository

This repository is **not the development upstream anymore**, but it's
**not** dead (yet):

* It may be used to start [discussions][discussion].

Sometimes, it's possible the discussion or bug report will be moved
to [Emacs's bug tracker][emacs-bug-tracker-eglot]. You may take the
initiative and start discussion there using `M-x report-emacs-bug`
or simply sending mail to `[email protected]`.

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].


# 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]


# _Obligatory animated gif section_

## 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
![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
![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
![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
![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
![eglot-rename](./gif-examples/eglot-rename.gif)

Type `M-x eglot-rename RET` to rename the symbol at point.

## 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
![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

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](https://github.com/joaotavora/eglot/issues/180)
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`, not `M-x eglot-`. Also, there are no
`eglot-` extra packages.

- There's no "whitelisting" or "blacklisting" directories to
languages. `M-x eglot` starts servers to handle file of a major
mode inside a specific project, using Emacs's built-in `project.el`
library 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.el` needed);
- Smoother/more responsive (read below).

Under the hood:

- Message parser is much simpler.
- Defers signature requests like `textDocument/hover` until server is
ready.
- Sends `textDocument/didChange` for 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

`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://joaotavora.github.io/eglot
[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