Adding support for languages#
Register a server#
Your language server must be registered with lsp-mode
in order for the lsp
command to figure out how to communicate with it. This section explains how to
do that.
The language being used is identified by either an Emacs major mode or by a regular expression matching the buffer's filename. A language server matching that language is then started.
Here's a minimal example using Python. First we tell lsp-mode
that buffers in
python-mode
correspond to the language "python"
:
(add-to-list 'lsp-language-id-configuration '(python-mode . "python"))
If there is no major mode corresponding to your language, or the major mode is
not sufficient to determine the language (e.g. web-mode
is used for
javascript
, html
, and css
) you can register it using a regular expression
that matches the filename instead:
(add-to-list 'lsp-language-id-configuration '(".*\\.svelte$" . "svelte"))
Note: If adding support directly in the lsp-mode.el
source obviously you
should modify lsp-language-id-configuration
directly instead of calling
add-to-list
.
Now we tell lsp-mode
how to start the pyls
language server when a buffer
uses the "python"
language:
(lsp-register-client (make-lsp-client
:new-connection (lsp-stdio-connection "pyls")
:activation-fn (lsp-activate-on "python")
:server-id 'pyls))
There are many more options for the client (see the lsp-client
struct
which documents each option) but what we've shown above is the minimal required
configuration. One common case, setting environment variables for the server,
is shown below.
Note: In the above example, when a new client is created using
make-lsp-client
, a new connection to the language server is created
using lsp-stdio-connection
. Please carefully check its
documentation, as the function checks for various things (e.g. testing
for the executable in PATH) and handles respective errors. Often
while adding a server, the LSP client author might do these checks
themselves, but without handling the errors correctly. This leads to
features like lsp-install-server
breaking for other users; e.g. see
this issue. This
is a common mistake that keeps reoccurring.
Here's an example of how to set up a custom language server in your init.el
file:
;; Use shopify-cli / theme-check-language-server for Shopify's liquid syntax.
(with-eval-after-load 'lsp-mode
(add-to-list 'lsp-language-id-configuration
'(shopify-mode . "shopify"))
(lsp-register-client
(make-lsp-client :new-connection (lsp-stdio-connection "theme-check-language-server")
:activation-fn (lsp-activate-on "shopify")
:server-id 'theme-check)))
Note: This example assumes that you've already set up a major mode of your own either by deriving it from web-mode
or perhaps by writing it yourself.
If the language server supports environment variables to control
additional behavior, you can register that by using the
:environment-fn
option, like the Bash language client does:
(lsp-register-client
(make-lsp-client :new-connection (lsp-stdio-connection '("bash-language-server" "start"))
:activation-fn (lsp-activate-on "shellscript")
:priority -1
:environment-fn (lambda ()
'(("EXPLAINSHELL_ENDPOINT" . lsp-bash-explainshell-endpoint)
("HIGHLIGHT_PARSING_ERRORS" . lsp-bash-highlight-parsing-errors)))
:server-id 'bash-ls))
lsp-bash-explainshell-endpoint
and lsp-bash-highlight-parsing-errors
are language client defcustom
that expose supported server environment
settings in a type-safe way. If you change any of those variables,
restart the language server with lsp-workspace-restart
for the changes
to be applied.
Also, if your client supports customizing the language server path it's recommended to make a wrapper function so the user can customize the value even after the client has been loaded. For example:
(defcustom lsp-tex-executable "digestif"
"Command to start the Digestif language server."
:group 'lsp-tex
:risky t
:type 'file)
(lsp-register-client
(make-lsp-client
;; instead of `:new-connection (lsp-stdio-connection lsp-tex-executable)` use
:new-connection (lsp-stdio-connection (lambda () lsp-tex-executable))
:activation-fn (lsp-activate-on "plaintex" "latex")
:priority -1
:server-id 'digestif))
Sections#
lsp-mode
provides tools to bridge emacs defcustom
as a language
configuration sections properties (see specification
workspace/configuration). In addition you may use lsp-generate-settings
from the Generate Settings script to generate lsp-defcustom
from the package.json
VScode plugin manifest. Example:
(lsp-defcustom lsp-foo-language-server-property "bar"
"Demo property."
:group 'foo-ls
:lsp-path "foo.section.property")
(lsp-configuration-section "foo")
;; => (("foo" ("settings" ("property" . "bar"))))
Documentation#
- Add the new language server to the lsp-clients.json file sorted by the
full-name
key alphabetically. - Create a new navigation entry in mkdocs.yml file.