== Adding support for new languages

Adding support for new languages/language servers is fairly straightforward:

[source,elisp]
----
(lsp-register-client
 (make-lsp-client :new-connection <connection-plist>
		  :major-modes '(<supported-major-modes>)
		  :server-id <server-id>))
----

=== Creating a connection
A `connection-plist` is a https://www.gnu.org/software/emacs/manual/html_node/elisp/Property-Lists.html[property list]
that tells `lsp-mode` how to launch and connect to a language server process.
For most language servers, you do not need to create an actual list yourself,
as helper functions <<lsp-stdio-connection, `lsp-stdio-connection`>> or
<<lsp-tcp-connection, `lsp-tcp-connection`>> can be used to create one.

==== Helper functions

[id="lsp-stdio-connection"]
===== Function: `lsp-stdio-connection COMMAND`
Returns a connection property list using `COMMAND`, for launching a language
server instance that sends and receives messages over standard I/O. `COMMAND`
can be:

* A string, denoting the command to launch the language server.
* A list of strings, denoting an executable with its command line arguments.
* A function, that either returns a string or a list of strings.

[id="lsp-tcp-connection"]
===== Function: `lsp-tcp-connection COMMAND-FN`

Returns a connection property list similar to <<lsp-stdio-connection, `lsp-stdio-connection`>>,
but `COMMAND-FN` can only be a function that takes a single argument, a
port number. It should return a command for launches a language server
process listening for TCP connections on the provided port.

=== Other arguments to `make-lsp-client`
* `:server-id`: A unique symbol that represents the client object created by
`make-lsp-client`. Examples include `'clangd`, `'pyls`, `'css-ls`, etc.
* `:major-modes`: A list of major-modes supported by the language server.
* `:activation-fn`: Function that returns `t` if the client can manage
  given buffer. It should take a single argument (the buffer object). Can be
  used instead of `:major-modes`.
* `:language-id`: Function that should take a single buffer as an argument,
  and return the https://microsoft.github.io/language-server-protocol/specification#textdocumentitem[language identifier]
  (`languageId`) for that buffer.
* `:add-on`: If non-nil, the client will be started even when there is another
  server handling the same mode/buffer.
* `:ignore-regexps`: A list of regular expressions. If any incoming data from
  the language server matches any of these regexps, it will be ignored. This
  is useful for filtering out unwanted messages, such as servers that send
  extraneous non-LSP messages.
* `:notification-handlers`: Hash table mapping notification method strings
  to functions handling them. See: <<Method handlers>>.
* `:request-handlers`: Hash table mapping request method strings to functions
  handling them. See: <<Method handlers>>.
* `:prefix-function`: A prefix function takes no arguments, and return the
  bounds for the entity under point as a cons pair (START . END), where both
  `START` and `END` are point values. The prefix function is used to compute
  the bounds for the entity being completed during completion, specifically,
  the `start` and `end` values in the list returned by https://www.gnu.org/software/emacs/manual/html_node/elisp/Completion-in-Buffers.html[Completion functions].
* `:uri-handlers`: Hash table mapping non-standard file URI schemes to a
  function that opens the file pointed to by the URI. The function should
  accept a single string (the file URI).
* `:action-handlers`: Hash table mapping code action strings to a function
  that executes them. While executing a code action, it is used to determine
  whether a particular code action should be executed by a client, or sent to
  the server. The function should take a single string (the code action)
  as an argument.
* `:multi-root`: Non-nil if the client supports multi-root workspaces.
* `:initialization-options`: A JSON-encodable object, or a function that
  returns one. The value will be used for additional initialization options
  for the https://microsoft.github.io/language-server-protocol/specification#initialize[`initialize`]
  request.
* `before-file-open-fn`: Function called before a LSP-managed file (by this
  client) is opened. Should accept a single argument, the currently active
  workspace.
* `initialized-fn`: Function called right after a workspace has been
  initialized. Should accept a single argument, the newly initialized
  workspace.
* `completion-in-comments?`: Non-nil if the client supports completion within
  comments.

=== Method handlers
A method handler is a function that takes two arguments, a `lsp--workspace`
object and the method parameters as a deserialized object. A defined client
can use method handlers to support language specific features that aren't
specified in the official LSP specification. For instance, method handlers
are used by the `lsp-rust` rls client to support https://github.com/rust-lang/rls/blob/master/contributing.md#extensions-to-the-language-server-protocol[progress indicators]
sent from the server to the editor:
[source,elisp]
----
(defun lsp-clients--rust-window-progress (_workspace params)
  ;; Minimal implementation - we could show the progress as well.
  (lsp-log (gethash "title" params)))
(defvar lsp-rust-notification-handlers (make-hash-table :test 'equal))
(puthash "window/progress" #'lsp-clients--rust-window-progress lsp-rust-notification-handlers)

(lsp-register-client
 (make-lsp-client :notification-handlers lsp-rust-notification-handlers
		  <other-arguments>))
----
