#+TITLE: LSP layer * Table of Contents :TOC_4_gh:noexport: - [[#description][Description]] - [[#features][Features:]] - [[#configuration][Configuration]] - [[#variables][Variables]] - [[#navigation-mode][Navigation mode]] - [[#extended-navigation-functions-for-derived-layers][Extended navigation functions for derived layers]] - [[#spacemacslsp-define-extensions-layer-name-kind-request-optional-extra-parameters][~spacemacs/lsp-define-extensions layer-name kind request &optional extra-parameters~]] - [[#spacemacslsp-bind-extensions-for-mode][~spacemacs/lsp-bind-extensions-for-mode~]] - [[#core-keybindings-for-derived-layers][Core keybindings for derived layers]] - [[#declared-prefixes][Declared prefixes]] - [[#navigation-prefixes][Navigation prefixes]] - [[#default-keybindings][Default keybindings]] - [[#diagnostics][Diagnostics]] - [[#future-additionsimprovements][Future additions/improvements]] - [[#make-spacemacslsp-bind-keys-for-mode-bind-conditionally][Make =spacemacs/lsp-bind-keys-for-mode= bind conditionally]] - [[#references][References]] * Description This layer adds support for basic language server protocol packages speaking [[https://microsoft.github.io/language-server-protocol/specification][language server protocol]]. Different language servers may support the language server protocol to varying degrees and they may also provide extensions; check the language server’s website for details. =M-x lsp-capabilities= in a LSP buffer to list capabilities of the server. ** Features: - Cross references (definitions, references, document symbol, workspace symbol search and others) - Workspace-wide symbol rename - Symbol highlighting - Flycheck - Completion with =company-lsp= - Signature help with eldoc - Symbol documentation in a child frame (=lsp-ui-doc=) - Navigation using imenu * Configuration The LSP ecosystem is based on two packages: [[https://github.com/emacs-lsp/lsp-mode][lsp-mode]] and [[https://github.com/emacs-lsp/lsp-ui][lsp-ui]]. Please check out their documentation. If you add =lsp-*-enable= to major mode hooks for auto initialization of language clients, customize =lsp-project-whitelist= =lsp-project-blacklist= to disable projects you don’t want to enable LSP. ** Variables A number of configuration variables have been exposed via the LSP layer =config.el=. Sensible defaults have been provided, however they may all be overridden in your .spacemacs, or dynamically using the bindings added under the derived mode t prefix by =(spacemacs/lsp-bind-keys-for-mode mode)= | Variable name | Default | Description | |---------------------------------+---------+-------------------------------------------------------------------------------------------| | =lsp-navigation= | `both' | `simple' or `peek' to bind xref OR lsp-ui-peek navigation functions | | =lsp-ui-remap-xref-keybindings= | nil | When non-nil, xref keybindings remapped to lsp-ui-peek-find-{definition,references} | | =lsp-ui-doc-enable= | t | When non-nil, the documentation overlay is displayed | | =lsp-ui-doc-include-signature= | nil | When nil, signature omitted from lsp-ui-doc overlay (this is usually redundant) | | =lsp-ui-sideline-enable= | t | When non-nil, the symbol information overlay is displayed | | =lsp-ui-sideline-show-symbol= | nil | When non-nil, the symbol information overlay includes symbol name (redundant for c-modes) | ** Navigation mode The ~lsp-navigation~ variable defined in =config.el= allows you to define a preference for lightweight or pretty (using =lsp-ui-peek=) source navigation styles. By default, the lightweight functions are bound under ~SPC m g~ and the =lsp-ui-peek= variants under ~SPC m G~. Setting ~lsp-navigation~ to either ~'simple~ or ~'peek~ eliminates the bindings under ~SPC m G~ and creates bindings under ~SPC m g~ according to the specified preference. *** Extended navigation functions for derived layers Some LSP server implementations provide extensions to the protocol, which can be leveraged using ~lsp-find-custom~ or ~lsp-ui-peek-find-custom~. A number of additional functions have been provided to facilitate wrapping these extensions in a manner consistent with the ~lsp-navigation~ setting. **** ~spacemacs/lsp-define-extensions layer-name kind request &optional extra-parameters~ Use this to define an extension to the lsp find functions. An example from the c-c++ layer: #+BEGIN_SRC elisp (spacemacs/lsp-define-extensions "c-c++" 'refs-address "textDocument/references" '(plist-put (lsp--text-document-position-params) :context '(:role 128))) #+END_SRC This defines the following interactive functions: - ~c-c++/find-refs-address~ - ~c-c++/peek-refs-address~ **** ~spacemacs/lsp-bind-extensions-for-mode~ Use this to bind one or more extensions under ~SPC m g~ and/or ~SPC m G~, as dictated by the value of ~lsp-navigation~. Using another example from the c-c++ layer: #+BEGIN_SRC elisp (spacemacs/lsp-bind-extensions-for-mode mode "c-c++" "&" 'refs-address "R" 'refs-read "W" 'refs-write "c" 'callers "C" 'callees "v" 'vars) #+END_SRC With ~lsp-navigation~ set to ~'both~ (the default), this is equivalent to: #+BEGIN_SRC elisp (spacemacs/set-leader-keys-for-major-mode mode "g&" 'c-c++/find-refs-address "gR" 'c-c++/find-refs-read "gW" 'c-c++/find-refs-write "gc" 'c-c++/find-callers "gC" 'c-c++/find-callees "gv" 'c-c++/find-vars "G&" 'c-c++/peek-refs-address "GR" 'c-c++/peek-refs-read "GW" 'c-c++/peek-refs-write "Gc" 'c-c++/peek-callers "GC" 'c-c++/peek-callees "Gv" 'c-c++/peek-vars) #+END_SRC whereas with ~lsp-navigation~ set to ~'peek~, this is equivalent to: #+BEGIN_SRC elisp (spacemacs/set-leader-keys-for-major-mode mode "g&" 'c-c++/peek-refs-address "gR" 'c-c++/peek-refs-read "gW" 'c-c++/peek-refs-write "gc" 'c-c++/peek-callers "gC" 'c-c++/peek-callees "gv" 'c-c++/peek-vars) #+END_SRC etc. ** Core keybindings for derived layers The ~spacemacs/lsp-bind-keys-for-mode mode~ function binds keys to a number of lsp features useful for all/most modes for the given major mode. It also declares some relevant keyboard shortcut prefixes. *** Declared prefixes The following prefixes have been declared: | prefix | name | functional area | |-----------+-------------+----------------------------------------------------------------------------| | ~SPC m =~ | format | Source formatting | | ~SPC m g~ | goto | Source navigation | | ~SPC m G~ | peek | Source navigation (lsp-ui-peek overlay) | | ~SPC m h~ | help | Help | | ~SPC m b~ | lsp/backend | Catchall. Restart LSP backend, other implementation-specific functionality | | ~SPC m r~ | refactor | What it says on the tin | | ~SPC m T~ | toggle | Toggle LSP backend features (documentation / symbol info overlays etc.) | **** Navigation prefixes The following prefixes have been declared under each of the navigation prefixes (i.e. ~SPC m g~ / ~SPC m G~) | prefix | name | functional area | |-----------------+------------------+----------------------------------------------------------| | ~SPC m h~ | hierarchy | Heirarchy (i.e. call/inheritance hierarchy etc. ) | | ~SPC m m~ | member hierarchy | Class/namespace members (functions, nested classes, vars | *** Default keybindings The default bindings are listed below. Derived language server layers should extend this list. | binding | function | |-------------+------------------------------------------------------------------------------| | ~SPC m = b~ | format buffer (lsp) | |-------------+------------------------------------------------------------------------------| | ~SPC m g t~ | goto type-definition (lsp) | | ~SPC m g k~ | goto viewport symbol (avy) | | ~SPC m g e~ | browse flycheck errors | | ~SPC m g M~ | browse file symbols (lsp-ui-imenu) | |-------------+------------------------------------------------------------------------------| | Note | /Replaced by the lsp-ui-peek equivalents when ~lsp-navigation~ == 'peek/ | | ~SPC m g i~ | find implementations (lsp) | | ~SPC m g d~ | find definitions (xref/lsp) | | ~SPC m g r~ | find references (xref/lsp) | | ~SPC m g s~ | find-workspace-symbol (lsp-ui) | | ~SPC m g p~ | goto previous (xref-pop-marker-stack) | |-------------+------------------------------------------------------------------------------| | Note | /Omitted when ~lsp-navigation~ == 'peek or 'simple/ | | | /Bound under ~SPC m g~ rather than ~SPC m G~ when ~lsp-navigation~ == 'peek/ | | ~SPC m G i~ | find implementation (lsp-ui-peek) | | ~SPC m G d~ | find definitions (lsp-ui-peek) | | ~SPC m G r~ | find references (lsp-ui-peek) | | ~SPC m G s~ | find-workspace-symbol (lsp-ui-peek) | | ~SPC m G p~ | goto previous (lsp-ui-peek stack - see Note 1) | | ~SPC m G n~ | goto next (lsp-ui-peek stack - see Note 1) | |-------------+------------------------------------------------------------------------------| | ~SPC m h h~ | describe thing at point | |-------------+------------------------------------------------------------------------------| | ~SPC m b r~ | lsp-restart-workspace | | ~SPC m b a~ | execute code action | | ~SPC m b c~ | lsp-capabilities | |-------------+------------------------------------------------------------------------------| | ~SPC m r r~ | rename | |-------------+------------------------------------------------------------------------------| | ~SPC m T d~ | toggle documentation overlay | | ~SPC m T F~ | toggle documentation overlay function signature | | ~SPC m T s~ | toggle symbol info overlay | | ~SPC m T S~ | toggle symbol info overlay symbol name | | ~SPC m T I~ | toggle symbol info overlay duplicates | Note 1: There is a window local jump list dedicated to cross references ** Diagnostics If some features do not work as expected, here is a common check list. - =M-x lsp-capabilities= If the LSP workspace is initialized correctly - =M-: xref-backend-functions= should be =(lsp--xref-backend)= for cross references - =M-: completion-at-point-functions= should be =(lsp-completion-at-point)= for completion * Future additions/improvements ** Make =spacemacs/lsp-bind-keys-for-mode= bind conditionally i.e. only bind keys if the language server supports the capability (queried using =lsp-capabilities=). =lsp-capabilities= uses current buffer to determine the language server, so this would probably entail adding the bindings dynamically in a mode hook. * References - [[https://github.com/emacs-lsp/lsp-mode][lsp-mode repo]] - [[https://github.com/emacs-lsp/lsp-ui][lsp-ui repo]]