[[https://melpa.org/#/lsp-mode][file:https://melpa.org/packages/lsp-mode-badge.svg]]
[[https://stable.melpa.org/#/lsp-mode][file:https://stable.melpa.org/packages/lsp-mode-badge.svg]]
[[https://gitter.im/emacs-lsp/lsp-mode][file:https://badges.gitter.im/emacs-lsp/lsp-mode.svg]]
[[https://travis-ci.org/emacs-lsp/lsp-mode][file:https://travis-ci.org/emacs-lsp/lsp-mode.svg?branch=master]]
* Language Server Protocol Support for Emacs
  #+caption: LSP mode
  [[file:examples/head.png]]

** Table of Contents                                      :TOC_4_gh:noexport:
- [[#language-server-protocol-support-for-emacs][Language Server Protocol Support for Emacs]]
  - [[#why][Why?]]
  - [[#overview][Overview]]
  - [[#installation][Installation]]
    - [[#install-via-melpa][Install via melpa]]
  - [[#configuration][Configuration]]
    - [[#install-language-server][Install language server]]
    - [[#configure-lsp-mode][Configure lsp-mode]]
      - [[#vanilla-emacs][Vanilla Emacs]]
      - [[#spacemacs][Spacemacs]]
      - [[#use-package][use-package]]
    - [[#how-it-works][How it works?]]
  - [[#supported-languages][Supported languages]]
  - [[#commands][Commands]]
  - [[#settings][Settings]]
  - [[#screenshots][Screenshots]]
  - [[#extensions][Extensions]]
    - [[#tramp-experimental][TRAMP (Experimental)]]
      - [[#how-it-works-1][How it works?]]
      - [[#sample-configuration][Sample configuration]]
  - [[#troubleshooting][Troubleshooting]]
  - [[#adding-support-for-languages][Adding support for languages]]
  - [[#faq][FAQ]]
  - [[#see-also][See also]]

** Why?
   - ❤️ *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
** Overview
   Client for [[https://github.com/Microsoft/language-server-protocol/][Language Server Protocol]] (v3.14). [[https://github.com/emacs-lsp/lsp-mode][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 ~flymake~ when Emacs > 26 or [[https://github.com/flycheck/flycheck][flycheck]]/[[https://github.com/emacs-lsp/lsp-ui][lsp-ui]])
   - Code completion - using [[https://github.com/tigersoldier/company-lsp][company-lsp]] or builtin ~complete-at-point~
   - Hovers - using [[https://github.com/emacs-lsp/lsp-ui][lsp-ui]]
   - Code actions - using ~lsp-execute-code-action~ or [[https://github.com/emacs-lsp/lsp-ui][lsp-ui]]
   - Code outline - using builtin [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Imenu.html][imenu]] or ~helm-imenu~
   - Code navigation - using builtin [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Xref.html][xref]]
   - Code lens (references/implementations) - using builtin [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Xref.html][xref]]
   - Highlights
   - Formatting
   - Debugger - [[https://github.com/yyoncho/dap-mode/][dap-mode]]
   - Helm integration - [[https://github.com/yyoncho/helm-lsp/][helm-lsp]]
** Installation
*** Install via melpa
    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 - [[http://stable.melpa.org][MELPA Stable]] and [[http://melpa.org][MELPA]].

    M-x ~package-install~ [RET] ~lsp-mode~ [RET]
** Configuration
*** Install language server
    Check the table bellow with the list of supported servers and the corresponding instructions on how to install the server.
*** Configure lsp-mode
**** Vanilla Emacs
     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 [[https://github.com/emacs-lsp/lsp-ui][lsp-ui]] for [[https://github.com/flycheck/flycheck][flycheck]] integration and higher level UI modules.
     - install [[https://github.com/tigersoldier/company-lsp][company-lsp]] if you want to use ~company-mode~ for completion.
     #+BEGIN_SRC emacs-lisp
       (require 'lsp-mode)
       (add-hook 'XXX-mode-hook #'lsp)
     #+END_SRC
     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 [[https://github.com/emacs-lsp/lsp-ui][lsp-ui]] and [[https://github.com/tigersoldier/company-lsp][company-lsp]]. To turn off that behavior you could set ~lsp-auto-configure~ to ~nil~.

**** Spacemacs
     [[https://github.com/emacs-lsp/lsp-mode][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.
**** use-package
     Replace ~(require 'lsp-mode)~ with the following if you use use-package.
     #+BEGIN_SRC emacs-lisp
       (use-package lsp-mode
         :commands lsp
         :init
         (setq ...))

       (use-package lsp-ui :commands lsp-ui-mode)
       (use-package company-lsp :commands company-lsp)
     #+END_SRC
*** How it works?
    ~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][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.
** Supported languages
   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                  | [[https://github.com/mads-hartmann/bash-language-server][bash-language-server]]                      | Yes           | npm i -g bash-language-server                 |                              |
   | C++                   | [[https://github.com/MaskRay/ccls][ccls]]                                      | [[https://github.com/MaskRay/emacs-ccls][emacs-ccls]]    | [[https://github.com/MaskRay/ccls][ccls]]                                          | Yes (via llvm debug adapter) |
   | C++                   | [[https://clang.llvm.org/extra/clangd.html][clangd]]                                    | Yes           | [[https://clang.llvm.org/extra/clangd.html][clangd]]                                        | Yes (via llvm debug adapter) |
   | C++                   | [[https://github.com/cquery-project/cquery][cquery]]                                    | [[https://github.com/cquery-project/emacs-cquery][emacs-cquery]]  | [[https://github.com/cquery-project/cquery][cquery]]                                        | Yes (via llvm debug adapter) |
   | CSS                   | [[https://github.com/vscode-langservers/vscode-css-languageserver-bin][css]]                                       | Yes           | npm install -g vscode-css-languageserver-bin  |                              |
   | Dart                  | [[https://github.com/natebosch/dart_language_server][dart_language_server]]                      | Yes           | pub global activate dart_language_server      |                              |
   | Elixir                | [[https://github.com/JakeBecker/elixir-ls][elixir-ls]]                                 | Yes           | [[https://github.com/JakeBecker/elixir-ls][elixir-ls]]                                     | Yes                          |
   | Fortran               | [[https://github.com/hansec/fortran-language-server][fortran-language-server]]                   | Yes           | pip install fortran-language-server           |                              |
   | Go                    | [[https://github.com/saibing/bingo][bingo]]                                     | Yes           | [[https://github.com/saibing/bingo/wiki/Install][bingo]]                                         |                              |
   | Groovy                | [[https://github.com/palantir/language-servers][groovy-language-server]]                    | Yes           | [[https://github.com/palantir/language-servers][groovy-language-server]]                        |                              |
   | HTML                  | [[https://github.com/vscode-langservers/vscode-html-languageserver][html]]                                      | Yes           | npm install -g vscode-html-languageserver-bin |                              |
   | Haskell               | [[https://github.com/haskell/haskell-ide-engine][IDE engine]]                                | [[https://github.com/emacs-lsp/lsp-haskell][lsp-haskell]]   | [[https://github.com/haskell/haskell-ide-engine][IDE engine]]                                    |                              |
   | Java                  | [[https://github.com/eclipse/eclipse.jdt.ls][Eclipse JDT LS]]                            | [[https://github.com/emacs-lsp/lsp-java][lsp-java]]      | Automatic by [[https://github.com/emacs-lsp/lsp-java][lsp-java]]                         | Yes                          |
   | JavaScript/TypeScript | [[https://github.com/theia-ide/typescript-language-server][typescript-language-server]]  (recommended) | Yes           | npm i -g typescript-language-server           |                              |
   | JavaScript/TypeScript | [[https://github.com/sourcegraph/javascript-typescript-langserver][javascript-typescript-stdio]]               | Yes           | npm i -g javascript-typescript-langserver     |                              |
   | JavaScript Flow       | [[https://flow.org][flow]] (add-on if working on a Flow file)   | Yes           | [[https://flow.org][flow]]                                          |                              |
   | Ocaml                 | [[https://github.com/freebroccolo/ocaml-language-server][ocaml-language-server]]                     | Yes           | [[https://github.com/freebroccolo/ocaml-language-server][ocaml-language-server]]                         |                              |
   | PHP                   | [[https://github.com/felixfbecker/php-language-server][php-language-server]]                       | Yes           | [[https://github.com/felixfbecker/php-language-server][php-language-server]]                           |                              |
   | Python                | [[https://github.com/palantir/python-language-server][pyls]]                                      | Yes           | pip install 'python-language-server[all]'     | Yes                          |
   | Python(Microsoft)     | [[https://github.com/Microsoft/python-language-server][Microsoft Python Language Server]]          | [[https://github.com/andrew-christianson/lsp-python-ms/][lsp-python-ms]] | [[https://github.com/andrew-christianson/lsp-python-ms/][lsp-python-ms]]                                 | Yes                          |
   | Ruby                  | [[https://github.com/castwide/solargraph][solargraph]]                                | Yes           | gem install solargraph                        | Yes                          |
   | Rust                  | [[https://github.com/rust-lang-nursery/rls][rls]]                                       | Yes           | [[https://github.com/rust-lang-nursery/rls][rls]]                                           | Yes (via llvm debug adapter) |
   | Scala                 | [[https://github.com/rossabaker/lsp-scala][lsp-scala]]                                 | [[https://github.com/rossabaker/lsp-scala][lsp-scala]]     | [[https://github.com/rossabaker/lsp-scala][lsp-scala]]                                     |                              |
   | Swift                 | [[https://github.com/apple/sourcekit-lsp][sourcekit-LSP]]                             | [[https://github.com/emacs-lsp/lsp-sourcekit][lsp-sourcekit]] | [[https://github.com/apple/sourcekit-lsp][sourcekit-LSP]]                                 |                              |
   | Vue                   | [[https://github.com/vuejs/vetur/tree/master/server][vue-language-server]]                       | Yes           | npm install -g vue-language-server            |                              |
** Commands
   - ~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 buffer
   - ~lsp-goto-implementation~ - Go to implementation
   - ~lsp-goto-type-definition~ - Go to type definition
   - ~lsp-rename~ - Rename symbol at point
   - ~lsp-restart-workspace~ - Restart project
   - ~lsp-symbol-highlight~ - Highlight all relevant references to the symbol under point.
   - ~lsp-workspace-folders-add~ - Add workspace folder
   - ~lsp-workspace-folders-remove~ - Remove workspace folder
   - ~lsp-workspace-folders-switch~ - Switch workspace folder
   - ~imenu~ or ~helm-imenu~ - display document structure.
   - ~completion-at-point~ - display completion using built-in emacs ~completion-at-point~ framework.
   - ~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 file
   - ~lsp-lens-hide~ - Hide lenses in the current file
   - ~lsp-lens-mode~ (experimental) - Turn on/off lenses in the current file.
** Settings
   - ~lsp-print-io~ - If non-nil, print all messages to and from the language server to ~*Messages*~.
   - ~lsp-inhibit-message~ - If non-nil, inhibit the message echo via ~inhibit-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 configure ~lsp-mode~. When set to t ~lsp-mode~ will auto-configure ~lsp-ui~ and ~company-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 by ~document/onHover~ will be displayed. If ~lsp-markup-display-all~ is set to nil ~eldoc~ will show only the symbol information.
   - ~lsp-enable-completion-at-point~ - Enable ~completion-at-point~ integration.
   - ~lsp-enable-xref~ - Enable xref integration.
   - ~lsp-prefer-flymake~ - If you prefer flycheck and ~lsp-ui-flycheck~ is available, ~(setq lsp-prefer-flymake nil)~.
   - ~lsp-enable-indentation~ - Indent regions using the file formatting functionality provided by the language server.
   - ~lsp-enable-on-type-formatting~ - Enable ~textDocument/onTypeFormatting~ integration.
   - ~lsp-before-save-edits~ - If non-nil, ~lsp-mode~ will 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 of ~kind~, ~name~ or ~position~. 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.
** Screenshots
    - RUST Completion with company-lsp
     [[file:examples/completion.png]]
    - Typescript references using lsp-ui
     [[file:examples/references.png]]
    - Debugging Python using dap-mode
     [[file:examples/python_debugging.png]]
    - Call hierarchy via ccls
     [[file:examples/call-hierarchy-ccls.png]]
** Extensions
*** TRAMP (Experimental)
    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 [[https://github.com/eclipse/eclipse.jdt.ls][Eclipse JDT LS]]) cannot have local and remote servers.
    - The server must be using TCP connection or it should be converted to TCP via ~netcat~ or similar tool.
**** How it works?
     ~lsp-mode~ detects that a particular file is located on remote machine and looks for a clients which can handle the current major mode and it is marked as with ~:remote?~ t. Then ~lsp-mode~ starts the client and it expects to use TCP connection. Since not all of the server have TCP support ~netcat~ is used to convert STDIO to TCP using ~lsp-make-nc-tramp-command~.
     #+BEGIN_SRC bash
       nc -l -p {port} -c '{command}'
     #+END_SRC
     In case the server already supports TCP connection it could be used directly without ~netcat~ adapter.
**** Sample configuration
     Here it is example how you can configure python language server to work when using ~TRAMP~.
     #+BEGIN_SRC emacs-lisp
       (lsp-register-client
        (make-lsp-client :new-connection (lsp-tramp-connection
                                          (lsp-make-nc-tramp-command "pyls"))
                         :major-modes '(python-mode)
                         :remote? t
                         :server-id 'pyls-tramp))
     #+END_SRC
** Troubleshooting
   - set ~lsp-print-io~ to ~t~ to inspect communication between client and the server.
   - ~lsp-describe-session~ will show the current projects roots + the started severs and allows inspecting the server capabilities.
   #+caption: Describe session
   [file:examples/describe.png]]
** Adding support for languages
   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")~
   #+BEGIN_SRC emacs-lisp
     (lsp-register-client
      (make-lsp-client :new-connection (lsp-stdio-connection "pyls")
                       :major-modes '(python-mode)
                       :server-id 'pyls))
   #+END_SRC
** FAQ
   - How to configure a server with local variables?
     Add ~lsp~ server call to ~hack-local-variables-hook~ which runs right after the local variables are loaded.
     #+BEGIN_SRC emacs-lisp
       (add-hook 'hack-local-variables-hook
                 (lambda () (when (derived-mode-p 'XXX-mode) (lsp))))
     #+END_SRC
   - 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.el~ predefined servers have
     priority -1, lower than external packages (priority 0 if unspecified). If a
     server is registered with ~:add-on?~ flag set to ~t~ it will be started in
     parallel to the other servers that are registered for the current mode.
** See also
   - [[https://github.com/yyoncho/dap-mode][dap-mode]] - Debugger integration for ~lsp-mode~.
   - [[https://github.com/joaotavora/eglot][eglot]] - An alternative minimal LSP implementation.
