- Language Server Protocol Support for Emacs
- ❤️ Community Driven
- 💎 Fully featured - supports LSP core and Language Server non-standard extensions
- 🚀 Easy to configure - works out of the box and automatically upgrades if additional packages are present
- 🌟 Flexible - could be configured as full-blown IDE with flashy UI or minimal distraction free
Client for Language Server Protocol (v3.14). lsp-mode aims to provide IDE-like experience by providing optional integration with the most popular Emacs packages like company, flycheck and projectile.
- Non-blocking asynchronous calls
- Real-time Diagnostics/linting (via builtin
flymakewhen Emacs > 26 or flycheck/lsp-ui) - Code completion - using company-lsp or builtin
completion-at-point - Hovers - using lsp-ui
- Code actions - using
lsp-execute-code-actionor lsp-ui - Code outline - using builtin imenu or
helm-imenu - Code navigation - using builtin xref
- Code lens (references/implementations) - using builtin xref
- Highlights
- Formatting
- Debugger - dap-mode
- Helm integration - helm-lsp
The recommended way to install lsp-mode is via package.el - the built-in package manager in Emacs. lsp-mode is available on the two major package.el community maintained repos - MELPA Stable and MELPA.
M-x package-install [RET] lsp-mode [RET]
Check the table bellow with the list of supported servers and the corresponding instructions on how to install the server.
You could go minimal and use lsp-mode as it is without external packages with the built-in flymake and completion-at-point or you could install the following extensions for better experience:
- install lsp-ui for flycheck integration and higher level UI modules.
- install company-lsp if you want to use
company-modefor completion.
(require 'lsp-mode)
(add-hook 'XXX-mode-hook #'lsp)where XXX could be major mode like python, java, c++. Alternatively, if you want to minimize you configuration you may use prog-mode-hook. In case you do that, lsp will try to start for each programming mode and echo a message when there is no client registered for the current mode or if the corresponding server is not present. In addition, lsp-mode will automatically detect and configure lsp-ui and company-lsp. To turn off that behavior you could set lsp-auto-configure to nil.
lsp-mode is included in spacemacs develop branch. Add lsp to dotspacemacs-configuration-layers and configure the language that you want to use to be backed by lsp backend.
Replace (require 'lsp-mode) with the following if you use use-package.
(use-package lsp-mode
:commands lsp
:init
(setq ...))
(use-package lsp-ui :commands lsp-ui-mode)
(use-package company-lsp :commands company-lsp)lsp-mode has predefined list of server configurations (located in lsp-clients.el) containing a mapping from major-mode to the server configuration. In addition to the default server configuration located in lsp-clients.el there are few languages servers which require separate package(check Supported languages). When you open a file from a particular project lsp-mode and call lsp command lsp-mode will look for server registrations able to handle current major-mode. If there is such client lsp-mode will look for the project root. If you open a file from the project for the first time you will be prompted the project. Once the project is imported project root is saved in lsp-session file and it will be loaded the next time you start Emacs so you no longer will be asked for a project root when you open a file from that project. Later if you want to change the project root you may use lsp-workspace-folder-remove to remove the project and call lsp-workspace-folder-add to add the root. If you want to force starting a particular language server in a file you may use C-u M-x lsp which will prompt you to select language server to start.
Some of the servers are directly supported by lsp-mode by requiring
lsp-clients.el while other require installing additional package which provide
server specific functionality.
| Language | Language Server | Built-in | Installation command | Debugger |
|---|---|---|---|---|
| Bash | bash-language-server | Yes | npm i -g bash-language-server | |
| C++ | ccls | emacs-ccls | ccls | Yes (via llvm debug adapter) |
| C++ | clangd | Yes | clangd | Yes (via llvm debug adapter) |
| C++ | cquery | emacs-cquery | cquery | Yes (via llvm debug adapter) |
| CSS/LessCSS/SASS/SCSS | css | Yes | npm install -g vscode-css-languageserver-bin | |
| Dart | dart_language_server | Yes | pub global activate dart_language_server | |
| Elixir | elixir-ls | Yes | elixir-ls | Yes |
| Fortran | fortran-language-server | Yes | pip install fortran-language-server | |
| Go | bingo | Yes | bingo | |
| Groovy | groovy-language-server | Yes | groovy-language-server | |
| HTML | html | Yes | npm install -g vscode-html-languageserver-bin | |
| Haskell | IDE engine | lsp-haskell | IDE engine | |
| Java | Eclipse JDT LS | lsp-java | Automatic by lsp-java | Yes |
| JavaScript/TypeScript | typescript-language-server (recommended) | Yes | npm i -g typescript-language-server; npm i -g typescript | |
| JavaScript/TypeScript | javascript-typescript-stdio | Yes | npm i -g javascript-typescript-langserver | |
| JavaScript Flow | flow (add-on if working on a Flow file) | Yes | flow | |
| Ocaml | ocaml-language-server | Yes | ocaml-language-server | |
| PHP | php-language-server | Yes | php-language-server | Yes |
| Python | pyls | Yes | pip install ‘python-language-server[all]’ | Yes |
| Python(Microsoft) | Microsoft Python Language Server | lsp-python-ms | lsp-python-ms | Yes |
| Ruby | solargraph | Yes | gem install solargraph | Yes |
| Rust | rls | Yes | rls | Yes (via llvm debug adapter) |
| Scala | lsp-scala | lsp-scala | lsp-scala | |
| Swift | sourcekit-LSP | lsp-sourcekit | sourcekit-LSP | Yes (via llvm debug adapter) |
| Vue | vue-language-server | Yes | npm install -g vue-language-server |
lsp-describe-session- Display session folders and running servers.lsp-describe-thing-at-point- Display help for the thing at point.lsp-execute-code-action- Execute code action.lsp-format-buffer- Format current bufferlsp-goto-implementation- Go to implementationlsp-goto-type-definition- Go to type definitionlsp-rename- Rename symbol at pointlsp-restart-workspace- Restart projectlsp-symbol-highlight- Highlight all relevant references to the symbol under point.lsp-workspace-folders-add- Add workspace folderlsp-workspace-folders-remove- Remove workspace folderlsp-workspace-folders-switch- Switch workspace folderimenuorhelm-imenu- display document structure.completion-at-point- display completion using built-in emacscompletion-at-pointframework.lsp-find-definition- to find the definition for the symbol under point.lsp-find-references- Find references for the symbol under point.lsp-lens-show- Show lenses in the current filelsp-lens-hide- Hide lenses in the current filelsp-lens-mode(experimental) - Turn on/off lenses in the current file.lsp-save-logs- Save a trace of all messages to and from the language server to a given file. Only works whenlsp-save-logsis non-nil.
lsp-print-io- If non-nil, print all messages to and from the language server to*lsp-log*.lsp-trace- If non-nil, keep a trace of all messages to and from the language server, which can be saved to a file withlsp-save-logs.lsp-print-performance- If non-nil, print performance info. to*lsp-log*.lsp-inhibit-message- If non-nil, inhibit the message echo viainhibit-message.lsp-report-if-no-buffer- If non nil the errors will be reported even when the file is not open.lsp-keep-workspace-alive- If non nil keep workspace alive when the last workspace buffer is closed.lsp-enable-snippet- Enable/disable snippet completion support.lsp-auto-guess-root- Automatically guess the project root using projectile/project.lsp-restart- Defines how server exited event must be handled.lsp-session-file- Automatically guess the project root using projectile/project.lsp-auto-configure- Auto configurelsp-mode. When set to tlsp-modewill auto-configurelsp-uiandcompany-lsp.lsp-document-sync-method- How to sync the document with the language server.lsp-auto-execute-action- Auto-execute single action.lsp-eldoc-render-all- Define whether all of the returned bydocument/onHoverwill be displayed. Iflsp-markup-display-allis set to nileldocwill show only the symbol information.lsp-enable-completion-at-point- Enablecompletion-at-pointintegration.lsp-enable-xref- Enable xref integration.lsp-prefer-flymake- If you prefer flycheck andlsp-ui-flycheckis available,(setq lsp-prefer-flymake nil). If set to:noneneither of two will be enabled.lsp-enable-indentation- Indent regions using the file formatting functionality provided by the language server.lsp-enable-on-type-formatting- EnabletextDocument/onTypeFormattingintegration.lsp-before-save-edits- If non-nil,lsp-modewill apply edits suggested by the language server before saving a document.lsp-imenu-show-container-name- Display the symbol’s container name in an imenu entry.lsp-imenu-container-name-separator- Separator string to use to separate the container name from the symbol while displaying imenu entries.lsp-imenu-sort-methods- How to sort the imenu items. The value is a list ofkind,nameorposition. Priorities are determined by the index of the element.lsp-response-timeout- Number of seconds to wait for a response from the language server before timing out.
- RUST Completion with company-lsp

- Typescript references using lsp-ui

- Debugging Python using dap-mode

- Call hierarchy via ccls

LSP mode has support for tramp buffers with the following requirements.
- The language server have to be present on the remote server since it is running on the remote machine.
- Having multi folder language server (like Eclipse JDT LS) cannot have local and remote servers.
lsp-mode detects whether a particular file is located on remote machine and looks for a client which can handle the current major mode and it is marked as :remote? t. Then lsp-mode starts the client through tramp.
Here it is example how you can configure python language server to work when using TRAMP.
(lsp-register-client
(make-lsp-client :new-connection (lsp-tramp-connection "pyls")
:major-modes '(python-mode)
:remote? t
:server-id 'pyls))- set
lsp-print-iototto inspect communication between client and the server. lsp-describe-sessionwill show the current projects roots + the started severs and allows inspecting the server capabilities.
Here it is the minimal configuration that is needed for new language server registration. Refer to the documentation of lsp-client.el for the additional settings supported on registration time. lsp-language-id-configuration must be updated to contain the corresponding mode -> language id - in this case (python-mode . "python")
(lsp-register-client
(make-lsp-client :new-connection (lsp-stdio-connection "pyls")
:major-modes '(python-mode)
:server-id 'pyls))- How to configure a server with local variables?
Add
lspserver call tohack-local-variables-hookwhich runs right after the local variables are loaded.(add-hook 'hack-local-variables-hook (lambda () (when (derived-mode-p 'XXX-mode) (lsp))))
- I have multiple language servers registered for language FOO. Which one will be used when opening a project?
The one with highest priority wins.
lsp-clients.elpredefined servers have priority -1, lower than external packages (priority 0 if unspecified). If a server is registered with:add-on?flag set totit will be started in parallel to the other servers that are registered for the current mode.

